Reputation: 7165
I have a select
element in my template as follows:
<select [(ngModel)]="snapshotCriteria.salesArea" required>
<option *ngFor="let salesArea of salesAreas" [ngValue]="salesArea">
{{salesArea.name}}
</option>
</select>
You can see that the model is bound to snapshotCriteria.salesArea
which is an object so we use ngValue
instead of value
. The salesArea
property itself is also an object.
The component is as follows:
export class Component implements OnInit {
salesAreas: SalesArea[];
snapshotCriteria: SnapshotCriteria = {
salesArea: null,
date: null,
startTime: 600,
endTime: 3059
};
constructor(private salesAreaService: SalesAreaService) {}
ngOnInit(): void {
this.salesAreaService.fetchSalesAreas(salesAreas) => this.salesAreas = salesAreas);
}
}
Note that salesArea
which is bound to the select
model is initialised to null
.
The template functions correctly when changes are made via the template by manipulating the dropdown. However in my unit tests, I directly update the model which the select
element references and contrary to what I'd expect, the view is not updated! As the field is required, my test is unable to submit the form as validation fails. This is the test:
it('...', fakeAsync(() => {
spyOn(salesAreaService, 'fetchSalesAreas').and.returnValue(Observable.of([
{areaNumber: 1, name: 'A'} as any as SalesArea,
{areaNumber: 2, name: 'B'} as any as SalesArea,
{areaNumber: 3, name: 'C'} as any as SalesArea
]));
fixture.detectChanges();
tick();
component.snapshotCriteria = {
salesArea: {areaNumber: 1, name: 'A'} as SalesArea,
date: new Date(2015, 5, 25),
startTime: 1000,
endTime: 1001
} as SnapshotCriteria;
fixture.detectChanges();
tick();
}));
Debugging shows that the select
element is not updated. I have tried various things to no avail:
salesArea
object to an empty object instead of
null
.input
and change
events in the test.ngModelChange
in the view but this is not triggered
in the test.A note of interest is that by using value
over ngValue
in the template, I am able to update the view by changing the underlying model.
Upvotes: 2
Views: 990
Reputation: 214175
I assume you need to do as follows:
it('...', fakeAsync(() => {
var mockArr = [
{areaNumber: 1, name: 'A'} as any as SalesArea,
{areaNumber: 2, name: 'B'} as any as SalesArea,
{areaNumber: 3, name: 'C'} as any as SalesArea
];
spyOn(salesAreaService, 'fetchSalesAreas').and.returnValue(Observable.of(mockArr));
fixture.detectChanges();
tick();
component.snapshotCriteria = {
salesArea: mockArr.find(x => x.areaNumber === 1),
date: new Date(2015, 5, 25),
startTime: 1000,
endTime: 1001
} as SnapshotCriteria;
fixture.detectChanges();
tick();
expect(...);
}));
Upvotes: 2