Что касается ошибки. Похоже, вам просто нужно импортировать By
. Это не что-то глобальное. Он должен быть импортирован из следующего модуля
import { By } from '@angular/platform-browser';
Что касается тестовой части, это то, что я смог выяснить. Когда вы меняете значение в компоненте, вам нужно инициировать обнаружение изменений, чтобы обновить представление. Вы делаете это с fixture.detectChanges()
. Как только это будет сделано, обычно представление должно быть обновлено значением.
Из тестирования чего-то похожего на ваш пример кажется, что это не так. Кажется, что после обнаружения изменений все еще выполняется какая-то асинхронная задача. Скажем, у нас есть следующее
const comp = fixture.componentInstance;
const select = fixture.debugElement.query(By.css('select'));
comp.selectedValue = 'a value';
fixture.DetectChanges();
expect(select.nativeElement.value).toEqual('1: a value');
Это не работает. Похоже, происходит какая-то асинхронность, из-за которой значение еще не установлено. Поэтому нам нужно дождаться асинхронных задач, вызвав fixture.whenStable
comp.selectedValue = 'a value';
fixture.DetectChanges();
fixture.whenStable().then(() => {
expect(select.nativeElement.value).toEqual('1: a value');
});
Вышеупомянутое будет работать. Но теперь нам нужно инициировать событие изменения, так как это не происходит автоматически.
fixture.whenStable().then(() => {
expect(select.nativeElement.value).toEqual('1: a value');
dispatchEvent(select.nativeElement, 'change');
fixture.detectChanges();
fixture.whenStable().then(() => {
// component expectations here
});
});
Теперь у нас есть еще одна асинхронная задача из события. Поэтому нам нужно снова стабилизировать его.
Ниже приведен полный тест, который я тестировал. Это рефакторинг примера из источника. тесты интеграции кода. Они использовали fakeAsync
и tick
, что похоже на использование async
и whenStable
. Но с fakeAsync
вы не можете использовать templateUrl
, поэтому я решил, что было бы лучше реорганизовать его, чтобы использовать async
.
Кроме того, тесты исходного кода выполняют своего рода двойное одностороннее тестирование, сначала тестируя модель для просмотра, а затем просмотр для модели. Хотя похоже, что ваш тест пытался провести двусторонний тест, от модели к модели. Поэтому я немного изменил его, чтобы лучше соответствовать вашему примеру.
import { Component } from '@angular/core';
import { TestBed, getTestBed, async } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { dispatchEvent } from '@angular/platform-browser/testing/browser_util';
@Component({
selector: 'ng-model-select-form',
template: `
<select [(ngModel)]="selectedCity" (ngModelChange)="onSelected($event)">
<option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option>
</select>
`
})
class NgModelSelectForm {
selectedCity: {[k: string]: string} = {};
cities: any[] = [];
onSelected(value) {
}
}
describe('component: NgModelSelectForm', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ FormsModule ],
declarations: [ NgModelSelectForm ]
});
});
it('should go from model to change event', async(() => {
const fixture = TestBed.createComponent(NgModelSelectForm);
const comp = fixture.componentInstance;
spyOn(comp, 'onSelected');
comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}];
comp.selectedCity = comp.cities[1];
fixture.detectChanges();
const select = fixture.debugElement.query(By.css('select'));
fixture.whenStable().then(() => {
dispatchEvent(select.nativeElement, 'change');
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(comp.onSelected).toHaveBeenCalledWith({name : 'NYC'});
console.log('after expect NYC');
});
});
}));
});
person
Paul Samsotha
schedule
30.09.2016