J-m*_*man 6 unit-testing jasmine typescript angular angular-reactive-forms
我有一个更改函数,该函数将传递给反应形式控件的更改事件的更改事件,该控件评估脏状态并检查控件上是否有任何错误,如果是,则将布尔标志设置为true / false。然后,此布尔标志用于确定是否显示<div>具有错误消息的元素。这在浏览器中可以正常工作,但是在运行单元测试时,永远不会将“ dirty”设置为true。这是我的代码:
的HTML
<form [formGroup]="myForm" novalidate>
<input id="age" formControlName="age" (change)="onChange()" />
<div id="ageError" *ngIf="ageIsError()">
<label>Age has errored</label>
</div>
</form>
Run Code Online (Sandbox Code Playgroud)
零件
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({
age: [null, [Validators.min(18)]]
});
}
onChange() {
if (this.ageIsError())
// do something
}
ageIsError() {
return this.myForm.controls.age.hasError('min') &&
this.myForm.controls.age.dirty;
}
Run Code Online (Sandbox Code Playgroud)
单元测试
it('should show error message when age is less than 18', fakeAsync(() => {
let age = component.myForm.controls.age;
age.setValue('10', { emitEvent: true });
fixture.detectChanges();
fixture.whenStable().then(() => {
let ageError = debugElement.query(By.css('#ageError')).nativeElement;
expect(component.ageIsError()).toBe(true);
expect(ageError.innerText).toContain('Age has errored');
});
}));
Run Code Online (Sandbox Code Playgroud)
同样,实际的实现在浏览器中也有效,但是单元测试失败。有谁知道要在茉莉花中发出事件以将控件设置为脏状态,还是有更好的方法来实现?谢谢!
在您的示例中,age.setValue(...)实际上为输入设置了正确的值,但它不会附加ageError到 DOM - 因为没有真实/模拟事件将控件标记为脏。这就是为什么在这种情况下该方法ageIsError总是返回的原因。false
作为一种解决方法,我只是使用模拟输入事件document.createEvent('Event'),看起来效果很好:
it('should show error message when age is less than 18', async(() => {
const customEvent: Event = document.createEvent('Event');
customEvent.initEvent('input', false, false);
const ageInput = fixture.debugElement.query(By.css('input#age')).nativeElement;
ageInput.value = 10;
ageInput.dispatchEvent(customEvent);
fixture.detectChanges();
fixture.whenStable().then(() => {
let ageError = fixture.debugElement.query(By.css('#ageError')).nativeElement;
expect(component.ageIsError()).toBe(true);
expect(ageError.innerText).toContain('Age has errored');
});
}));
Run Code Online (Sandbox Code Playgroud)
我还找到了您的解决方案的修复方法 - 只需age.markAsDirty()之前调用即可detectChanges:
it('should show error message when age is less than 18', async(() => {
let age = component.myForm.controls.age;
age.setValue('10'); // { emitEvent: true } is by default
age.markAsDirty(); // add this line
fixture.detectChanges();
fixture.whenStable().then(() => {
let ageError = fixture.debugElement.query(By.css('#ageError')).nativeElement;
expect(component.ageIsError()).toBe(true);
expect(ageError.innerText).toContain('Age has errored');
});
}));
Run Code Online (Sandbox Code Playgroud)
我还创建了一个stackblitz 示例,请也查看一下。希望这些解决方案对您有所帮助:)
| 归档时间: |
|
| 查看次数: |
1262 次 |
| 最近记录: |