Angular 2 + Jasmine:测试焦点时的浏览器焦点

时间:2017-02-02 00:06:58

标签: unit-testing angular jasmine karma-jasmine

我正在尝试编写一个单元测试,用于检查焦点事件的影响是否发生。我的实际测试用例更复杂,但我使用以下代码创建了一个最小的再现:

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运行此测试时,只要我专注于运行业力目标的chrome选项卡,测试就会通过。但是,如果浏览器没有焦点,则测试失败(即使浏览器可见,但我点击另一个窗口),并显示错误消息:

Expected null not to be null.

我认为当Chrome标签没有焦点时,inputEl.focus()调用实际上并未被调用,但我不知道如何修复它。无论浏览器的焦点如何,我写的所有其他单元测试都会通过有没有人碰到这个或有任何想法?

1 个答案:

答案 0 :(得分:7)

要在Angular元素上触发事件,您可以使用内置的JavaScript ES6方法dispatchEvent,随后调用Angular的更改检测机制来更新DOM:

inputElement.dispatchEvent(new Event('focus'));
fixture.detectChanges();

实现同样目标的更优雅的方法是使用angular&#39; s包装器方法:

import { dispatchEvent } from '@angular/platform-browser/testing/src/browser_util'

dispatchEvent(inputElement, 'focus');
fixture.detectChanges();

有趣的是当你想为你的输入元素设置一个值。您需要先在输入的值属性中指定一个字符串,然后触发输入&#39;改变事件:

inputElement.value = 'abcd';
dispatchEvent(inputElement, 'input');
fixture.detectChanges();

注意:有些活动没有按照您的预期行事。例如,发送“点击”按钮。事件不会把焦点放在你的输入元素上!一个解决方法可能是首先触发一个焦点&#39;事件,然后点击&#39;事件如下:

dispatchEvent(inputElement, 'focus');
dispatchEvent(inputElement, 'input');
fixture.detectChanges();

所有可用的JavaScript事件均为here