为使用 mat-autocomplete 的组件编写单元测试

2024-03-24

我是 Angular 的新手,我正在尝试使用 Angular 5 构建一个具有自动完成功能的文本字段。

我在中找到了这个例子角度材质文档 https://material.angular.io/components/autocomplete/examples:

https://stackblitz.com/angular/kopqvokeddbq?file=app%2Fautocomplete-overview-example.ts https://stackblitz.com/angular/kopqvokeddbq?file=app%2Fautocomplete-overview-example.ts

我想知道如何编写单元测试来测试自动完成功能。我正在为输入元素设置一个值并触发“输入”事件,并尝试选择 mat-option 元素,但发现它们都没有创建:

我的组件 html 的相关部分:

<form>
  <mat-form-field class="input-with-icon">
    <div>
      <i ngClass="jf jf-search jf-lg md-primary icon"></i>
      <input #nameInput matInput class="input-field-with-icon" placeholder="Type name here"
             type="search" [matAutocomplete]="auto" [formControl]="userFormControl" [value]="inputField">
    </div>
  </mat-form-field>
</form>

<mat-autocomplete #auto="matAutocomplete">
  <mat-option *ngFor="let option of filteredOptions | async" [value]="option.name"
              (onSelectionChange)="onNameSelect(option)">
    {{ option.name }}
  </mat-option>
</mat-autocomplete>

规格文件:

it('should filter users based on input', fakeAsync(() => {
    const hostElement = fixture.nativeElement;

    sendInput('john').then(() => {
        fixture.detectChanges();
        expect(fixture.nativeElement.querySelectorAll('mat-option').length).toBe(1);

        expect(hostElement.textContent).toContain('John Rambo');
    });
}));
function sendInput(text: string) {
    let inputElement: HTMLInputElement;

    inputElement = fixture.nativeElement.querySelector('input');
    inputElement.focus();
    inputElement.value = text;
    inputElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    return fixture.whenStable();
}

组件 HTML:

userFormControl: FormControl = new FormControl();

ngOnInit() {
    this.filteredOptions = this.userFormControl.valueChanges
        .pipe(
            startWith(''),
            map(val => this.filter(val))
        );
}

filter(val: string): User[] {
    if (val.length >= 3) {
        console.log(' in filter');
        return this.users.filter(user =>
            user.name.toLowerCase().includes(val.toLowerCase()));
    }
}

在此之前,我意识到为了使 FormControl 对象设置值,我必须首先执行 inputElement.focus() ,这与使用角度材料的垫输入有关。我需要做些什么才能触发打开垫子选项窗格吗?

我该如何让这个测试发挥作用?


@Adam https://stackoverflow.com/users/954940/adam对之前答案的评论让我想到了mat-autocomplete组件自己的测试 https://github.com/angular/components/blob/master/src/material/autocomplete/autocomplete.spec.ts, 特别是here https://github.com/angular/components/blob/master/src/material/autocomplete/autocomplete.spec.ts#L2026。你在哪里可以看到focusin是打开“选项”的事件。

但它们实际上在组件外部的覆盖层中打开,所以在我的测试中fixture.nativeElement.querySelectorAll('mat-option').length was 0但如果我查询该元素document.querySelectorAll('mat-option')我得到了预期数量的选项。

总结一下:

    fixture.detectChanges();
    const inputElement = fixture.debugElement.query(By.css('input')); // Returns DebugElement
    inputElement.nativeElement.dispatchEvent(new Event('focusin'));
    inputElement.nativeElement.value = text;
    inputElement.nativeElement.dispatchEvent(new Event('input'));

    fixture.detectChanges();
    await fixture.whenStable();
    fixture.detectChanges();

    const matOptions = document.querySelectorAll('mat-option');
    expect(matOptions.length).toBe(3,
      'Expect to have less options after input text and filter');

额外球:如果您想单击一个选项(我就是这样做),您可以像这样继续:

    const optionToClick = matOptions[0] as HTMLElement;
    optionToClick.click();
    fixture.detectChanges();

尽管我没有成功单击并将值输入到输入中。 ???? 嗯,我不是专家测试人员,但这种行为可能应该包含在自己的测试中mat-autocomplete的测试(实际上是这样)并依赖它?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为使用 mat-autocomplete 的组件编写单元测试 的相关文章

随机推荐