jeudi 11 janvier 2018

Angular testing and ngModel

I'm writing one of my first component test with Angular and I have some difficulties to make the ngModel binding work. Here is my test module definition:

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        LdapLoginComponent,
      ],
      imports: [
        CommonModule,
        FormsModule,
        NoopAnimationsModule,
        MatInputModule,
        MatFormFieldModule,
        RouterTestingModule,
      ],
      providers: [
        {
          provide: AuthorizationService,
          useValue: { login() {} },
        },
      ]
    }).compileComponents();
  }));

And here my test case:

  it('should subscribe to the login observable with the credentials', fakeAsync(() => {
    // Given
    const username = 'username';
    const password = 'password';
    const expectedNavigation = ['/'];
    const expectedProvider = AuthorizationProvider.LDAP;
    const submitButton = de.query(By.css('button[type=submit]')).nativeElement;
    const usernameField: HTMLInputElement = de.query(By.css('input[name=username]')).nativeElement;
    const passwordField: HTMLInputElement = de.query(By.css('input[name=password]')).nativeElement;
    const authorizationService = fixture.debugElement.injector.get(AuthorizationService);
    const router = fixture.debugElement.injector.get(Router);
    const loginSpy = spyOn(authorizationService, 'login').and.returnValue(Observable.of(true));
    const navigateSpy = spyOn(router, 'navigate');
    comp.username = username;
    usernameField.dispatchEvent(new Event('input'));
    comp.password = password;
    passwordField.dispatchEvent(new Event('input'));
    tick();
    fixture.detectChanges();

    // When
    submitButton.click();

    // Then
    expect(fixture).toBeTruthy();
    expect(loginSpy).toHaveBeenCalledWith(expectedProvider, username, password);
    expect(navigateSpy).toHaveBeenCalledWith(expectedNavigation);
  }));

My component class:

export class LdapLoginComponent {

  username: string;
  password: string;
  errorMessage: string;
  submitDisabled = false;

  constructor(
    private authorizationService: AuthorizationService,
    private router: Router,
  ) {
  }

  login(): void {
    delete this.errorMessage;
    this.submitDisabled = true;
    this.authorizationService.login(AuthorizationProvider.LDAP, this.username, this.password)
      .subscribe(
        () => {
          this.router.navigate(['/']);
        },
        (err: Error) => {
          this.errorMessage = err.message;
          this.submitDisabled = false;
        },
      );
  }

}

And my component template:

<form class="form-container" (submit)="login()">
    <input
    type="text"
    name="username"
    placeholder="Insert your username"
    [(ngModel)]="username"
    required
    i18n-placeholder="@@input.placeholder.username">
    <input
      type="password"
      name="password"
      placeholder="Insert your password"
      [(ngModel)]="password"
      required
      i18n-placeholder="@@input.placeholder.password">
  <button
    type="submit"
    color="warn"
    [disabled]="submitDisabled"
    i18n="@@input.submit">Submit</button>
</form>

I'm changing the value of the username and password fields inside my test and I'm expecting the username and password fields of my class to be updated accordingly. Everything works well if I test manually in my browser, but not in the test.

Any ideas ?

Thanks.

Aucun commentaire:

Enregistrer un commentaire