使用 async、querySelectorAll、focus 测试整个方法
Test the entire method with async, querySelectorAll, focus
如何测试整个方法onShowSidebar
?
public async onShowSidebar() {
await delay();
const inputList = this.elem.nativeElement.querySelectorAll('#form input, #form textarea') as NodeListOf<HTMLInputElement | HTMLTextAreaElement>;
const selected = Array.from(inputList).find(f => !f.disabled);
if (selected)
selected.focus();
}
constructor(
private elem: ElementRef
) { }
delay = (ms: number = 100): Promise<boolean> => {
return new Promise(resolve => {
setTimeout(() => {
resolve(true);
}, ms);
});
};
我的困难在于将 querySelectorAll 模拟为 return 元素。然后测试是否调用了焦点
注意:需要使用querySelectorAll,因为使用了自定义输入组件,简单的示例渲染如下:
<form id="form">
<custom-input><input></custom-input>
<custom-area><textarea></custom-area>
</form>
经过一段时间尝试做一个有效的测试:
it('test onShowSidebar input1 focus', async () => {
const element = spyOn(component['elem'].nativeElement, 'querySelectorAll').and.callThrough();
await component.onShowSidebar();
expect(element).toHaveBeenCalled();
const input1 = element.calls.first().returnValue[0] as HTMLInputElement; //in the following tests just increase the index
const inputFocused = fixture.nativeElement.querySelector(`:focus`);
expect(inputFocused).toBeTruthy();
expect(inputFocused).toEqual(input1);
});
// disable the next input and do as many tests as needed and returnValue[1]
it('test onShowSidebar without focus', async () => {
component.formGroup.get('input1').disable();
component.formGroup.get('input2').disable();
component.formGroup.get('input3').disable();
fixture.detectChanges();
const element = spyOn(component['elem'].nativeElement, 'querySelectorAll').and.callThrough();
await component.onShowSidebar();
expect(element).toHaveBeenCalled();
const inputs = element.calls.first().returnValue as Array<HTMLInputElement | HTMLTextAreaElement>;
const inputFocused = fixture.nativeElement.querySelector(`:focus`);
expect(inputFocused).toBeFalsy();
inputs.forEach(input => {
expect(inputFocused).not.toEqual(input);
});
});
一些要点:
- 有必要使用
component['elem']
而不是模拟
ElementRef
callThrough
用于进行真实调用,return 用于渲染
元素
- 因为
element
只是一个 HTMLInputElement
return 而不是模拟,它
无法测试是否调用了焦点,因此解决方案
是检查谁被关注,以及是否与
屏幕上的输入序列
如何测试整个方法onShowSidebar
?
public async onShowSidebar() {
await delay();
const inputList = this.elem.nativeElement.querySelectorAll('#form input, #form textarea') as NodeListOf<HTMLInputElement | HTMLTextAreaElement>;
const selected = Array.from(inputList).find(f => !f.disabled);
if (selected)
selected.focus();
}
constructor(
private elem: ElementRef
) { }
delay = (ms: number = 100): Promise<boolean> => {
return new Promise(resolve => {
setTimeout(() => {
resolve(true);
}, ms);
});
};
我的困难在于将 querySelectorAll 模拟为 return 元素。然后测试是否调用了焦点
注意:需要使用querySelectorAll,因为使用了自定义输入组件,简单的示例渲染如下:
<form id="form">
<custom-input><input></custom-input>
<custom-area><textarea></custom-area>
</form>
经过一段时间尝试做一个有效的测试:
it('test onShowSidebar input1 focus', async () => {
const element = spyOn(component['elem'].nativeElement, 'querySelectorAll').and.callThrough();
await component.onShowSidebar();
expect(element).toHaveBeenCalled();
const input1 = element.calls.first().returnValue[0] as HTMLInputElement; //in the following tests just increase the index
const inputFocused = fixture.nativeElement.querySelector(`:focus`);
expect(inputFocused).toBeTruthy();
expect(inputFocused).toEqual(input1);
});
// disable the next input and do as many tests as needed and returnValue[1]
it('test onShowSidebar without focus', async () => {
component.formGroup.get('input1').disable();
component.formGroup.get('input2').disable();
component.formGroup.get('input3').disable();
fixture.detectChanges();
const element = spyOn(component['elem'].nativeElement, 'querySelectorAll').and.callThrough();
await component.onShowSidebar();
expect(element).toHaveBeenCalled();
const inputs = element.calls.first().returnValue as Array<HTMLInputElement | HTMLTextAreaElement>;
const inputFocused = fixture.nativeElement.querySelector(`:focus`);
expect(inputFocused).toBeFalsy();
inputs.forEach(input => {
expect(inputFocused).not.toEqual(input);
});
});
一些要点:
- 有必要使用
component['elem']
而不是模拟ElementRef
callThrough
用于进行真实调用,return 用于渲染 元素- 因为
element
只是一个HTMLInputElement
return 而不是模拟,它 无法测试是否调用了焦点,因此解决方案 是检查谁被关注,以及是否与 屏幕上的输入序列