How can i simulate browser focus when testing using angular and jasmine?
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.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on June 18, 2022Comments
-
Admin about 2 years
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?
-
Alex C over 4 years
import { dispatchEvent } from '@angular/platform-browser/testing/src/browser_util'
=> that dependency doesnt exist. -
MarshHawk over 3 yearsthis answer was very helpful, saved me when something like
inputElement.focus()
didn't work.