angular/adev/shared-docs/components/search-dialog/search-dialog.component.spec.ts
Matthieu Riegler 3a85031dc0 docs(docs-infra): Modernize tests
Remove usages of `detectChanges` and rely on `whenStable`.
This commit also removed the usage of `provideZonelessChangeDetection` which is no longer necessary.
2026-01-05 11:47:08 -05:00

170 lines
5.1 KiB
TypeScript

/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {ApplicationRef} from '@angular/core';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {Router, provideRouter} from '@angular/router';
import {SearchDialog} from './search-dialog.component';
import {ENVIRONMENT, WINDOW} from '../../providers';
import {ALGOLIA_CLIENT, Search} from '../../services';
import {FakeEventTarget} from '../../testing/index';
import {AlgoliaIcon} from '../algolia-icon/algolia-icon.component';
import {SearchResult} from '../../interfaces';
describe('SearchDialog', () => {
let fixture: ComponentFixture<SearchDialog>;
const searchResults = jasmine.createSpy();
const fakeWindow = new FakeEventTarget();
let search: Search;
beforeEach(async () => {
searchResults.and.returnValue([]);
TestBed.configureTestingModule({
imports: [SearchDialog],
providers: [
provideRouter([]),
{provide: ENVIRONMENT, useValue: {algolia: {index: 'fakeIndex'}}},
{provide: ALGOLIA_CLIENT, useValue: {search: searchResults}},
{provide: WINDOW, useValue: fakeWindow},
],
});
fixture = TestBed.createComponent(SearchDialog);
search = TestBed.inject(Search);
await fixture.whenStable();
});
it('should navigate to active item when user pressed Enter', async () => {
const router = TestBed.inject(Router);
const navigateByUrlSpy = spyOn(router, 'navigateByUrl');
search.searchQuery.set('fakeQuery');
searchResults.and.returnValue(Promise.resolve({results: [{hits: fakeSearchResults}]}));
// Fire the request
TestBed.inject(ApplicationRef).tick();
// Wait for the resource to resolve
await TestBed.inject(ApplicationRef).whenStable();
fakeWindow.dispatchEvent(
new KeyboardEvent('keydown', {
code: 'Enter',
key: 'Enter',
charCode: 13,
keyCode: 13,
view: window,
bubbles: true,
}),
);
expect(navigateByUrlSpy).toHaveBeenCalledOnceWith('fakeUrl1#h1');
});
it('should always display algolia logo', () => {
const algoliaIcon = fixture.debugElement.query(By.directive(AlgoliaIcon));
expect(algoliaIcon).toBeTruthy();
});
it('should display `No results found` message when there are no results for provided query', async () => {
search.searchQuery.set('fakeQuery');
searchResults.and.returnValue(Promise.resolve({results: [{hits: []}]}));
// Fire the request
TestBed.inject(ApplicationRef).tick();
// Wait for the resource to resolve
await TestBed.inject(ApplicationRef).whenStable();
const noResultsContainer = fixture.debugElement.query(
By.css('.docs-search-results__no-results'),
);
expect(noResultsContainer).toBeTruthy();
});
it('should display `Start typing to see results` message when there are no provided query', () => {
searchResults.and.returnValue(undefined);
const startTypingContainer = fixture.debugElement.query(
By.css('.docs-search-results__start-typing'),
);
expect(startTypingContainer).toBeTruthy();
});
it('should display list of the search results when results exist', async () => {
search.searchQuery.set('fakeQuery');
searchResults.and.returnValue(Promise.resolve({results: [{hits: fakeSearchResults}]}));
// Fire the request
TestBed.inject(ApplicationRef).tick();
// Wait for the resource to resolve
await TestBed.inject(ApplicationRef).whenStable();
const resultListContainer = fixture.debugElement.query(By.css('ul.docs-search-results'));
const resultItems = fixture.debugElement.queryAll(By.css('ul.docs-search-results li a'));
expect(resultListContainer).toBeTruthy();
expect(resultItems.length).toBe(2);
expect(resultItems[0].nativeElement.href).toBe(`${window.origin}/fakeUrl1#h1`);
expect(resultItems[1].nativeElement.href).toBe(`${window.origin}/fakeUrl2#h1`);
});
it('should close search dialog when user clicked outside `.docs-search-container`', () => {
const dialogContainer = fixture.debugElement.query(By.css('dialog'));
const closeSearchDialogSpy = spyOn(fixture.componentInstance, 'closeSearchDialog');
dialogContainer.nativeElement.click();
expect(closeSearchDialogSpy).toHaveBeenCalled();
});
});
const fakeSearchResults = [
{
'url': 'https://angular.dev/fakeUrl1#h1',
'hierarchy': {
'lvl0': 'FakeLvl0',
'lvl1': 'FakeLvl1',
'lvl2': 'FakeLvl2',
'lvl3': null,
'lvl4': null,
'lvl5': null,
'lvl6': null,
},
'objectID': 'fakeObjectId1',
_snippetResult: {},
type: '',
content: null,
},
{
'url': 'https://angular.dev/fakeUrl2#h1',
'hierarchy': {
'lvl0': 'FakeLvl0',
'lvl1': 'FakeLvl1',
'lvl2': 'FakeLvl2',
'lvl3': null,
'lvl4': null,
'lvl5': null,
'lvl6': null,
},
'objectID': 'fakeObjectId2',
type: '',
content: null,
_snippetResult: {},
},
] satisfies SearchResult[];