Angular 测试 .spec.ts 如何 select 多个选项

Angular test .spec.ts How to select multiple options

我有一个要测试的多个 Select 列表,基本上当您 select n 个项目时,您然后单击一个按钮,该按钮将一个列表中的项目复制到另一个列表。我在尝试 select 多个值时遇到问题。这是一个多 select,所以我希望能够 select n 个项目。

我可以 select 这行的一项,但我如何 select 测试多项?

select.value = select.options[0].value;

这里是测试selector.component.spec.ts

 it('When assign button is clicked expect to be displayed in assigned list', () => {

    let unassignedItems = [
      { id:1, name: 'Rob' },
      { id:2, name: 'Dave' },
      { id:3, name: 'Steve' }      
    ] as Person[];
    component.unassignedItems = unassignedItems;
    fixture.detectChanges();

    let select: HTMLSelectElement = unassignedItemsSelect.nativeElement;    
    select.value = select.options[0].value;
    select.dispatchEvent(new Event('change'));
    fixture.detectChanges();

    assignedItemButton.triggerEventHandler('click', null);

    expect(component.assignedItems[0].id).toBe(1)
    
  })

组件看起来像这样 selector.component.ts

import { Component, Input, OnInit} from '@angular/core';
import { Person } from '../Person';

@Component({
  selector: 'app-selector',
  templateUrl: './selector.component.html',
  styleUrls: ['./selector.component.scss']
})
export class SelectorComponent implements OnInit {

  constructor() { }

  unassignedSelectedItems: Person[] = [];
  assignedSelectedItems: Person[] = [];

  @Input() unassignedItems : Person[] = [];
  @Input() assignedItems: Person[] = [];

  ngOnInit(): void {
  }

  assignSelections(): void {
    this.assignedItems.push(...this.unassignedSelectedItems);
    // remove the item from the unassigned list
    this.unassignedSelectedItems.forEach(selectedItem => {
      let index = this.unassignedItems.findIndex(x => x.id == selectedItem.id);
      this.unassignedItems.splice(index, 1); // removes the item at that index  
    });
    // clear the selected item for the next ones
    this.unassignedSelectedItems = [];
  }

  unassignSelections(): void {
    this.unassignedItems.push(...this.assignedSelectedItems);
    // remove the item from the assigned list
    this.assignedSelectedItems.forEach(selectedItem => {
      let index = this.assignedItems.findIndex(x => x.id == selectedItem.id);
      this.assignedItems.splice(index, 1); // removes the item at that index
    });
    // clear the selected item for the next ones
    this.assignedSelectedItems = [];
  }

}

模板看起来像这样selector.component.html

<div class="container">
    <div class="row">

        <div class="col-3">
            <select id="unassignedItems" class="form-select" multiple [(ngModel)]="unassignedSelectedItems">
                <option *ngFor="let item of unassignedItems" [ngValue]="item">{{item.name}}</option>
            </select>
        </div>

        <div class="col-1 align-middle" >
            <button id="assignedItemButton" [disabled]="unassignedItems.length==0" class="btn btn-primary m-1" type="button" (click)="assignSelections()">&gt;</button>
            <button id="unassignedItemButton" [disabled]="assignedItems.length==0" class="btn btn-primary m-1" type="button" (click)="unassignSelections()">&lt;</button>
        </div>

        <div class="col-3">
            <select id="assignedItems" class="form-select" multiple [(ngModel)]="assignedSelectedItems">
                <option *ngFor="let item of assignedItems" [ngValue]="item">{{item.name}}</option>
            </select>
        </div>

    </div>
</div>

棘手的一个,测试原生 multi select。问题是,<select> 并未反映其 value 中的所有 selected 值,仅反映其中一个。因此将其设置为多个值不会有任何效果。考虑到 extract multiple selected values from a select 的尴尬方式,以及测试本机行为和 ngModel 可能不是(也不应该是)您的目标这一事实,我会设置 unassignedItemsassignedItems 手动。

但是如果你真的想在你的测试中以“原生”方式模拟这个,设置你想要的选项 select 比如

options[0].selected = true;

然后发出 change 事件。这将更新 <select>selectedOptions 属性,它由 angular 的 SelectMultipleControlValueAccessor 内部使用。如果您觉得有趣,请检查它的 code。该代码将在 change 事件上执行,获取 selectedOptions' 值,并将它们传播到与 [(ngModel)].

关联的变量中