How can i simulate browser focus when testing using angular and jasmine?

蹲街弑〆低调 提交于 2020-08-01 11:27:13

问题


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);
  });
}));

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.

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?


回答1:


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();

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();

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();

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();

All the available JavaScript events are here.



来源:https://stackoverflow.com/questions/41992155/how-can-i-simulate-browser-focus-when-testing-using-angular-and-jasmine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!