Angular 单击组件​​测试中的 select 选项

Angular click select option in component test

我尝试了以下方法来尝试单击 select 下拉列表 none 中的一个选项,其中的工作。

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

在每个 运行 fixture.detectChanges(); 到 运行 变化检测之后,但是当我去检查元素值时它没有改变。 expect(selectEl.nativeElement.options[selectEl.nativeElement.selectedIndex].textContent).toBe('name2');

我是不是缺少一些简单的东西来让它工作?

更改下拉列表的选定选项的方法是设置下拉列表值,然后调度一个 change 事件。

你可以参考这个答案:

在你的情况下,你应该这样做:

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

您不必发送更改事件。 首先,您需要点击下拉菜单的触发器,我假设这是您的 selectEl selectEl = fixture.debugElement.query(By.css('#dropdown')).

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

在 detectChanges 之后,您的下拉菜单应该会打开。只有在这之后你才能从 fixture 中获得你的选项,因为之前它们不存在于你的 fixture 中。

我能够获得选项的唯一方法是执行 const selectOptions = fixture.debugElement.queryAll(By.css('.select-option'));,其中“select-选项”是我放在选项上的 class。我在我的项目中使用 mat-select ,所以这可能是由于那个。

您可以通过 selectOptions[0].nativeElement.click(); 单击第一个选项。之后您需要再次调用 fixture.detectChanges()。 现在您 select 有了一个选项!

我能够通过 selectEl.innerText.trim() 获得现在 select 的值。不确定这是否是最好的方法,但它确实有效。 Trim 用于去除空格。

我对 Emmy 的回答做了一些扩展。这是用于 selecting material 下拉列表的有效 "helper" 方法。

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

这让您可以指定您想要 select(通过 ID)的下拉列表和您想要 select 的索引。此方法的唯一注意事项是您必须向下拉列表中的 mat-option 元素添加 class。示例:

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

只需确保 mat-option 的 class 包含添加了 'Option' 的 ID。

这解决了 Emmy 的回答中的一个问题,即如果您在一个表单上有多个下拉菜单,您可以指定单击哪个 mat-option。

您可以通过在测试中引用它来使用上述扩展方法,如下所示:

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

我可以提供的最简单的解决方案如下。

let selectElement: HTMLSelectElement = fixture.nativeElement.querySelector('#dropdown');
selectElement.selectedIndex = 3;
selectElement.dispatchEvent(new Event('change'));

首先,您通过 ID 获取元素,然后 select 按编号获取索引 在您的情况下,它是 3 然后通过调度事件将触发 change 事件。