web-dev-qa-db-fra.com

Angular 2+: formulaire de test avec mat-slide-toggle - l'événement change ne se déclenchera pas

Je ne sais pas pourquoi l'événement de changement ne se déclenche pas et ne déclenche donc pas la fonction que j'ai enregistrée pour l'événement de changement.

Je sais que cela fonctionne lorsque je l'exécute, mais je ne peux pas l'obtenir dans les spécifications.

Voici une démonstration de ce dont je parle ... Comme vous pouvez le voir dans les journaux, le toggle n'est jamais appelé: https://stackblitz.com/edit/angular-material- slide-toggle-test-utmbmy? file = app% 2Fhello.component.spec.ts

En gros, voici mon code ici ...

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

Dans mes spécifications:

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

La journalisation after imprime slider.checked Pour être la valeur opposée de before. Cependant, component.useDefault Reste le même et l'instruction de journalisation dans la fonction toggle n'est jamais appelée, ce qui signifie qu'elle ne l'a jamais déclenchée.

Pourquoi cela se passe-t-il et comment résoudre ce problème?

J'ai essayé de placer le tout dans fakeAsync, en utilisant tick, en plaçant le code 'after' dans fixture.whenStable() et fixture.whenRenderingDone().

J'ai un NoopAnimationsModule dans le TestBed de import.

10
user1902183

Lorsque vous utilisez des composants tiers, vous devez leur faire confiance pour gérer l'événement. Cependant, vous pouvez déclencher l'événement en utilisant triggereventhandler tandis que vous spyOn la méthode que vous souhaitez appeler.

Composant

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

Tester

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

Voir le test passant sur stackblitz: https://stackblitz.com/edit/angular-material-slide-toggle-test-spy-trigger-event?file=app/hello.component.spec.ts =

8
Leo Caseiro