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();

Stackblitz Example