使用 Angular 和 jasmine 进行测试时如何模拟浏览器焦点? [英] How can i simulate browser focus when testing using angular and jasmine?
问题描述
我正在尝试编写一个单元测试来检查焦点事件的影响是否发生.我的实际测试用例更复杂,但我使用以下代码创建了一个最小复制:
I am trying to write a unit test that checks whether or not the effect of a focus event takes place. My actual test case is more complicated, but I have created a minimal reproduction with the following code:
it('testing input focus', async(() => {
let showDiv = false;
const template = `<div *ngIf="shouldShow" class='hidden-div'>
SHOW ME WHAT YOU GOT
</div>
<input (focus)="shouldShow = !shouldShow" name="input">`;
buildTestComponent(template, {shouldShow: showDiv}).then((fixture) => {
fixture.detectChanges();
const inputEl: HTMLInputElement = fixture.nativeElement.querySelector('input');
expect(fixture.nativeElement.querySelector('.hidden-div')).toBe(null);
inputEl.focus();
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('.hidden-div')).not.toBe(null);
});
}));
当我使用 karma 运行此测试时,只要我专注于运行 karma 目标的 chrome 选项卡,测试就会通过.但是,如果浏览器没有焦点,则测试失败(即使浏览器可见,但我点击另一个窗口)并显示错误消息:
When I run this test with karma the test passes as long as I have focus on the chrome tab that is running the karma target. However, if the browser does not have focus the test fails (even if the browser is visible, but I click on another window) with error message:
Expected null not to be null.
我假设当 Chrome 选项卡没有焦点时, inputEl.focus() 调用实际上并没有被调用,但我不知道如何修复它.无论浏览器焦点如何,我编写的所有其他单元测试都通过了.有没有人遇到过这个或者有什么想法?
I assume that when the Chrome tab doesn't have focus, the inputEl.focus() call doesn't actually get called but I don't know how to fix it. All other unit tests I have written pass regardless of browser focus. Has anyone run into this or have any ideas?
推荐答案
要在 Angular 元素上触发事件,可以使用内置的 JavaScript ES6 方法 dispatchEvent 随后调用 Angular 的更改检测机制来更新 DOM:
To trigger an event on an Angular element, you can use the built-in JavaScript ES6 method dispatchEvent with a subsequent call of Angular's change detection mechanism to get your DOM updated:
inputElement.dispatchEvent(new Event('focus'));
fixture.detectChanges();
实现相同目的的更优雅的方法是使用 Angular 的包装方法:
A more elegant way to achieve the same thing is to use angular's wrapper method:
import { dispatchEvent } from '@angular/platform-browser/testing/src/browser_util'
dispatchEvent(inputElement, 'focus');
fixture.detectChanges();
一个有趣的例子是当你想为你的输入元素设置一个值.您需要先将字符串分配给输入的 value 属性,然后触发输入"更改事件:
An interesting one is when you want to set a value to your input element. You will need to first assign a string to the input's value property and then trigger an 'input' change event:
inputElement.value = 'abcd';
dispatchEvent(inputElement, 'input');
fixture.detectChanges();
注意:有些事件并不像您预期的那样发生.例如,调度一个 'click' 事件不会将焦点放在您的输入元素上!一种解决方法可能是先触发焦点"事件,然后触发点击"事件,如下所示:
Note: There are events that do not act the way you may expect. For example, dispatching a 'click' event will NOT give the focus to your input element! A workaround could be to first trigger a 'focus' event and then a 'click' event as follows:
dispatchEvent(inputElement, 'focus');
dispatchEvent(inputElement, 'input');
fixture.detectChanges();
所有可用的 JavaScript 事件都在 这里一个>.
All the available JavaScript events are here.
这篇关于使用 Angular 和 jasmine 进行测试时如何模拟浏览器焦点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!