Reputation:
I have the following -
window.addEventListener( "orientationchange", () => {
// Code to test
});
How can I trigger this event in Jasmine? I have tried the following and it didn't work -
event = document.createEvent("HTMLEvents");
event.initEvent("orientationchange", true, true);
Here is the class -
export class AvailabilityComponent {
changed: boolean = false;
constructor( ) {
window.addEventListener( "orientationchange", () => {
this.changed = !this.changed;
} );
}
}
Thanks
Upvotes: 0
Views: 3122
Reputation: 222379
orientationchange
event listener can be tested with
window.dispatchEvent(new Event('orientationchange'));
The problem is this is functional test, not unit test. Usually this kind of things is tested in E2E tests, this is the place where we want to check that the application plays nicely with browser and real DOM. Also, anonymous listeners cannot be removed, they may affect subsequent test and cause memory leaks.
A proper strategy for unit testing is to test written code line by line. Angular guide is specific on test isolation:
However, it's often more productive to explore the inner logic of application classes with isolated unit tests that don't depend upon Angular. Such tests are often smaller and easier to read, write, and maintain.
To be test-friendly the class can be refactored to
export const WINDOW = new OpaqueToken();
... providers: [..., { provide: WINDOW, useFactory: () => window }];
export class AvailabilityComponent {
changed: boolean = false;
constructor(@Inject(WINDOW) window: Window) {
window.addEventListener( "orientationchange", this.orientationChangeListener);
}
orientationChangeListener = () => {
this.changed = !this.changed;
}
}
So it can be easily tested with
const windowMock = jasmine.createSpyObj(['addEventListener']);
const comp = new AvailabilityComponent(windowMock);
expect(windowMock.addEventListener).toHaveBeenCalledWith("orientationchange",
comp.orientationChangeListener);
expect(comp.changed).toBe(false);
comp.orientationChangeListener.call(null); // unbind method
expect(comp.changed).toBe(true);
There is builtin DOCUMENT
service already, and WINDOW
service follows the same way, the recipe similar to $window
in AngularJS. Acting on the mocked service allows to provide isolation for unit test and not pollute global scope with changes that have to be cleaned up in afterEach
.
Since AvailabilityComponent
is a component and will be tested with TestBed anyway, it probably makes sense to incorporate the test into TestBed. See also this answer on isolated vs TestBed unit tests.
Upvotes: 1
Reputation:
I have managed to this working with the following -
it( 'expect orientationchange to update changed to be truthy', () => {
event = new Event('orientationchange');
component.ngOnInit();
window.dispatchEvent(event);
// ...
});
Upvotes: 0
Reputation: 493
You can use window.dispatchEvent(new Event("orientationchange"))
directly instead of
event = document.createEvent("HTMLEvents");
event.initEvent("orientationchange", true, true);
Upvotes: 2