Angular Jest Spectator - функция фокусировки не работает - PullRequest
1 голос
/ 09 апреля 2020

Итак, у меня есть Angular компонент, который выглядит следующим образом

<div class="hello" (keydown.enter)="doSomething()"></div>

, и я пытаюсь написать тест для случая - когда пользователь фокусируется на div, нажатие клавиши enter должно вызвать 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">

Пожалуйста, дайте мне ie поддержку, как сфокусироваться на элементе div, а затем нажмите Enter на это.

1 Ответ

2 голосов
/ 01 мая 2020

Во-первых, вам нужно понять, что делает метод spectator.focus().

Давайте рассмотрим этот метод в Исходный код зрителя :

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); Вот код этого метода:

export function patchElementFocus(element: HTMLElement): void {
  element.focus = () => dispatchFakeEvent(element, 'focus');
  element.blur = () => dispatchFakeEvent(element, 'blur');
}

, где dispatchFakeEvent вызывает node.dispatchEvent(event); собственный метод под hood.

Итак, spectator.focus(element) вызывает node.dispatchEvent(...).

Теперь вам нужно понять разницу между доверенными и ненадежными событиями.

События, инициируемые с помощью node.dispatchEvent называются ненадежными событиями и не запускают действия браузера по умолчанию ( ссылка на w3.org )

Это означает, что ручное инициирование события не генерирует действие по умолчанию, связанное с этим событием . Например, ручное инициирование события фокуса не приводит к тому, что элемент получает фокус , ручное инициирование события отправки не отправляет форму.

Вы можете только прослушивать созданные вручную события через обработчики событий. Это то, что зритель демонстрирует нам. (Тест https://github.com/ngneat/spectator/blob/fcdb6a809571706fac3d7b5d8da5bf2f7ba0e305/projects/spectator/test/events/events.component.spec.ts#L13) (Слушатель https://github.com/ngneat/spectator/blob/fcdb6a809571706fac3d7b5d8da5bf2f7ba0e305/projects/spectator/test/events/events.component.html#L2)

Наконец, решение здесь состоит в том, чтобы использовать собственный метод element.focus(), чтобы иметь возможность установить фокус на ваш див. Кроме того, tabindex attribute требуется здесь.

spectator.query<HTMLDivElement>('.hello').focus();
expect(spectator.query('.hello')).toBeFocused();

Пример Stackblitz

...