'How to unit-test a valuechange of mat-autocomplete filtered search result in Angular?
I use the mat-autocomplete functionality for searching in projects and want to test if entering a search string, which cannot be found in the project list, leads to a zero result.
It's working fine in the browser, but I cannot get the test working.
Template:
<div class="sidebar__header--count" data-test-sidebar-project-count>
<span>Projects</span> ({{ (filteredProjects | async).length }})
</div>
...
<div class="searchbar">
<mat-form-field class="searchbar__input">
<input
matInput
data-test-search-input
[formControl]="searchControl" />
</mat-form-field>
</div>
<div class="nav__list" *ngIf="(filteredProjects | async).length !== 0">
<mat-nav-list>...output...</mat-nav-list>
</div>
Component:
...
export class SidebarComponent {
@Input() projects: ProjectData[];
searchControl: FormControl = new FormControl();
filteredProjects: Observable<ProjectData[]>;
constructor() {
this.filteredProjects = this.searchControl.valueChanges.pipe(
startWith(''),
map(project =>
project ? this.filterProjects(project) : this.projects.slice()
)
);
}
private filterProjects(value: string): ProjectData[] {
return this.projects.filter(project =>
[project.key, project.name].some(
str => str?.toLowerCase().indexOf(value?.toLowerCase().trim()) >= 0
)
);
}
}
Test:
...
it('should reduce initial project list based on search criteria', done => {
/* given */
component.projects = [
{
name: 'FooProject1',
key: 'FOO1'
},
{
name: 'FooProject2',
key: 'FOO2'
}
] as any;
fixture.detectChanges();
/* when */
component.searchControl.setValue('bla');
fixture.detectChanges();
/* then */
component.filteredProjects.subscribe(result => {
expect(result.length).toBe(0);
done();
});
In the test the filteredProjects
doesn't get reduced to zero and stays at a length of 2.
I also tried a different approach with checking for a string in the HTML like this:
/* then */
const sidebarProjectCountElement = fixture.debugElement.nativeElement.querySelector('[data-test-sidebar-project-count]');
expect(sidebarProjectCountElement).toContainText('(0)');
But this also doesn't work.
Solution 1:[1]
The reason you are not able to get filtered projects is because youare setting the subscription AFTER you are setting searchControl
's value.
I was also facing similar challenge and below is how I fixed it.
it('should reduce initial project list based on search criteria', () => {
/* given */
component.projects = [
{ name: 'FooProject1', key: 'FOO1' },
{ name: 'FooProject2', key: 'FOO2' }
] as any;
fixture.detectChanges();
let output;
/* first of all, set the subscription in test */
component.filteredProjects.subscribe(result => {
output = result;
});
component.searchControl.setValue('bla');
fixture.detectChanges();
/* then */
expect(output.length).toEqual(0);
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Paritosh |