I am not sure why the the change event isn't firing and therefore not triggering the function I registered for the change event.
I know this works when I run it, but I can't get it in the spec.
Here is a demo of what I am talking about... As you can see from the logs, the toggle
never gets called:
https://stackblitz.com/edit/angular-material-slide-toggle-test-utmbmy?file=app%2Fhello.component.spec.ts
Roughly, this is my code here...
component.html:
<mat-slide-toggle [checked]="useDefault" (change)="toggle($event)"></mat-slide-toggle>
component.ts:
...
toggle(event: MatSlideToggleChange) {
console.log('Toggle fired');
this.useDefault = event.checked;
}
In my spec.ts:
it('should trigger toggle...', () => {
const componentDebug = fixture.debugElement;
const slider: MatSlideToggle =
componentDebug.query(By.css('form mat-slide-toggle')).componentInstance;
console.log('before ' + slider.checked);
slider.toggle();
fixture.detectChanges();
console.log('after ' + slider.checked);
console.log('useDefault ' + component.useDefault);
});
The after
logging does print out slider.checked
to be the opposite value from before
. However, the component.useDefault
stays the same and the logging statement in the toggle
function is never called, which means it never triggered it.
Why is this going on and how do I fix this?
I've tried placing the whole thing into fakeAsync
, using tick
, placing the 'after' code into fixture.whenStable()
and fixture.whenRenderingDone()
.
I have a NoopAnimationsModule
in the TestBed
's import
.
When using third-party components, you should trust them to handle the event. However, you could trigger the event, using the triggereventhandler while you spyOn the method you want to be called.
import { Component } from '@angular/core';
import { MatSlideToggleChange } from '@angular/material';
@Component({
selector: 'hello',
template: `
<mat-slide-toggle
[checked]="useDefault" (change)="toggle($event)"
></mat-slide-toggle>`
})
export class HelloComponent {
public useDefault = false;
public toggle(event: MatSlideToggleChange) {
console.log('toggle', event.checked);
this.useDefault = event.checked;
}
}
it('should call change method on slide change', () => {
const componentDebug = fixture.debugElement;
const slider = componentDebug.query(By.directive(MatSlideToggle));
spyOn(component, 'toggle'); // set your spy
slider.triggerEventHandler('change', null); // triggerEventHandler
expect(component.toggle).toHaveBeenCalled(); // event has been called
});
See the test passing on stackblitz: https://stackblitz.com/edit/angular-material-slide-toggle-test-spy-trigger-event?file=app/hello.component.spec.ts
<mat-slide-toggle (change)="onToggle($event)">Compare</mat-slide-toggle>
event.checked = true || false;
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