在 Angular 单元测试中使用回车键提交表单
Posted
技术标签:
【中文标题】在 Angular 单元测试中使用回车键提交表单【英文标题】:Submitting form with enter key in Angular unit test 【发布时间】:2018-02-27 14:32:19 【问题描述】:我正在为作为登录表单的 Angular 4 组件编写测试。可以通过单击“提交”按钮或在任何输入字段中按 Enter 来提交表单。此行为由 Angular 表单指令规定。
我可以编写一个测试用例来验证按钮单击是否提交表单,但我无法通过按键事件触发提交行为。
模板:
<form (ngSubmit)="onLoginSubmit()" #loginForm="ngForm">
<div class="form-group">
<label for="userid">User ID</label>
<input type="text" class="form-control" name="userid" id="userid" required
[(ngModel)]="model.userId" #userid="ngModel">
<div [hidden]="userid.valid || userid.untouched" class="alert alert-danger">
User ID is required
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" id="password" required
[(ngModel)]="model.password" #password="ngModel">
<div [hidden]="password.valid || password.untouched" class="alert alert-danger">
Password is required
</div>
</div>
<button type="submit" class="btn btn-success" [disabled]="loginForm.form.invalid">Submit</button>
规格:
import ComponentFixture, TestBed from '@angular/core/testing';
import By from '@angular/platform-browser';
import DebugElement, Component, ViewChild from '@angular/core';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import Observable from 'rxjs/Observable';
import LoginFormComponent from './login-form.component';
import ILoginService from '../../service/ILoginService';
import IAuthService from '../../service/IAuthService';
describe('Login Form', () =>
let comp: LoginFormComponent;
let fixture: ComponentFixture<LoginFormComponent>;
let userIdElement: DebugElement;
let passwordElement: DebugElement;
let submitElement: DebugElement;
beforeEach(() =>
TestBed.configureTestingModule(
imports: [FormsModule, ReactiveFormsModule],
declarations: [LoginFormComponent],
providers: [
provide: 'IloginService', useClass: UserServiceMock ,
provide: 'IAuthService', useClass: MockAuthService ]
);
fixture = TestBed.createComponent(LoginFormComponent);
comp = fixture.componentInstance;
userIdElement = fixture.debugElement.query(By.css('input[name=userid]'));
passwordElement = fixture.debugElement.query(By.css('input[name=password]'));
submitElement = fixture.debugElement.query(By.css('button'));
);
describe('Submit', () =>
let authService: IAuthService;
let authServiceSpy: jasmine.Spy;
let loginService: ILoginService;
let loginServiceSpy: jasmine.Spy;
beforeEach(() =>
comp.model.userId = 'mock user';
comp.model.password = 'mock password';
comp.loginUrl = 'mock url';
authService = fixture.debugElement.injector.get('IAuthService');
authServiceSpy = spyOn(authService, 'login').and.returnValue(null);
loginService = fixture.debugElement.injector.get('IloginService');
loginServiceSpy = spyOn(loginService, 'handleLoginResult');
);
it('should invoke the auth and login services when submit is clicked', () =>
submitElement.nativeElement.click();
);
xit('should submit the form on enter key pressed in userId input', () =>
userIdElement.nativeElement.dispatchEvent(new KeyboardEvent('keydown', key: 'Enter' ))
);
xit('should submit the form on enter key pressed in password input', () =>
passwordElement.nativeElement.dispatchEvent(new KeyboardEvent('keydown', key: 'Enter' ))
);
afterEach(() =>
fixture.detectChanges();
fixture.whenStable().then(() =>
expect(authService.login).toHaveBeenCalledWith('mock user', 'mock password', 'mock url');
expect(loginService.handleLoginResult).toHaveBeenCalled();
);
);
);
);
从按钮分派“click”事件的测试通过,但从输入元素分派 keydown 事件的测试(当前已禁用)失败。
我可以分派不同的事件来触发表单的 ngSubmit 处理程序吗?
【问题讨论】:
你找到答案了吗? 【参考方案1】:(迟到的答案,但我在这里没有看到被接受的答案) 仅调度事件是不够的,您还必须将事件发送到组件。所以在你的例子中,你只有一个表单提交,所以你 需要打电话:
component.onLoginSubmit();
但是要分离出逻辑,也许有一个主机侦听器正在为您工作:
@HostListener('keypress.enter', ['$event'])
keypressEnter(event: KeyboardEvent)
// Maybe some further logic due to keys? Validation?
this.onLoginSubmit();
那么在你的测试中你还必须调用:
component.keypressEnter(new KeyboardEvent('keypress', key: 'Enter' ));
最后,fixture.detectChanges() 将完成占空比。
单独调用 dispatch 事件是行不通的。
【讨论】:
【参考方案2】:尝试使用keypress
而不是'keydown`
new KeyboardEvent('keypress', key: 'Enter' )
【讨论】:
感谢您的建议,但 'keypress' 并不比 'keydown' 或 'keyup' 好用以上是关于在 Angular 单元测试中使用回车键提交表单的主要内容,如果未能解决你的问题,请参考以下文章