Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 323
jshoudy Avatar asked Feb 02 '17 00:02

jshoudy


People also ask

How to test a function in Jasmine?

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.

Why should I test my angular application?

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:

How to use testbed in Angular 2+?

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.

How do I run a test in angular CLI?

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.


1 Answers

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.

like image 145
Ploutarchos Spyridonos Avatar answered Oct 10 '22 16:10

Ploutarchos Spyridonos