Angular Jest Spectator - 焦点功能不起作用
Angular Jest Spectator - focus function does not work
所以,我有 Angular 个看起来像这样的组件
<div class="hello" (keydown.enter)="doSomething()"></div>
我正在尝试为案例编写测试 - 当用户专注于 div 时,按回车键应该调用 doSomething()。不幸的是,我不能用旁观者来嘲笑这种情况。
我已经试过了:
spectator.focus(spectator.query('.hello'));
expect(spectator.query('.hello')).toBeFocused(); // test failed
spectator.keyboard.pressEnter();
还有
spectator.query('.hello').dispatchEvent(new Event('focus'));
并且两者都带有
spectator.detectChanges(); // without success
我想,问题出在我的 HTML 模板中,但这些函数也不适用于:
<div class="hello" tabindex="0">
甚至
<input class="hello" type="text">
请大家多多支持,如何聚焦div元素然后按回车。
首先,您需要了解 spectator.focus()
方法的作用。
我们来看看Spectator source code中的这个方法:
public focus(selector: SpectatorElement = this.element): void {
const element = this.getNativeElement(selector);
if (!(element instanceof HTMLElement)) {
throw new Error(`Cannot focus: ${selector} is not a HTMLElement`);
}
patchElementFocus(element);
element.focus();
this.detectChanges();
}
我们可以注意到,在触发本机 element.focus()
方法之前,它还会调用 patchElementFocus(element);
下面是此方法的 the code:
export function patchElementFocus(element: HTMLElement): void {
element.focus = () => dispatchFakeEvent(element, 'focus');
element.blur = () => dispatchFakeEvent(element, 'blur');
}
其中 dispatchFakeEvent
在后台调用 node.dispatchEvent(event);
本机方法。
因此,spectator.focus(element)
触发 node.dispatchEvent(...)
。
现在,您需要了解可信事件和不可信事件之间的区别。
使用 node.dispatchEvent 触发的事件称为不可信事件,它们不会触发默认浏览器操作 (w3.org reference)
这意味着手动触发事件不会生成与该事件关联的默认操作。例如,手动触发焦点事件不会使元素获得焦点,手动触发提交事件不会提交表单。
您只能通过事件处理程序收听手动创建的事件。
这就是《旁观者》向我们展示的。 (测试https://github.com/ngneat/spectator/blob/fcdb6a809571706fac3d7b5d8da5bf2f7ba0e305/projects/spectator/test/events/events.component.spec.ts#L13) (Listener https://github.com/ngneat/spectator/blob/fcdb6a809571706fac3d7b5d8da5bf2f7ba0e305/projects/spectator/test/events/events.component.html#L2)
最后,这里的解决方案是使用本机 element.focus()
方法来将焦点设置在您的 div 上。另外,这里需要tabindex attribute
。
spectator.query<HTMLDivElement>('.hello').focus();
expect(spectator.query('.hello')).toBeFocused();
所以,我有 Angular 个看起来像这样的组件
<div class="hello" (keydown.enter)="doSomething()"></div>
我正在尝试为案例编写测试 - 当用户专注于 div 时,按回车键应该调用 doSomething()。不幸的是,我不能用旁观者来嘲笑这种情况。 我已经试过了:
spectator.focus(spectator.query('.hello'));
expect(spectator.query('.hello')).toBeFocused(); // test failed
spectator.keyboard.pressEnter();
还有
spectator.query('.hello').dispatchEvent(new Event('focus'));
并且两者都带有
spectator.detectChanges(); // without success
我想,问题出在我的 HTML 模板中,但这些函数也不适用于:
<div class="hello" tabindex="0">
甚至
<input class="hello" type="text">
请大家多多支持,如何聚焦div元素然后按回车。
首先,您需要了解 spectator.focus()
方法的作用。
我们来看看Spectator source code中的这个方法:
public focus(selector: SpectatorElement = this.element): void {
const element = this.getNativeElement(selector);
if (!(element instanceof HTMLElement)) {
throw new Error(`Cannot focus: ${selector} is not a HTMLElement`);
}
patchElementFocus(element);
element.focus();
this.detectChanges();
}
我们可以注意到,在触发本机 element.focus()
方法之前,它还会调用 patchElementFocus(element);
下面是此方法的 the code:
export function patchElementFocus(element: HTMLElement): void {
element.focus = () => dispatchFakeEvent(element, 'focus');
element.blur = () => dispatchFakeEvent(element, 'blur');
}
其中 dispatchFakeEvent
在后台调用 node.dispatchEvent(event);
本机方法。
因此,spectator.focus(element)
触发 node.dispatchEvent(...)
。
现在,您需要了解可信事件和不可信事件之间的区别。
使用 node.dispatchEvent 触发的事件称为不可信事件,它们不会触发默认浏览器操作 (w3.org reference)
这意味着手动触发事件不会生成与该事件关联的默认操作。例如,手动触发焦点事件不会使元素获得焦点,手动触发提交事件不会提交表单。
您只能通过事件处理程序收听手动创建的事件。 这就是《旁观者》向我们展示的。 (测试https://github.com/ngneat/spectator/blob/fcdb6a809571706fac3d7b5d8da5bf2f7ba0e305/projects/spectator/test/events/events.component.spec.ts#L13) (Listener https://github.com/ngneat/spectator/blob/fcdb6a809571706fac3d7b5d8da5bf2f7ba0e305/projects/spectator/test/events/events.component.html#L2)
最后,这里的解决方案是使用本机 element.focus()
方法来将焦点设置在您的 div 上。另外,这里需要tabindex attribute
。
spectator.query<HTMLDivElement>('.hello').focus();
expect(spectator.query('.hello')).toBeFocused();