如何测试输入元素的输入?
How to test typing to an input element?
我正在尝试 'typing' 测试输入元素。我的目标是在输入元素中放入一些值,并查看其绑定是否具有输入值,以及查看我在输入元素中输入的值。
代码:
app.component:
import { Component } from "@angular/core";
@Component({
selector: "my-app",
template: `
<span>My input: </span>
<input name="name-input" placeholder="Enter name" [(ngModel)]="name" />
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "";
}
测试:
import { TestBed } from "@angular/core/testing";
import { FormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";
describe("AppComponent", () => {
var fixture: any;
var app: AppComponent;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [FormsModule]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
app = fixture.componentInstance;
});
it("should create the app", () => {
expect(app).toBeTruthy();
});
it("should type text into input element", () => {
let inputElement = fixture.nativeElement.querySelector(
`input[name='name-input']`
);
inputElement.value = "someValue";
inputElement.dispatchEvent(new Event("input"));
fixture.detectChanges();
expect(app.name).toBe("someValue");
});
});
行后:
inputElement.value = "someValue";
inputElement.dispatchEvent(new Event("input"));
fixture.detectChanges();
预期:app.name 等于“someValue”。
找到:app.name 等于空字符串:"".
证明它不起作用的 stackblitz:
https://stackblitz.com/edit/Whosebug-input-question1q2w3e?
你应该调度一个 KeyboardEvent
on the HTMLInputElement
within a fakeAsync
区域。
您的单元测试将如下所示:
it('#keydown should update app#name', fakeAsync(() => {
// given
let inputElement = fixture.nativeElement.querySelector(`input[name='name-input']`);
// when
let event = new KeyboardEvent('keydown', { key: 'x' });
inputElement.dispatchEvent(event);
tick();
// then
expect(app.name).toBe("x");
}));
我相信您正在寻找的是以下代码:
it("should type text into input element after the view has been done initializing", () => {
fixture.detectChanges(); // ngOnInit Lifecycle hook is run here
let inputElement = fixture.nativeElement.querySelector(
`input[name='name-input']`
);
inputElement.value = "someValue";
inputElement.dispatchEvent(new Event("input"));
fixture.detectChanges();
expect(app.name).toBe("someValue");
});
现在,为什么这样做有效?
根据official documentation,当你运行 fixture.detectChanges()
第一次时,ngOnInit()
生命周期钩子被调用,这是错误的关键。
您正在 ngOnInit()
之外设置值,但是,初始化视图的生命周期挂钩尚未 运行。这意味着当您第一次调用 fixture.detectChanges()
时,它会调用 ngOnInit()
生命周期挂钩。然后将视图重新初始化为其原始状态,恢复之前所做的所有更改(如设置输入值)。
亲切的问候。
我正在尝试 'typing' 测试输入元素。我的目标是在输入元素中放入一些值,并查看其绑定是否具有输入值,以及查看我在输入元素中输入的值。
代码:
app.component:
import { Component } from "@angular/core";
@Component({
selector: "my-app",
template: `
<span>My input: </span>
<input name="name-input" placeholder="Enter name" [(ngModel)]="name" />
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "";
}
测试:
import { TestBed } from "@angular/core/testing";
import { FormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";
describe("AppComponent", () => {
var fixture: any;
var app: AppComponent;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [FormsModule]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
app = fixture.componentInstance;
});
it("should create the app", () => {
expect(app).toBeTruthy();
});
it("should type text into input element", () => {
let inputElement = fixture.nativeElement.querySelector(
`input[name='name-input']`
);
inputElement.value = "someValue";
inputElement.dispatchEvent(new Event("input"));
fixture.detectChanges();
expect(app.name).toBe("someValue");
});
});
行后:
inputElement.value = "someValue";
inputElement.dispatchEvent(new Event("input"));
fixture.detectChanges();
预期:app.name 等于“someValue”。 找到:app.name 等于空字符串:"".
证明它不起作用的 stackblitz: https://stackblitz.com/edit/Whosebug-input-question1q2w3e?
你应该调度一个 KeyboardEvent
on the HTMLInputElement
within a fakeAsync
区域。
您的单元测试将如下所示:
it('#keydown should update app#name', fakeAsync(() => {
// given
let inputElement = fixture.nativeElement.querySelector(`input[name='name-input']`);
// when
let event = new KeyboardEvent('keydown', { key: 'x' });
inputElement.dispatchEvent(event);
tick();
// then
expect(app.name).toBe("x");
}));
我相信您正在寻找的是以下代码:
it("should type text into input element after the view has been done initializing", () => {
fixture.detectChanges(); // ngOnInit Lifecycle hook is run here
let inputElement = fixture.nativeElement.querySelector(
`input[name='name-input']`
);
inputElement.value = "someValue";
inputElement.dispatchEvent(new Event("input"));
fixture.detectChanges();
expect(app.name).toBe("someValue");
});
现在,为什么这样做有效?
根据official documentation,当你运行 fixture.detectChanges()
第一次时,ngOnInit()
生命周期钩子被调用,这是错误的关键。
您正在 ngOnInit()
之外设置值,但是,初始化视图的生命周期挂钩尚未 运行。这意味着当您第一次调用 fixture.detectChanges()
时,它会调用 ngOnInit()
生命周期挂钩。然后将视图重新初始化为其原始状态,恢复之前所做的所有更改(如设置输入值)。
亲切的问候。