I have the below method that listens to a custom event and sets the focus of the element. I want to write a unit test for this method. I am trying to mock the focus element focus and using fakeAsync to provide a little delay and also mocking the renderer listener but the coverage is not getting through this method.
listenToModalCloseEvent() {
this.modalListenerFn = this.renderer.listen(document, 'popupClosed', () => {
if (this.focusElement) {
setTimeout(() => {
this.focusElement.focus();
}, 0);
}
});
}
here is what I have trid,
it('should call listenToModalCloseEvent', fakeAsync(() => {
dummyElement.dispatchEvent(new Event('popupClosed', { bubbles: true }));
service.focusElement = dummyElement;
service.listenToModalCloseEvent();
const spy = spyOnProperty(service, 'focusElement').and.returnValue({ focus: () => {}});
spyOn((service as any).renderer, 'listen').and.callThrough();
tick(100);
expect(service.focusElement).toBeDefined();
expect(spy).toHaveBeenCalled();
}))
Don't where I am wrong
CodePudding user response:
The main issue is that you're dispatching popupClosed
event before the subscription to that event. Also:
- you can spy directly on
focusElement.focus()
method - you don't need to pass
100
totick
method ifsetTimeout
is called with0
- I don't know how you defined
dummyElement
so I just created it manually.
Here's the final test:
it('should call listenToModalCloseEvent', fakeAsync(() => {
const dummyElement = document.createElement('input')!;
document.body.appendChild(dummyElement); // now it can propagate events to the document
service.focusElement = dummyElement;
service.listenToModalCloseEvent();
const spy = spyOn(dummyElement, 'focus');
dummyElement.dispatchEvent(new Event('popupClosed', { bubbles: true }));
dummyElement.remove(); // remove input from the page
tick(0);
expect(service.focusElement).toBeDefined();
expect(spy).toHaveBeenCalled();
}))
btw, expect(service.focusElement).toBeDefined();
looks weird because you explicitly assigned that property to class.