web-dev-qa-db-fra.com

Angular cliquez sur l'option de sélection dans le test des composants

J'ai essayé ce qui suit pour essayer de cliquer sur une option dans une liste déroulante sélectionnée dont aucune ne fonctionne.

selectEl = fixture.debugElement.query(By.css('#dropdown'));
selectEl.nativeElement.options[3].nativeElement.dispatchEvent(new Event('click'));
selectEl.queryAll(By.css('option'))[3].nativeElement.click();
selectEl.nativeElement.options[3].nativeElement.click();

Après chaque je lance fixture.detectChanges(); pour exécuter la détection de changement mais quand je vais vérifier la valeur des éléments, elle n'a pas changé. expect(selectEl.nativeElement.options[selectEl.nativeElement.selectedIndex].textContent).toBe('name2');

Suis-je en train de manquer quelque chose de simple pour que cela fonctionne?

9
Steve Fitzsimons

La façon de modifier l'option sélectionnée d'une liste déroulante consiste à définir la valeur de la liste déroulante, puis à distribuer un événement change.

Vous pouvez utiliser cette réponse comme référence: test unitaire angulaire sélectionnez espion onChange sur la valeur vide

Dans votre cas, vous devriez faire quelque chose comme ceci:

  const select: HTMLSelectElement = fixture.debugElement.query(By.css('#dropdown')).nativeElement;
  select.value = select.options[3].value;  // <-- select a new value
  select.dispatchEvent(new Event('change'));
  fixture.detectChanges();
11
Ayala

Vous n'êtes pas obligé d'envoyer un événement de modification. Vous devez d'abord cliquer sur le déclencheur de votre liste déroulante, je suppose que c'est votre selectEl selectEl = fixture.debugElement.query(By.css('#dropdown')).

selectEl.click();
fixture.detectChanges();

Après detectChanges, votre liste déroulante doit être ouverte. Ce n'est qu'après cela que vous pourrez obtenir vos options du luminaire, car avant, elles n'étaient pas présentes dans votre luminaire.

La seule façon dont j'ai pu obtenir mes options est de faire const selectOptions = fixture.debugElement.queryAll(By.css('.select-option')); où 'select-option' est la classe que j'ai mise sur les options. J'utilise mat-select dans mon projet, cela peut donc être dû à cela.

Vous pouvez cliquer sur la première option en faisant selectOptions[0].nativeElement.click();. Vous devez ensuite appeler à nouveau fixture.detectChanges(). Vous avez maintenant sélectionné une option!

J'ai pu obtenir la valeur qui est maintenant sélectionnée en faisant selectEl.innerText.trim(). Je ne sais pas si c'est la meilleure façon de le faire, mais cela fonctionne. Trim est utilisé pour supprimer l'espace blanc.

7
Emmy

J'ai développé un peu la réponse d'Emmy. Voici une méthode "d'aide" efficace pour sélectionner les listes déroulantes de matériaux.

import { By } from '@angular/platform-browser';

export default class TestUtils {
  static selectDropdown(id: string, fixture: any): void {
    const select = fixture.debugElement.query(By.css(`#${id}`)).nativeElement;
    select.click();
    fixture.detectChanges();
    const selectOptions = fixture.debugElement.queryAll(By.css(`.${id}Option`));
    selectOptions[5].nativeElement.click();
    fixture.detectChanges();
  }
}

Cela vous permet de spécifier la liste déroulante que vous souhaitez sélectionner (par id) et l'index que vous souhaitez sélectionner. La seule mise en garde pour cette méthode est que vous devez ajouter une classe à vos éléments mat-option dans votre liste déroulante. Exemple:

<mat-option *ngFor="let trim of trims" value="{{trim}}" class="trimDropdownOption">{{trim}}</mat-option>

Assurez-vous simplement que la classe de l'option mat contient l'ID avec l'ajout de l'option.

Cela résout un problème avec la réponse d'Emmy où si vous avez plusieurs listes déroulantes sur un même formulaire, vous pouvez spécifier l'option de tapis sur laquelle vous cliquez.

Vous pouvez utiliser la méthode d'extension ci-dessus en la référençant comme suit dans votre test:

TestUtils.selectDropdown('yearDropdown', 1, fixture);
expect(fixture.componentInstance.onYearChange).toHaveBeenCalled();
0
Nate