我正在尝试测试包含文本输入元素的组件。我想验证当文本输入的值更改时组件的状态按预期更改。当然,文本输入使用ngModel指令(双向绑定)。
虽然组件在运行时工作正常,但我在创建有效的传递测试时遇到了麻烦。我发布了我认为应该在下面工作的内容,以及之后的测试结果。
我做错了什么?
TEST:
import {Component} from 'angular2/core';
import {describe, it, injectAsync, TestComponentBuilder} from 'angular2/testing';
import {FORM_DIRECTIVES} from 'angular2/common';
import {By} from 'angular2/platform/common_dom';
class TestComponent {
static get annotations() {
return [
new Component({
template: '<input type="text" [(ngModel)]="name" /><p>Hello {{name}}</p>',
directives: [FORM_DIRECTIVES]
})
]
}
}
describe('NgModel', () => {
it('should update the model', injectAsync([TestComponentBuilder], tcb => {
return tcb
.createAsync(TestComponent)
.then(fixture => {
fixture.nativeElement.querySelector('input').value = 'John';
const inputElement = fixture.debugElement.query(By.css('input'));
inputElement.triggerEventHandler('input', { target: inputElement.nativeElement });
fixture.detectChanges();
expect(fixture.componentInstance.name).toEqual('John');
});
}));
});
输出:
Chrome 45.0.2454 (Mac OS X 10.10.5) NgModel should update the model FAILED
Expected undefined to equal 'John'.
at /Users/nsaunders/Projects/ng2-esnext-seed/src/test/ngmodel.spec.js!transpiled:41:52
at ZoneDelegate.invoke (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:322:29)
at Zone.run (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:218:44)
at /Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:567:58
at ZoneDelegate.invokeTask (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:355:38)
at Zone.runTask (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:254:48)
at drainMicroTaskQueue (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:473:36)
at XMLHttpRequest.ZoneTask.invoke (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:425:22)
答案 0 :(得分:10)
这是一种方法:
import {Component} from 'angular2/core';
import {describe, it, inject, fakeAsync, tick, TestComponentBuilder} from 'angular2/testing';
import {FORM_DIRECTIVES} from 'angular2/common';
class TestComponent {
static get annotations() {
return [
new Component({
template: '<input type="text" [(ngModel)]="name" /><p>Hello {{name}}</p>',
directives: [FORM_DIRECTIVES]
})
]
}
}
describe('NgModel', () => {
it('should update the model', inject([TestComponentBuilder], fakeAsync(tcb => {
let fixture = null;
tcb.createAsync(TestComponent).then(f => fixture = f);
tick();
fixture.detectChanges();
let input = fixture.nativeElement.querySelector('input');
input.value = 'John';
let evt = document.createEvent('Event');
evt.initEvent('input', true, false);
input.dispatchEvent(evt);
tick(50);
expect(fixture.componentInstance.name).toEqual('John');
})));
});
答案 1 :(得分:3)
NgModel侦听input
事件以获得有关更改的通知:
dispatchEvent(inputElement, "input");
tick();
对于其他输入元素,可能会使用其他事件(复选框,广播,选项......)。
答案 2 :(得分:1)
我这样处理:
import {TestBed, ComponentFixture, async} from "@angular/core/testing";
import {dispatchEvent} from "@angular/platform-browser/testing/browser_util";
import {FormsModule} from "@angular/forms";
import {By} from "@angular/platform-browser";
import {DebugElement} from "@angular/core";
describe('my.component', () => {
let comp: MyComp,
fixture: ComponentFixture<MyComp>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule],
declarations: [
MyComp
]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(MyComp);
comp = fixture.componentInstance;
fixture.detectChanges();
});
})
);
it('should handle inputs', () => {
const sendInputs = (inputs: Array<DebugElement>) => {
inputs.forEach(input => {
dispatchEvent(input.nativeElement, 'input');
});
fixture.detectChanges();
return fixture.whenStable();
};
let inputs: Array<DebugElement> = fixture.debugElement.queryAll(By.css('input'));
// set username input value
inputs[0].nativeElement.value = "Username";
// set email input value
inputs[1].nativeElement.value = "Email";
sendInputs(inputs).then(() => {
// emit click event to submit form
fixture.nativeElement.querySelectorAll('button')[0].click();
expect(comp.username).toBe("Username");
expect(comp.email).toBe("Email");
});
});
});
我的html有点像这样:
<form (ngSubmit)="submit()">
<input type="text" name="username" class="form-control" placeholder="username" required [(ngModel)]="username">
<input type="email" name="email" class="form-control" placeholder="email" required [(ngModel)]="email">
<button type="submit" class="btn btn-primary block full-width m-b">Submit</button>
</form>
我还建议查看角度源代码测试,这对我有很多帮助:Forms tests