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?
We can test this by using the Jasmine function expect (), which will verify whether the incoming output is equal, contain, toBe an expected output or not. It is going to help us to assert that the functionality returns the given output. Finally, our spec file will look as follows: To run the spec file we need to write the command ng test.
Testing your Angular application helps you check that your app is working as you expect. Before writing tests for your Angular app, you should have a basic understanding of the following concepts:
In the beforeEach function for our test suite, we configure a testing module using the TestBed class. This creates a test Angular Module which we can use to instantiate components, perform dependency injection, and so on.The testBed is a mock environment to run Angular 2+ component tests without the browser.
The Angular CLI downloads and installs everything you need to test an Angular application with the Jasmine test framework. The project you create with the CLI is immediately ready to test. Just run the ng test CLI command: The ng test command builds the application in watch mode , and launches the Karma test runner.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With