/// /// Copyright 2015-2026 Micro Focus or one of its affiliates. /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// import { O, SHIFT, TAB } from '@angular/cdk/keycodes'; import { Component } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { dispatchKeyboardEvent } from '../../common/testing/dispatch-event'; import { InfiniteScrollLoadFunction } from '../../directives/infinite-scroll/index'; import { SelectComponent } from './select.component'; import { SelectModule } from './select.module'; @Component({ selector: 'app-select-test', template: ` @if (visible) { } `, imports: [SelectModule], }) export class SelectTestComponent { input: string = ''; value: string | string[]; options: string[] | InfiniteScrollLoadFunction = ['One', 'Two', 'Three']; multiple: boolean = false; required: boolean = false; allowNull: boolean = false; clearButton: boolean = false; visible: boolean = true; placeholder: string; pageSize: number = 20; dropdownOpen: boolean = false; readonlyInput: boolean = false; ariaLabelledby: string; // eslint-disable-next-line @typescript-eslint/no-empty-function onValueChange(): void {} // eslint-disable-next-line @typescript-eslint/no-empty-function onInputChange(): void {} } describe('Select Component', () => { let component: SelectTestComponent; let fixture: ComponentFixture; let nativeElement: HTMLElement; beforeEach(() => { TestBed.configureTestingModule({ imports: [SelectModule, SelectTestComponent], }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(SelectTestComponent); component = fixture.componentInstance; nativeElement = fixture.nativeElement; fixture.detectChanges(); }); it('should display placeholder as empty string if not set', () => { const placeholderTextInitial = fixture.nativeElement.querySelector('input').placeholder; expect(placeholderTextInitial).toBe(''); component.placeholder = 'Placeholder Text'; fixture.detectChanges(); const placeholderText = fixture.nativeElement.querySelector('input').placeholder; expect(placeholderText).toBe('Placeholder Text'); }); it('should not call valueChange on initialization of single select', () => { spyOn(component, 'onValueChange'); expect(component).toBeTruthy(); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should not call valueChange on initialization of multiple select', () => { spyOn(component, 'onValueChange'); component.multiple = true; fixture.detectChanges(); expect(component).toBeTruthy(); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should not call inputChange on initialization of single select', () => { spyOn(component, 'onInputChange'); expect(component).toBeTruthy(); expect(component.onInputChange).not.toHaveBeenCalled(); }); it('should not call inputChange on initialization of multiple select', () => { component.multiple = true; fixture.detectChanges(); spyOn(component, 'onInputChange'); expect(component).toBeTruthy(); expect(component.onInputChange).not.toHaveBeenCalled(); }); it('should not call valueChange when the value Input is changed in single select', () => { spyOn(component, 'onValueChange'); component.value = 'One'; fixture.detectChanges(); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should call not valueChange when the value Input is changed in multiple select', () => { component.multiple = true; fixture.detectChanges(); spyOn(component, 'onValueChange'); component.value = [component.options[0]]; fixture.detectChanges(); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should call not inputChange when the input is changed in single select', () => { spyOn(component, 'onInputChange'); component.input = 'One'; fixture.detectChanges(); expect(component.onInputChange).not.toHaveBeenCalled(); }); it('should not call inputChange when the input is changed in multiple select', () => { component.multiple = true; fixture.detectChanges(); spyOn(component, 'onInputChange'); component.input = 'One'; fixture.detectChanges(); expect(component.onInputChange).not.toHaveBeenCalled(); }); it('should not show the clear button by default in single select', () => { expect(getClearButton()).toBeFalsy(); }); it('should not show the clear button by default in single select when allowNull is true', () => { component.allowNull = true; fixture.detectChanges(); expect(getClearButton()).toBeFalsy(); }); it('should not show the clear button by default in multiple select', () => { component.multiple = true; fixture.detectChanges(); expect(getClearButton(true)).toBeFalsy(); }); it('should not show the clear button when there is a value but allowNull is false in single select', () => { component.input = 'One'; component.value = 'One'; component.clearButton = true; fixture.detectChanges(); expect(getClearButton()).toBeFalsy(); }); it('should show the clear button when there is a value but allowNull is true in single select', () => { component.value = 'One'; component.allowNull = true; component.clearButton = true; fixture.detectChanges(); expect(getClearButton()).toBeTruthy(); }); it('should show the clear button when there is a value in multiple select', () => { component.multiple = true; fixture.detectChanges(); component.value = [component.options[0]]; component.clearButton = true; fixture.detectChanges(); expect(getClearButton(true)).toBeTruthy(); }); it('should clear the value when clear button is clicked in single select', () => { component.value = 'One'; component.allowNull = true; component.clearButton = true; fixture.detectChanges(); expect(getClearButton()).toBeTruthy(); // press the clear button getClearButton().click(); fixture.detectChanges(); expect(component.value).toBe(null); expect(component.input).toBe(null); }); it('should clear the value when clear button is click in multiple select', () => { component.multiple = true; fixture.detectChanges(); component.clearButton = true; component.value = [component.options[0]]; fixture.detectChanges(); expect(getClearButton(true)).toBeTruthy(); getClearButton(true).click(); fixture.detectChanges(); expect(component.value).toEqual([]); expect(component.input).toBe(''); }); it('should not lose current value when blurred', () => { component.input = 'One'; component.value = 'One'; fixture.detectChanges(); expect(component.value).toBe('One'); nativeElement.blur(); expect(component.value).toBe('One'); }); it('should reset to previous value when blurred and value does not match dropdown options', () => { component.input = 'One'; component.value = 'One'; fixture.detectChanges(); component.input = 'two'; fixture.detectChanges(); expect(component.input).toBe('two'); nativeElement.blur(); fixture.detectChanges(); expect(component.value).toBe('One'); }); it('should disable selected options when multiple = true', () => { component.multiple = true; component.value = ['One']; fixture.detectChanges(); const typeaheadOptions = nativeElement.querySelectorAll( '.ux-typeahead-options li' ); expect(typeaheadOptions.item(0).classList).toContain('disabled'); expect(typeaheadOptions.item(1).classList).not.toContain('disabled'); expect(typeaheadOptions.item(2).classList).not.toContain('disabled'); }); it('should re-enabled options when they are deselected when multiple = true', () => { component.multiple = true; component.value = ['One']; fixture.detectChanges(); // remove the selected item and it should be re-enabled component.value = []; fixture.detectChanges(); const typeaheadOptions = nativeElement.querySelectorAll( '.ux-typeahead-options li' ); expect(typeaheadOptions.item(0).classList).not.toContain('disabled'); expect(typeaheadOptions.item(1).classList).not.toContain('disabled'); expect(typeaheadOptions.item(2).classList).not.toContain('disabled'); }); it('should not allow a disabled option to be selected when multiple = true', () => { component.multiple = true; component.value = ['One']; fixture.detectChanges(); let tags = fixture.nativeElement.querySelectorAll('li.ux-tag'); expect(tags.length).toBe(1); nativeElement.querySelectorAll('.ux-typeahead-options li').item(0).click(); tags = fixture.nativeElement.querySelectorAll('li.ux-tag'); expect(tags.length).toBe(1); }); it('should disable selected options when multiple = true and pagination is enabled', async () => { enablePagination(); component.multiple = true; component.value = ['Option 1']; component.dropdownOpen = true; fixture.detectChanges(); await fixture.whenStable(); const typeaheadOptions = nativeElement.querySelectorAll( '.ux-typeahead-options li' ); expect(typeaheadOptions.item(0).classList).not.toContain('disabled'); expect(typeaheadOptions.item(1).classList).toContain('disabled'); expect(typeaheadOptions.item(2).classList).not.toContain('disabled'); }); it('should re-enable options when they are deselected when multiple = true and pagination is enabled', async () => { enablePagination(); component.multiple = true; component.value = ['Option 1']; component.dropdownOpen = true; fixture.detectChanges(); await fixture.whenStable(); // remove the selected item and it should be re-enabled component.value = []; fixture.detectChanges(); const typeaheadOptions = nativeElement.querySelectorAll( '.ux-typeahead-options li' ); expect(typeaheadOptions.item(0).classList).not.toContain('disabled'); expect(typeaheadOptions.item(1).classList).not.toContain('disabled'); expect(typeaheadOptions.item(2).classList).not.toContain('disabled'); }); it('should not allow a disabled option to be selected when multiple = true and pagination is enabled', async () => { enablePagination(); component.multiple = true; component.value = ['Option 1']; component.dropdownOpen = true; fixture.detectChanges(); await fixture.whenStable(); let tags = fixture.nativeElement.querySelectorAll('li.ux-tag'); expect(tags.length).toBe(1); nativeElement.querySelectorAll('.ux-typeahead-options li').item(1).click(); fixture.detectChanges(); tags = fixture.nativeElement.querySelectorAll('li.ux-tag'); expect(tags.length).toBe(1); }); it('should add a required attribute to the multiple select when required is true', () => { component.required = true; component.multiple = true; component.dropdownOpen = true; fixture.detectChanges(); const inputElementEmpty = nativeElement.querySelector('input.ux-tag-input'); const attributeRequired = inputElementEmpty.hasAttribute('required'); expect(attributeRequired).toBe(true); }); it('should add a required attribute to the single select when required is true', () => { component.required = true; component.dropdownOpen = true; fixture.detectChanges(); const inputElementEmpty = nativeElement.querySelector('input.form-control'); const attributeRequired = inputElementEmpty.hasAttribute('required'); expect(attributeRequired).toBe(true); }); it('should focus on input when icon is clicked', () => { component.readonlyInput = true; fixture.detectChanges(); const inputElement = nativeElement.querySelector('input.form-control'); const inputIcon = nativeElement.querySelector('i.ux-select-icon'); inputIcon.click(); expect(document.activeElement).toBe(inputElement); }); it('should not emit valueChange when programmatically changing value input', () => { spyOn(component, 'onValueChange'); component.value = 'Three'; fixture.detectChanges(); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should apply aria-labelledby to the input element', () => { component.ariaLabelledby = 'test-id'; fixture.detectChanges(); const inputElement = nativeElement.querySelector('input.form-control'); expect(inputElement.getAttribute('aria-labelledby')).toContain('test-id'); }); it('should apply aria-labelledby to the input element when multiple is true', () => { component.multiple = true; component.ariaLabelledby = 'test-id'; fixture.detectChanges(); const inputElement = nativeElement.querySelector('input.ux-tag-input'); expect(inputElement.getAttribute('aria-labelledby')).toContain('test-id'); }); function enablePagination(): void { component.options = function (pageNum: number, pageSize: number): Promise { return new Promise(resolve => { const items: string[] = []; if (pageNum >= 2) { resolve([]); } for (let idx = pageNum * pageSize; idx < (pageNum + 1) * pageSize; idx++) { items.push(`Option ${idx}`); } resolve(items); }); }; fixture.detectChanges(); } function getClearButton(isMultiple: boolean = false): HTMLElement | null { return nativeElement.querySelector( `.${isMultiple ? 'ux-tag-icon' : 'ux-select-icon'}.ux-icon-close` ); } }); @Component({ selector: 'app-select-value-test', template: ` `, imports: [SelectModule], }) export class SelectValueTestComponent { // eslint-disable-next-line @typescript-eslint/no-empty-function onValueChange(): void {} options: string[] = ['One', 'Two', 'Three']; value: string | string[]; multiple: boolean; } describe('Select Component - Value Input', () => { let component: SelectValueTestComponent; let fixture: ComponentFixture; let nativeElement: HTMLElement; beforeEach(() => { TestBed.configureTestingModule({ imports: [SelectModule, SelectValueTestComponent], }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(SelectValueTestComponent); component = fixture.componentInstance; nativeElement = fixture.nativeElement; }); it('should have an initial value set to One', async () => { spyOn(component, 'onValueChange'); component.value = component.options[0]; fixture.autoDetectChanges(); await fixture.whenStable(); const selectText = fixture.nativeElement.querySelector('input').value; expect(selectText).toEqual('One'); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should have an initial value set to One when multiple is true', async () => { spyOn(component, 'onValueChange'); component.multiple = true; component.value = [component.options[0]]; fixture.detectChanges(); await fixture.whenStable(); const tagText = fixture.nativeElement.querySelector('.ux-tag-text').innerText; expect(tagText).toBe('One'); expect(component.onValueChange).not.toHaveBeenCalled(); }); }); @Component({ selector: 'app-select-ng-model-test', template: ` `, imports: [SelectModule, FormsModule], }) export class SelectNgModelTestComponent { options: string[] = ['One', 'Two', 'Three']; value: string | string[]; multiple: boolean = false; // eslint-disable-next-line @typescript-eslint/no-empty-function onValueChange(): void {} } describe('Select Component - NgModel Input', () => { let component: SelectNgModelTestComponent; let fixture: ComponentFixture; let nativeElement: HTMLElement; beforeEach(() => { TestBed.configureTestingModule({ imports: [SelectModule, FormsModule, SelectNgModelTestComponent], }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(SelectNgModelTestComponent); component = fixture.componentInstance; nativeElement = fixture.nativeElement; }); it('should have an initial value set to One', async () => { component.value = component.options[0]; fixture.autoDetectChanges(); await fixture.whenStable(); spyOn(component, 'onValueChange'); const selectText = fixture.nativeElement.querySelector('input').value; expect(selectText).toEqual('One'); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should have an initial value set to One when multiple is true', async () => { component.multiple = true; component.value = [component.options[0]]; fixture.autoDetectChanges(); await fixture.whenStable(); spyOn(component, 'onValueChange'); const tags = fixture.nativeElement.querySelectorAll('li.ux-tag'); expect(tags.length).toBe(1); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should change from untouched to touched when clicking the input in single mode', async () => { // await for forms to register handlers fixture.detectChanges(); await fixture.whenStable(); // get the select component instance const select = fixture.debugElement.query(By.directive(SelectComponent)).componentInstance; // spy on the touched event const touchedSpy = spyOn(select, '_onTouched'); component.multiple = false; component.value = component.options[0]; fixture.detectChanges(); await fixture.whenStable(); expect(touchedSpy).not.toHaveBeenCalled(); getSelect(component.multiple).dispatchEvent(new Event('focus')); fixture.detectChanges(); await fixture.whenStable(); expect(touchedSpy).toHaveBeenCalled(); }); it('should change from untouched to touched when clicking the input in multiple mode', async () => { // await for forms to register handlers fixture.detectChanges(); await fixture.whenStable(); // get the select component instance const select = fixture.debugElement.query(By.directive(SelectComponent)).componentInstance; // spy on the touched event const touchedSpy = spyOn(select, '_onTouched'); component.multiple = true; component.value = [component.options[0]]; fixture.detectChanges(); await fixture.whenStable(); expect(touchedSpy).not.toHaveBeenCalled(); getMultipleSelectInput().dispatchEvent(new Event('focus')); fixture.detectChanges(); await fixture.whenStable(); expect(touchedSpy).toHaveBeenCalled(); }); it('should not open dropdown when tabbing past select', async () => { fixture.detectChanges(); const input = getInput(); input.focus(); dispatchKeyboardEvent(input, 'keydown', TAB, null, 'Tab'); await fixture.whenStable(); fixture.detectChanges(); expect(getTypeahead()).toBeFalsy(); }); it('should not open dropdown when pressing a not printable key such as shift', async () => { fixture.detectChanges(); const input = getInput(); input.focus(); dispatchKeyboardEvent(input, 'keydown', SHIFT, null, 'Shift'); await fixture.whenStable(); fixture.detectChanges(); expect(getTypeahead()).toBeFalsy(); }); it('should open dropdown when entering value', async () => { fixture.detectChanges(); const input = getInput(); input.focus(); dispatchKeyboardEvent(input, 'keydown', O, null, 'o'); component.value = 'O'; fixture.detectChanges(); await fixture.whenStable(); expect(getTypeahead()).toBeTruthy(); }); function getInput(): HTMLElement | null { return nativeElement.querySelector('input.form-control'); } function getTypeahead(): HTMLElement | null { return nativeElement.querySelector('ux-typeahead.open'); } function getSelect(isMultiple: boolean): HTMLElement | null { return nativeElement.querySelector( `ux-select ${isMultiple ? 'ux-tag-input' : 'input.form-control'}` ); } function getMultipleSelectInput(): HTMLInputElement { return nativeElement.querySelector('input.ux-tag-input'); } }); @Component({ selector: 'app-select-reactive-form-test', template: `
`, imports: [SelectModule, ReactiveFormsModule], }) export class SelectReactiveFormTestComponent { multiple: boolean = false; form = new FormGroup({ select: new FormControl('One'), }); options: string[] = ['One', 'Two', 'Three']; // eslint-disable-next-line @typescript-eslint/no-empty-function onValueChange(): void {} } describe('Select Component - Reactive Form Input', () => { let component: SelectReactiveFormTestComponent; let fixture: ComponentFixture; let nativeElement: HTMLElement; beforeEach(() => { TestBed.configureTestingModule({ imports: [SelectModule, ReactiveFormsModule, SelectReactiveFormTestComponent], }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(SelectReactiveFormTestComponent); component = fixture.componentInstance; nativeElement = fixture.nativeElement; }); it('should have an initial value set One', async () => { fixture.autoDetectChanges(); await fixture.whenStable(); spyOn(component, 'onValueChange'); const selectText = fixture.nativeElement.querySelector('input').value; expect(selectText).toEqual('One'); expect(component.onValueChange).not.toHaveBeenCalled(); }); it('should have an initial value set One when multiple is true', () => { component.multiple = true; component.form.setValue({ select: ['One'], }); fixture.detectChanges(); spyOn(component, 'onValueChange'); const tagText = fixture.nativeElement.querySelector('.ux-tag-text').innerText; expect(tagText).toBe('One'); expect(component.onValueChange).not.toHaveBeenCalled(); }); }); @Component({ selector: 'app-select-test', template: ` @if (visible) { @if (multiple) {
}
} `, imports: [SelectModule], }) export class SingleSelectWithCustomIconTestComponent { input: string = ''; value: string | string[]; options: string[] = ['One', 'Two', 'Three']; multiple: boolean = false; allowNull: boolean = false; clearButton: boolean = false; visible: boolean = true; placeholder: string; // eslint-disable-next-line @typescript-eslint/no-empty-function onValueChange(): void {} // eslint-disable-next-line @typescript-eslint/no-empty-function onInputChange(): void {} } describe('Select Component - With custom Icon', () => { let component: SingleSelectWithCustomIconTestComponent; let fixture: ComponentFixture; let nativeElement: HTMLElement; beforeEach(() => { TestBed.configureTestingModule({ imports: [SelectModule, SingleSelectWithCustomIconTestComponent], }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(SingleSelectWithCustomIconTestComponent); component = fixture.componentInstance; nativeElement = fixture.nativeElement; }); it('should close the dropdown when clicking on custom icon multiple mode', () => { component.multiple = true; component.value = [component.options[0]]; fixture.detectChanges(); // click on icon to open typeahead, expect a class of open getCustomIcon().click(); fixture.detectChanges(); expect(getTypeahead()).toBeTruthy(); // Click on button again to close, expect no class of open getCustomIcon().click(); fixture.detectChanges(); expect(getTypeahead()).toBeFalsy(); fixture.detectChanges(); }); it('should close the dropdown when clicking on custom icon single mode', () => { component.multiple = false; component.value = component.options[0]; fixture.detectChanges(); // click on icon to open typeahead, expect a class of open getCustomIcon().click(); fixture.detectChanges(); expect(getTypeahead()).toBeTruthy(); fixture.detectChanges(); // Click on button again to close, expect no class of open getCustomIcon().click(); fixture.detectChanges(); expect(getTypeahead()).toBeFalsy(); fixture.detectChanges(); }); function getTypeahead(): HTMLElement | null { return nativeElement.querySelector('ux-typeahead.open'); } function getCustomIcon(): HTMLElement | null { return nativeElement.querySelector('.ux-select-icon'); } }); @Component({ selector: 'app-select-with-recent-options-test', template: ` `, imports: [SelectModule], }) export class SelectWithRecentOptionsTestComponent { value: string | string[]; options: string[] = ['One', 'Two', 'Three']; multiple: boolean = false; allowNull: boolean = false; dropdownOpen: boolean = true; recentOptions: string[] = []; recentOptionsMaxCount = 2; // eslint-disable-next-line @typescript-eslint/no-empty-function onRecentOptionsChange(_: string[]): void {} } describe('Select with recent options', () => { let component: SelectWithRecentOptionsTestComponent; let fixture: ComponentFixture; let nativeElement: HTMLElement; beforeEach(() => { TestBed.configureTestingModule({ imports: [SelectModule, SelectWithRecentOptionsTestComponent], }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(SelectWithRecentOptionsTestComponent); component = fixture.componentInstance; nativeElement = fixture.nativeElement; fixture.detectChanges(); }); it('should initially display no recent options', () => { expect(nativeElement.querySelector('.ux-typeahead-recent-options')).toBeNull(); }); it('should display provided recent options', () => { component.recentOptions = ['One', 'Two']; fixture.detectChanges(); expect(nativeElement.querySelector('.ux-typeahead-recent-options')).not.toBeNull(); const recentOptionListItems = nativeElement.querySelectorAll('.ux-typeahead-recent-options li'); expect(recentOptionListItems.length).toBe(2); expect((recentOptionListItems[0] as HTMLElement).innerText).toBe('One'); expect((recentOptionListItems[1] as HTMLElement).innerText).toBe('Two'); }); it('should not allow more than the maximum recent options', async () => { component.recentOptions = ['One', 'Two', 'Three']; fixture.detectChanges(); await fixture.whenStable(); expect(nativeElement.querySelector('.ux-typeahead-recent-options')).not.toBeNull(); const recentOptionListItems = nativeElement.querySelectorAll('.ux-typeahead-recent-options li'); expect(recentOptionListItems.length).toBe(2); expect((recentOptionListItems[0] as HTMLElement).innerText).toBe('One'); expect((recentOptionListItems[1] as HTMLElement).innerText).toBe('Two'); expect(component.recentOptions.length).toBe(2); expect(component.recentOptions[0]).toBe('One'); expect(component.recentOptions[1]).toBe('Two'); }); it('should update recent options when maximum recent options changes', async () => { component.recentOptions = ['One', 'Two']; fixture.detectChanges(); expect(nativeElement.querySelector('.ux-typeahead-recent-options')).not.toBeNull(); let recentOptionListItems = nativeElement.querySelectorAll('.ux-typeahead-recent-options li'); expect(recentOptionListItems.length).toBe(2); expect((recentOptionListItems[0] as HTMLElement).innerText).toBe('One'); expect((recentOptionListItems[1] as HTMLElement).innerText).toBe('Two'); component.recentOptionsMaxCount = 1; fixture.detectChanges(); await fixture.whenStable(); recentOptionListItems = nativeElement.querySelectorAll('.ux-typeahead-recent-options li'); expect(recentOptionListItems.length).toBe(1); expect((recentOptionListItems[0] as HTMLElement).innerText).toBe('One'); expect(component.recentOptions.length).toBe(1); expect(component.recentOptions[0]).toBe('One'); }); it('should disable selected recent options when multiple = true', () => { component.multiple = true; component.value = ['One']; component.recentOptions = ['One', 'Two']; fixture.detectChanges(); const recentOptionListItems = nativeElement.querySelectorAll('.ux-typeahead-recent-options li'); expect(recentOptionListItems.item(0).classList).toContain('disabled'); expect(recentOptionListItems.item(1).classList).not.toContain('disabled'); }); it('should not be able to select a recent option that is currently selected when multiple = true', () => { component.multiple = true; component.value = ['One']; component.recentOptions = ['One', 'Two']; fixture.detectChanges(); let tags = fixture.nativeElement.querySelectorAll('li.ux-tag'); expect(tags.length).toBe(1); const recentOptionListItems = nativeElement.querySelectorAll( '.ux-typeahead-recent-options li' ); recentOptionListItems.item(0).click(); fixture.detectChanges(); tags = fixture.nativeElement.querySelectorAll('li.ux-tag'); expect(tags.length).toBe(1); }); });