Как проверить ввод ключа на кнопке в Angular? - PullRequest
0 голосов
/ 06 ноября 2018

Я работаю над приложением, где доступность очень важна. В рамках этого у нас есть ряд различных компонентов, которые мы хотим обеспечить доступными через события мыши и клавиатуры. Мы пытаемся настроить модульные тесты на соответствие этим требованиям, чтобы гарантировать, что любые изменения, внесенные в эти компоненты, будут по-прежнему соответствовать этим стандартам. Мы столкнулись с проблемой с кнопками. У меня есть пример приложения для демонстрации:

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  console = console;

  actionTaken($event) {
    this.console.log($event);
  }
}

app.component.html

<!-- <button
  (click)="actionTaken($event)"
  (keyup.enter)="actionTaken($event)">
    Take Action
</button> -->

<button
  (click)="actionTaken($event)">
    Take Action
</button>

В html есть две кнопки: одна прослушивает событие щелчка, а другая - событие щелчка и событие ввода keyup.

Тот, у которого есть два прослушивателя событий, - тот, который, как я полагаю, мне нужно будет использовать, но когда я его использую, я вижу, что, когда я нажимаю кнопку ввода на кнопке, событие запускается дважды, один раз как keyup а другой как клик.

Тот, у кого есть один прослушиватель событий, когда я его использую, я вижу, что когда я нажимаю кнопку ввода на кнопке, событие запускается только один раз, как событие щелчка.

Я могу использовать второй вариант, хотя я не уверен, что приложение будет работать таким образом во всех браузерах. Кроме того, я попытался настроить модульные тесты, чтобы убедиться, что они работают в соответствии с нашими договорными обязательствами (ввод и щелчок мышью должны работать), и я не могу понять, как писать тесты.

Вот то, что я пробовал до сих пор.

app.component.spec.ts

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  }));

  it('clicking on button should take action', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    spyOn(component, 'actionTaken');

    fixture.nativeElement
           .querySelector('button')
           .click();

    expect(component.actionTaken).toHaveBeenCalledTimes(1);
  });

  it('clicking on button should log to console', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    spyOn(component.console, 'log');

    fixture.nativeElement
           .querySelector('button')
           .click();

    expect(component.console.log).toHaveBeenCalledTimes(1);
  });

  it('pressing enter on button should take action', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    spyOn(component, 'actionTaken');

    fixture.nativeElement
           .querySelector('button')
           .dispatchEvent(new KeyboardEvent('keyup', { key: 'enter', bubbles: true }));

    expect(component.actionTaken).toHaveBeenCalledTimes(1);
  });

  it('pressing enter on button should log to console', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    spyOn(component.console, 'log');

    fixture.nativeElement
           .querySelector('button')
           .dispatchEvent(new KeyboardEvent('keyup', { key: 'enter', bubbles: true }));

    expect(component.console.log).toHaveBeenCalledTimes(1);
  });
});

Используя кнопку, прослушивающую оба события, все эти тесты проходят, но когда я запускаю код в браузере, я вижу, что тесты не соответствуют действительности, поскольку клавиша ввода фактически запускает метод дважды, а не один раз. как показывают тесты.

При использовании кнопки, прослушивающей только событие щелчка, тестирование клавиши «Ввод» завершается неудачно, хотя в браузере работает эта функция.

Это только кажется, проблема с кнопками. Другие типы элементов HTML, похоже, не работают таким образом.

Как правильно написать компонент, события и тесты, чтобы требуемый метод вызывался только один раз щелчком мыши и клавишей ввода, и тесты будут правильно настроены для проверки этого?

1 Ответ

0 голосов
/ 06 ноября 2018

Спецификация HTML5 имеет понятие элемента activation. Нажатие клавиши enter является лишь одним из способов активировать кнопку. Пользователь также может нажать кнопку space или использовать другие методы для активации кнопки (голосовое управление и т. Д.). Обычно activation завершается событием click для этого элемента. Вопрос: все ли браузеры реализуют спецификацию одинаково? Кнопки enter активируются в каждом браузере?

Если вы хотите убедиться, что ваша кнопка реагирует на клавишу enter, вы можете оставить оба обработчика на своей кнопке и проверить в обработчике click, является ли событие synthetic или authentic.

Проблема в том, что ваш тест лежит на вас и говорит, что все правильно, может иметь несколько источников. Во-первых, это зависит от того, с каким браузером вы запускаете свои тесты. PhantomJS может вести себя иначе, чем другие браузеры. Вторая проблема может заключаться в том, что вы создаете синтетическое событие keyup в своем тесте, и браузер может вести себя по-разному для синтетических событий в отношении процесса активации. Я проверил это в Chrome, и фактически Chrome не активирует кнопку, когда событие синтетическое.

Я бы просто использовал обработчик click и оставил процесс активации в браузере и вручную проверил, как ведут себя разные браузеры, поддерживаемые приложением. В тесте я бы просто испустил событие click.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...