Модульное тестирование компонента, содержащего ngbTypeahead

У меня есть компонент, который содержит форму с 3 входными текстами. Два входа — это чистые текстовые поля, а одно — текстовое поле с директивой ngbTypeahead ng-bootstrap. Моя форма построена с использованием FormBuilder (реактивная форма).

 this.form = fb.group({
  department: [''],
  name: ['', Validators.required],
  location: ['', Validators.required]
});

Мой шаблон выглядит так:

<input type="text" class="form-control" formControlName="name"/>
...
<input type="text" class="form-control" formControlName="location"/>
...
<input
    type="text"
    class="form-control"
    formControlName="department"
    [ngbTypeahead]="autocompleteDepartments"
    [resultFormatter]="formatDepartment"
    [inputFormatter]="formatDepartment"/>

Компонент содержит функции для ngbTypeahead

autocompleteDepartments(text$: Observable<string>): Observable<Department> {
    ....
}
formatDepartment(department: Department) {
    return department.name;
}

Итак, this.form.department.value — это не строка, а такой объект:

interface Department {
  id: number;
  name: string;
  foo: boolean;
  bar: number;
  ...
}

Все работает нормально.

Теперь я хочу протестировать свой компонент, и для этого мне нужно установить значение для каждого из трех входов. Для двух чистых входов проблем нет:

const nameHtmlEl = <HTMLInputElement>fixture.debugElement.query(By.css('[formControlName="name"]')).nativeElement;
nameHtmlEl.value = "Toto";
nameHtmlEl.dispatchEvent(new Event('input'));

Но для ввода с директивой ngbTypeahead я не знаю, как установить значение (которое должно быть объектом отдела, а не строкой): я пробовал это, но это не работает:

const departmentHtmlEl = /*<HTMLInputElement>*/ fixture.debugElement.query(By.css('[formControlName="department"]')).nativeElement;
departmentHtmlEl.value = <Department>{id: 10, name: "Foo", ...};
departmentHtmlEl.dispatchEvent(new Event('input'));

person gentiane    schedule 15.09.2017    source источник


Ответы (1)


Я полагаю, вы пытаетесь имитировать выбор одного из отфильтрованных элементов для Typeahead.

Я бы сделал это так, чтобы по-прежнему устанавливать ключевую строку, которую вы ищете:

departmentHtmlEl.value = 'Foo';

если вы ищете по имени.

затем я бы смоделировал выбор. Это вы могли бы сделать с помощью

getWindowLinks(fixture.debugElement)[0].triggerEventHandler('click', {});

где getWindowLinks:

function getWindowLinks(element: DebugElement): DebugElement[] {
  return Array.from(element.queryAll(By.css('button.dropdown-item')));
}

Кроме того, вам придется использовать fakeAsync, чтобы сделать эту работу. Пример теста будет выглядеть примерно так:

 it('sample test', fakeAsync(() => {
    const departmentHtmlEl = /*<HTMLInputElement>*/ fixture.debugElement.query(By.css('[formControlName="department"]')).nativeElement;
    departmentHtmlEl.value = 'Foo';
    fixture.detectChanges();

    tick(300);
    // this should be more than the number on debounceTime you are using for the search

    getWindowLinks(fixture.debugElement)[0].triggerEventHandler('click', {});
    fixture.detectChanges();

    tick(300);

    // your expectation code here.
  }));

Надеюсь это поможет.

person Saurabh Lath    schedule 26.10.2017
comment
Это не сработало для меня. После изменения значения, обнаружения изменений и выполнения достаточно долгого tick() этих параметров button.dropdown-item по-прежнему не было в DOM. - person Jacob Stamm; 19.07.2018
comment
Привет @JacobStamm, если вы добавите следующее после изменения значения, это должно сработать. departmentHtmlEl.dispatchEvent(new Event('input')); - person user1906451; 24.10.2019
comment
Не забудьте вызвать flush() после tick, чтобы очистить очередь планировщика. - person strizzwald; 09.03.2021