From 565db018195b49ff03d61811a1f67fd008102968 Mon Sep 17 00:00:00 2001 From: Michal Kinas <113341662+MichalKinas@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:29:43 +0200 Subject: [PATCH] [MNT-25635] Search filter autocomplete search for tags when input changes (#11780) --- ...ilter-autocomplete-chips.component.spec.ts | 53 ++++++++----------- ...rch-filter-autocomplete-chips.component.ts | 21 +++++--- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.spec.ts b/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.spec.ts index 37310f7c8f..749ad5fa1d 100644 --- a/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.spec.ts @@ -18,7 +18,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { SearchFilterAutocompleteChipsComponent } from './search-filter-autocomplete-chips.component'; -import { EMPTY, of, ReplaySubject } from 'rxjs'; +import { of, ReplaySubject } from 'rxjs'; import { AutocompleteField, AutocompleteOption } from '../../models/autocomplete-option.interface'; import { TagService } from '../../../tag/services/tag.service'; import { SitesService } from '../../../common/services/sites.service'; @@ -33,13 +33,7 @@ describe('SearchFilterAutocompleteChipsComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [SearchFilterAutocompleteChipsComponent], - providers: [ - { - provide: TagService, - useValue: { getAllTheTags: () => EMPTY } - } - ] + imports: [SearchFilterAutocompleteChipsComponent] }); fixture = TestBed.createComponent(SearchFilterAutocompleteChipsComponent); @@ -86,23 +80,6 @@ describe('SearchFilterAutocompleteChipsComponent', () => { }); }); - it('should load tags if field = TAG', (done) => { - const tagPagingMock = { - list: { - pagination: {}, - entries: [{ entry: { tag: 'tag1', id: 'id1' } }, { entry: { tag: 'tag2', id: 'id2' } }] - } - }; - - component.settings.field = AutocompleteField.TAG; - spyOn(tagService, 'getAllTheTags').and.returnValue(of(tagPagingMock)); - component.ngOnInit(); - component.autocompleteOptions$.subscribe((result) => { - expect(result).toEqual([{ value: 'tag1' }, { value: 'tag2' }]); - done(); - }); - }); - it('should update display value when options changes', () => { const newOption = 'option1'; spyOn(component, 'onOptionsChange').and.callThrough(); @@ -215,13 +192,9 @@ describe('SearchFilterAutocompleteChipsComponent', () => { it('should use id if present, otherwise value, in LOCATION query fragment', () => { component.settings.field = AutocompleteField.LOCATION; component.settings.autocompleteOptions = []; - component.selectedOptions = [ - { id: 'site1', value: 'Marketing' }, - { value: 'custom' } - ]; + component.selectedOptions = [{ id: 'site1', value: 'Marketing' }, { value: 'custom' }]; component.submitValues(); - expect(component.context.queryFragments[component.id]) - .toBe('SITE:"site1" OR SITE:"custom"'); + expect(component.context.queryFragments[component.id]).toBe('SITE:"site1" OR SITE:"custom"'); }); it('should still call sitesService.getSites when input is empty for LOCATION field', () => { @@ -251,6 +224,22 @@ describe('SearchFilterAutocompleteChipsComponent', () => { expect(searchSpy).toHaveBeenCalledWith('', 0, 15); }); + it('should search for tags if field = TAG and input is not empty', () => { + component.settings.field = AutocompleteField.TAG; + const searchSpy = spyOn(tagService, 'searchTags').and.returnValue( + of({ + list: { + pagination: {}, + entries: [{ entry: { tag: 'tag1', id: 'id1' } }, { entry: { tag: 'tag2', id: 'id2' } }] + } + }) + ); + + component.onInputChange('tag'); + + expect(searchSpy).toHaveBeenCalledWith('tag', { orderBy: 'tag', direction: 'asc' }, false, 0, 15); + }); + describe('optionComparator', () => { it('should return false if either option is undefined', () => { expect(component.optionComparator(undefined, { value: 'A' })).toBe(false); @@ -258,7 +247,7 @@ describe('SearchFilterAutocompleteChipsComponent', () => { }); it('should compare by id if both have id', () => { - expect(component.optionComparator({ id: 'abc', value: 'B' } , { id: 'ABC', value: 'B' })).toBe(true); + expect(component.optionComparator({ id: 'abc', value: 'B' }, { id: 'ABC', value: 'B' })).toBe(true); expect(component.optionComparator({ id: 'abc', value: 'B' }, { id: 'def', value: 'B' })).toBe(false); }); diff --git a/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.ts b/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.ts index 3ef3f75ab5..ce02115a9a 100644 --- a/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.ts +++ b/lib/content-services/src/lib/search/components/search-filter-autocomplete-chips/search-filter-autocomplete-chips.component.ts @@ -124,6 +124,8 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI onInputChange(value: string) { if (this.settings.field === AutocompleteField.CATEGORIES) { this.searchForExistingCategories(value); + } else if (this.settings.field === AutocompleteField.TAG) { + this.searchForExistingTags(value); } else if (this.settings.field === AutocompleteField.LOCATION) { this.populateSitesOptions(); } @@ -166,13 +168,7 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI private setOptions() { switch (this.settings.field) { case AutocompleteField.TAG: - this.tagService.getAllTheTags().subscribe((tagPaging) => { - this.autocompleteOptionsSubject$.next( - tagPaging.list.entries.map((tag) => ({ - value: tag.entry.tag - })) - ); - }); + this.autocompleteOptionsSubject$.next([]); break; case AutocompleteField.CATEGORIES: this.autocompleteOptionsSubject$.next([]); @@ -197,6 +193,17 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI }); } + private searchForExistingTags(searchTerm: string) { + this.tagService.searchTags(searchTerm, { orderBy: 'tag', direction: 'asc' }, false, 0, 15).subscribe((existingTagsResult) => { + this.autocompleteOptionsSubject$.next( + existingTagsResult.list.entries.map((tag) => ({ + id: tag.entry.id, + value: tag.entry.tag + })) + ); + }); + } + private populateSitesOptions(): void { this.sitesService .getSites()