使用Angular2中的Karma启用按钮时的单元测试

时间:2017-01-09 09:02:36

标签: unit-testing angular karma-jasmine angular-cli

我使用角度CLI进行Angular2项目设置。我正在尝试测试表单组件。它有两个字段:电子邮件和密码。两者都是required。有一个submit类型的登录按钮。只有在用户在两个字段中都提供了有效输入后才能启用它。

<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>

现在,我想用业力来测试按钮。我浏览了文档,并通过在测试和验证过程中提供随机输入来测试输入:

//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 = 'raj@gmail.com';//valid
   userEmail.dispatchEvent(new Event('change'));

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

});

我不明白测试失败的原因。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:7)

如果您查看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

你可以注意到你的错误主要是错误的事件名称。

您必须使用input事件代替change

it('should check loginBtn is enabled after inputs check out', async(() => {
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    userEmail.value = 'raj@gmail.com';
    userEmail.dispatchEvent(new Event('input'));

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

<强> Plunker Example