web-dev-qa-db-fra.com

Test unitaire lorsqu'un bouton est activé à l'aide de Karma dans Angular2

J'ai une configuration de projet Angular2 utilisant angular CLI. J'essaie de tester un composant de formulaire. Il a deux champs: email et mot de passe. Les deux sont required. Il y a une connexion bouton de type submit. Il n'est activé qu'après que l'utilisateur a fourni des entrées valides dans les deux champs.

<form (ngSubmit)="login()" #loginForm="ngForm">

        <md-input-container class="md-block">
            <input md-input [(ngModel)]="user.email" class="userEmail"
                name="userEmail" type="email" placeholder="Email" 
                ngControl="userEmail" 
            required>
        </md-input-container>
        <br>

        <md-input-container class="md-block">
            <input md-input [(ngModel)]="user.password" class="userPassword"
                name="userPassword" type="password" placeholder="Password" 
                ngControl="userPassword" 
            required>
        </md-input-container>
        <br>



        <!--the button is enabled only after all form fields are valid-->
        <button  color="primary" md-button 
            type="submit" class='loginButton'
        [disabled]="!loginForm.form.valid">
            Login
         </button>

Maintenant, je veux tester le bouton en utilisant le karma. J'ai parcouru les documents et j'ai pu tester l'entrée, en donnant une entrée aléatoire pendant le test et en la vérifiant:

//imports...

describe('LoginComponent (inline template)', () => {
  let comp:    LoginComponent;
  let fixture: ComponentFixture<TmLoginComponent>;
  let userEmail: HTMLInputElement;
  let userPassword: HTMLInputElement;
  let loginBtn: HTMLElement;
  let title: HTMLElement;



  beforeEach(() => {

    TestBed.configureTestingModule({
      declarations: [ LoginComponent ], // declare the test component
      imports: [ MaterialModule.forRoot(), FormsModule, 
                  RouterTestingModule.withRoutes(
                  [{path: 'login', component: LoginComponent}, ])
                ],
      providers: [{provide: UserAuthenticationService, useValue: uaServiceStub }, CookieService],

    });

    fixture = TestBed.createComponent(LoginComponent);

    comp = fixture.componentInstance; //LoginComponent test instance

    // query by CSS element selector
    userEmail = fixture.debugElement.query(By.css('.userEmail')).nativeElement;
    userPassword = fixture.debugElement.query(By.css('.userPassword')).nativeElement;
    loginBtn = fixture.debugElement.query(By.css('.loginButton')).nativeElement;


//tests

//this test is successful
  it('should check initial input', () => {
    fixture.detectChanges();
    expect(userEmail.value).toBe('')
  });

//this test is successful
  it('should check later input', async(() => {    
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      userEmail.value = 'someValue';
      userEmail.dispatchEvent(new Event('change'));

      expect(userEmail.value).toBe('someValue');
    });

  }));

//EDITED: NEW TEST
it('should check loginBtn is disabled initially', () => {
  fixture.detectChanges();
  loginBtn =   fixture.debugElement.query(By.css('.loginButton')).nativeElement;
  fixture.whenStable().then(() => {
    expect(loginBtn.disabled).toBe(true)
   })
 });


//this test fails. "Expected true to be false"
  it('should check loginBtn is enabled after inputs check out', async(() => {
   fixture.detectChanges();
   fixture.whenStable().then(() => {
   userEmail.value = '[email protected]';//valid
   userEmail.dispatchEvent(new Event('change'));

   userPassword.value = 'asdf';//vaild
   userPassword.dispatchEvent(new Event('change'));
   fixture.detectChanges();
   expect(loginBtn.disabled).toBe(false)
  })
 }));

});

Je ne vois pas pourquoi le test échoue. Quelqu'un peut-il aider?

11
Snowman

Si vous jetez un œil au code source de DefaultValueAccessor:

Host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},

https://github.com/angular/angular/blob/2.4.2/modules/%40angular/forms/src/directives/default_value_accessor.ts#L36

vous pouvez remarquer que votre erreur principale est un nom d'événement incorrect.

Vous devez utiliser input événement au lieu de change

it('should check loginBtn is enabled after inputs check out', async(() => {
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    userEmail.value = '[email protected]';
    userEmail.dispatchEvent(new Event('input'));

    userPassword.value = 'asdf';
    userPassword.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    expect(loginBtn.disabled).toBe(false)
  });
}));

Exemple Plunker

8
yurzui