I have been trying to perform a test for angular 2 application that clicks a submit button which calls a function. I usually use two methods to perform the same.
element.nativeElement.click()
and
element.triggerEventHandler('click',null);
I thought both these methods were same, until I came across this situation where triggering event handler method does not work.
element = fixture.debugElement.query(By.css('.dropList li'));
element.triggerEventHandler('click',null); //Click event works here
fixture.detectChanges();
let button = fixture.debugElement.query(By.css('button'));
//button.triggerEventHandler('click',null); //Does not call function
button.nativeElement.click(); //Calls function
fixture.detectChanges();
Template for your reference:
<form (ngSubmit)="printSelection()">
<div class="dropList">
<ul>
<li *ngFor="let element of data.elements" (click)="selectElement(element)"> </li>
</ul>
</div>
<button type="submit">Submit</button>
</form>
So, are there any difference between these two approaches or do you think I may have gone wrong somewhere in my code?
element.nativeElement.click()
is native method to simulate a mouse click on an element. It's bubbling and it behaves in the same way as if we click on the element.
debugElement.triggerEventHandler(eventName, eventObj)
is angular built-in method that just calls all listeners for given eventName on current debug element:
triggerEventHandler(eventName: string, eventObj: any) {
this.listeners.forEach((listener) => {
if (listener.name == eventName) {
listener.callback(eventObj);
}
});
}
Listeners are added when DebugRenderer2
runs listen
method:
listen(
target: 'document'|'windows'|'body'|any, eventName: string,
callback: (event: any) => boolean): () => void {
if (typeof target !== 'string') {
const debugEl = getDebugNode(target);
if (debugEl) {
debugEl.listeners.push(new EventListener(eventName, callback));
}
}
return this.delegate.listen(target, eventName, callback);
}
It happens when we apply event binding to element like
(click)="handler()"
@HostListener('click')
host: '{ '(mouseenter): 'handler()' }
renderer.listen
Let's say we have the following template:
<div (click)="test()">
<div class="innerDiv">
{{title}}
</div>
</div>
And our test will look like:
de = fixture.debugElement.query(By.css('.innerDiv'));
de.nativeElement.click(); // event will be bubbled and test handler will be called
de.triggerEventHandler('click', null); // there is not handlers for click event
// that angular added to this element
// so test method won't be called
Then let's look at your template. There is no handlers for button
so triggerEventHandler
won't have any effect. On the other hand button.nativeElement.click();
will fire submit because button has type submit and its standart behaviour of button on click event.
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