我正在为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();
});
});
});
});
发送点击的测试&#39;来自按钮的事件通过,但是从输入元素调度keydown事件的测试(当前已禁用)失败。
我可以发送一个不同的事件来触发表单的ngSubmit处理程序来触发吗?
答案 0 :(得分:2)
尝试使用 angular.module("demo", []);
angular
.module("demo")
.controller("demoController", ["$scope", function($scope) {
$scope.users = shuffleArray([{
name: "John",
age: 22,
value: false,
color: "green"
}, {
name: "Leo",
age: 54,
value: false,
color: "blue"
}, {
name: "Matt",
age: 35,
value: false,
color: "red"
}]);
function shuffleArray(array){
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
$scope.changeValue = function(obj){
obj.value = !obj.value;
};
}])
代替&#39; keydown`
keypress
答案 1 :(得分:0)
(迟到的答案,但我在这里没有看到被接受的答案) 仅仅调度事件是不够的,您还必须将事件发送给组件。所以在你的例子中,你只有一个表单提交,所以你 需要调用:
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 :(得分:-1)
尝试获取表单元素并调用triggerEventHandler,以触发提交事件
let formElement: DebugElement;
formElement= fixture.debugElement.query(By.css('form'));
formElement.triggerEventHandler('ngSubmit', null);