如何在Angular中测试keyup回车按钮?
我正在开发一个可访问性非常重要的应用程序。作为其中的一部分,我们有许多不同的组件,我们希望确保可以通过鼠标事件和键盘事件访问这些组件。我们正试图围绕这些需求设置单元测试,以确保对这些组件所做的任何更改仍然符合这些标准。我们遇到了按钮问题。我有一个示例应用程序来演示:如何在Angular中测试keyup回车按钮?,angular,unit-testing,Angular,Unit Testing,我正在开发一个可访问性非常重要的应用程序。作为其中的一部分,我们有许多不同的组件,我们希望确保可以通过鼠标事件和键盘事件访问这些组件。我们正试图围绕这些需求设置单元测试,以确保对这些组件所做的任何更改仍然符合这些标准。我们遇到了按钮问题。我有一个示例应用程序来演示: app.component.ts import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './
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);
}
}
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);
});
});
app.component.html
<!-- <button
(click)="actionTaken($event)"
(keyup.enter)="actionTaken($event)">
Take Action
</button> -->
<button
(click)="actionTaken($event)">
Take Action
</button>
使用按钮监听这两个事件,所有这些测试都通过了,但是当我在浏览器中运行代码时,我可以看到测试并不真实,因为enter键实际上触发了两次方法,而不是像测试所指示的那样触发了一次
尽管“回车”键测试失败,但使用按钮仅监听单击事件,尽管该功能似乎在浏览器中工作
这似乎只是按钮的问题。其他类型的HTML元素似乎不是这样工作的
编写组件、事件和测试的正确方法是什么?这样,只需单击鼠标并按enter键即可调用所需的方法一次,并且测试将正确设置以验证这一点?具有元素激活的概念。按enter
键只是激活按钮的一种方式。用户也可以按space
键或使用其他方法激活按钮(语音控制等)。通常,激活
会在该元素上的点击事件中达到高潮。问题是:所有浏览器是否都以相同的方式实现规范?是否在每个浏览器中都使用enter
键激活按钮
如果要确保按钮对enter
键做出反应,可以将两个处理程序都保留在按钮上,然后在单击
处理程序中检查事件是合成的还是真实的
你们的测试对你们撒谎并说一切都是正确的问题可能有多个来源。首先,它取决于运行测试的浏览器。PhantomJS的行为可能与其他浏览器不同。第二个问题可能是您正在测试中创建合成的keyup
事件,并且浏览器在激活过程中对合成事件的行为可能不同。我已经在Chrome上测试过了,事实上Chrome在合成事件时不会激活按钮
我只需使用单击处理程序,将激活过程留在浏览器上,并手动测试应用程序支持的不同浏览器的行为。在测试中,我只会发出click
事件。我认为按钮type=“submit”总是响应Enter键感谢您的评论。type=“submit”似乎是默认类型。我还尝试了type=“button”,根据,它应该没有默认行为,并且我仍然看到相同的功能。感谢您提供的信息。标准角度设置通过Chrome运行测试。如果我理解正确,按下enter
键将是一个synthetic
事件?另外,如果我选择忽略合成的点击事件,我会失去你所说的其他事件,比如空间?而且,这并不能回答这个问题。你的建议是手动测试,这是我希望避免的。今天它是一个按钮
,也许明天设计团队会将其更改为a
或div
,此时我们需要知道如何再次手动测试它们。是的,当用户按下enter
时,浏览器会创建合成点击事件。是的,当您处理keyup
事件并仅处理enter
key事件并忽略所有synthetic单击事件时,您将丢失导致按钮激活的所有synthetic事件。所以这看起来是个坏主意:)我的建议是只对点击处理程序进行单元测试,而不要费心测试所有可能的合成点击事件和浏览器的不同行为。但如果您真的想测试keyup,那么您必须找到一种方法来调度触发单击的键事件(如果可能的话)。也许一些能够复制本地用户键盘输入的e2e测试框架会有所帮助。