Написание модульного теста для компонента, который использует mat-autocomplete - PullRequest
0 голосов
/ 20 мая 2018

Я новичок в Angular, я пытаюсь создать текстовое поле с автозаполнением, используя Angular 5.

Я нашел этот пример в Документы Angular Material :

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

Мне было интересно, как написать модульный тест для проверки функциональности автозаполнения.Я устанавливаю значение для элемента input и запускаю событие 'input' и пытался выбрать элементы 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>

Spec-файл:

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 (), это как-то связано с использованием матового ввода углового материала.Есть ли что-то, что я должен сделать, чтобы вызвать открытие панели опций mat?

Как мне сделать этот тест работоспособным?

Ответы [ 2 ]

0 голосов
/ 20 августа 2019
Комментарий

@ Adam к предыдущему ответу привел меня к собственному тесту mat-autocomplete компонента , особенно здесь .Где вы можете видеть, что focusin - это событие, которое открывает «опции».

Но они фактически открываются в оверлее вне вашего компонента, поэтому в моем тесте fixture.nativeElement.querySelectorAll('mat-option').length было 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();
0 голосов
/ 29 мая 2018

Вам нужно добавить больше событий.У меня была более или менее та же проблема, что и у вас, и она сработала только тогда, когда я запустил событие focusin.

Я использую эти события в своем коде.Не уверен, что все это необходимо.

inputElement.dispatchEvent(new Event('focus'));
inputElement.dispatchEvent(new Event('focusin'));
inputElement.dispatchEvent(new Event('input'));
inputElement.dispatchEvent(new Event('keydown'));

Вам необходимо добавить это в функцию sendInput ...

...