#angular #unit-testing #angular-material #jasmine #mat-select
Вопрос:
У меня есть следующий шаблон:
<mat-select #select>
<mat-option *ngFor="let option of optionsData">
{{ select.panelOpen ? option.viewValue : option.value }}
</mat-option>
</mat-select>
И следующий тест, который не проходит:
it('should populate options list with view values', async () => {
const expected = optionsData.map(o => o.viewValue);
const select = de.query(By.css('.mat-select')).nativeElement;
select.click();
fixture.detectChanges();
await fixture.whenStable().then(() => {
for (const option of select.children) {
expect(expected.findIndex(e => e === option.textContent)).toBeGreaterThan(-1);
}
});
});
Но если я изменю первую строку в тесте на:
const expected = optionsData.map(o => o.value)
Тогда испытание пройдет. Это означает, что panelOpen всегда имеет значение false и получает только значение вместо значения представления, даже если я нажал на элемент «выбрать».
Почему функция click() не меняет значение panelOpen с false на true?
Ответ №1:
Я исправил эту проблему с помощью директивы
import { OnInit, Directive, EventEmitter, Output } from '@angular/core';
import { MatSelect } from '@angular/material/select';
@Directive({
selector: '[athMatOptionDirective]'
})
export class MatOptionDirective implements OnInit {
@Output() matOptionState: EventEmitter<any> = new EventEmitter();
constructor(private matSelect: MatSelect) { }
ngOnInit() {
this.matSelect.openedChange.subscribe(isOpen => {
if(isOpen) return this.matOptionState.emit(true)
return this.matOptionState.emit(false)
})
}
}
в вашем html-компоненте:
<mat-form-field>
<mat-select athMatOptionDirective (matOptionState)="getMatOptionState(event)">
</mat-select>
</mat-form-field
компонент машинописного текста:
getMatOptionState(event) {
console.log('is mat-option open?', event)
}
Большое спасибо Юрию Штрумпфлонеру (https://juristr.com/blog/2020/06/access-material-select-options)
пример здесь: stackblitz