diff --git a/projects/ui/src/lib/components/po-field/po-field.module.ts b/projects/ui/src/lib/components/po-field/po-field.module.ts index 4c6188fade..d2875d47bc 100644 --- a/projects/ui/src/lib/components/po-field/po-field.module.ts +++ b/projects/ui/src/lib/components/po-field/po-field.module.ts @@ -55,7 +55,7 @@ import { PoUrlComponent } from './po-url/po-url.component'; import { PoCheckboxModule } from './po-checkbox/po-checkbox.module'; import { PoSwitchModule } from './po-switch/po-switch.module'; import { PoLabelModule } from '../po-label'; -import { PoTagComponent, PoTagModule } from '../po-tag'; +import { PoTagModule } from '../po-tag'; /** * @description diff --git a/projects/ui/src/lib/components/po-field/po-multiselect/po-multiselect.component.spec.ts b/projects/ui/src/lib/components/po-field/po-multiselect/po-multiselect.component.spec.ts index a1c2e9784c..cbe3e35295 100644 --- a/projects/ui/src/lib/components/po-field/po-multiselect/po-multiselect.component.spec.ts +++ b/projects/ui/src/lib/components/po-field/po-multiselect/po-multiselect.component.spec.ts @@ -1,17 +1,16 @@ import { OverlayModule } from '@angular/cdk/overlay'; import { HttpClient, HttpHandler } from '@angular/common/http'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { ComponentFixture, fakeAsync, flush, TestBed } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing'; import { Observable, of, throwError } from 'rxjs'; import * as UtilsFunction from '../../../utils/util'; -import { Renderer2 } from '@angular/core'; import { PoTagComponent } from '../../po-tag/po-tag.component'; +import { Renderer2 } from '@angular/core'; import { PoKeyCodeEnum } from '../../../enums/po-key-code.enum'; import { PoFieldContainerComponent } from '../po-field-container/po-field-container.component'; import { PoMultiselectBaseComponent } from '../po-multiselect/po-multiselect-base.component'; -import { PoDisclaimerComponent } from './../../po-disclaimer/po-disclaimer.component'; import { PoFieldContainerBottomComponent } from './../po-field-container/po-field-container-bottom/po-field-container-bottom.component'; import { PoMultiselectDropdownComponent } from './po-multiselect-dropdown/po-multiselect-dropdown.component'; import { PoMultiselectFilter } from './po-multiselect-filter.interface'; @@ -107,7 +106,7 @@ describe('PoMultiselectComponent:', () => { expect(component.getTagsWidth().length).toBeTruthy(); }); - it('should calc visible items with a tiny space', () => { + it('should calc visible items with a tiny space', fakeAsync(() => { const selectedOptions = [ { label: 'label', value: 1 }, { label: 'label', value: 2 }, @@ -123,15 +122,21 @@ describe('PoMultiselectComponent:', () => { selectedOptions: selectedOptions, isCalculateVisibleItems: true, fieldValue: 'value', - fieldLabel: 'label' + fieldLabel: 'label', + initCalculateItems: true, + handleKeyboardNavigationTag: () => {} }; + spyOn(fakeThis, 'handleKeyboardNavigationTag'); component.calculateVisibleItems.call(fakeThis); + tick(300); + expect(fakeThis.visibleTags.length).toBe(1); expect(fakeThis.visibleTags[1]).toBe(undefined); expect(fakeThis.isCalculateVisibleItems).toBeFalsy(); - }); + expect(fakeThis.handleKeyboardNavigationTag).toHaveBeenCalled(); + })); it('should set focus on input', () => { component.initialized = false; @@ -162,55 +167,6 @@ describe('PoMultiselectComponent:', () => { expect(component.debounceResize).toHaveBeenCalled(); }); - it('shouuld call focusPreviousDisclaimer', () => { - component['focusPreviousDisclaimer'](tags.children, index); - - const focusedElement = tags.children[index - 1] as HTMLElement; - - expect(tags.contains(focusedElement)).toBe(true); - }); - - it('should call focusNextDisclaimer', () => { - spyOn(component.inputElement.nativeElement, 'focus'); - - component['focusNextDisclaimer'](tags.children, index); - - expect(component.inputElement.nativeElement.focus).toHaveBeenCalled(); - }); - - it('should call focusNextDisclaimer when index equals 1', () => { - const fakeEvent = { focus: jasmine.createSpy('focus') }; - spyOn(tags.children[1 + 1], 'querySelector').and.returnValue(fakeEvent); - - component['focusNextDisclaimer'](tags.children, 1); - - expect((tags.children[1] as HTMLElement).outerHTML).toBe('
'); - }); - - it('should call addKeyListener if keyCode entries [37, 39, 40]', () => { - spyOn(component, 'focusPreviousDisclaimer' as any); - spyOn(component, 'focusNextDisclaimer' as any); - spyOn(component, 'controlDropdownVisibility'); - - const spanElement = document.createElement('span'); - - const eventLeft = new KeyboardEvent('keydown', { keyCode: PoKeyCodeEnum.left }); - component['addKeyListener'](spanElement, tags, index, eventLeft); - spanElement.dispatchEvent(eventLeft); - - const eventRight = new KeyboardEvent('keydown', { keyCode: PoKeyCodeEnum.right }); - component['addKeyListener'](spanElement, tags, index, eventRight); - spanElement.dispatchEvent(eventRight); - - const eventArrowDown = new KeyboardEvent('keydown', { keyCode: PoKeyCodeEnum.arrowDown }); - component['addKeyListener'](spanElement, tags, index, eventArrowDown); - spanElement.dispatchEvent(eventArrowDown); - - expect(component['focusPreviousDisclaimer']).toHaveBeenCalledWith(tags, index); - expect(component['focusNextDisclaimer']).toHaveBeenCalledWith(tags, index); - expect(component.controlDropdownVisibility).toHaveBeenCalledWith(true); - }); - it('should call preventDefault and controlDropdownVisibility(false) when keyCode esc is pressed', () => { const event = { preventDefault: jasmine.createSpy(), keyCode: 27 }; spyOn(component, 'controlDropdownVisibility'); @@ -221,17 +177,21 @@ describe('PoMultiselectComponent:', () => { expect(component.controlDropdownVisibility).toHaveBeenCalledWith(false); }); - it('should call controlDropdownVisibility arrow to down is pressed', () => { - const fakeEvent = { - preventDefault: () => true, - keyCode: 40, - setFocusOnDropdownListbox: () => {} - }; + it('onKeyDown: should call controlDropdownVisibility arrow to down is pressed', () => { + const event = new KeyboardEvent('keydown', { keyCode: PoKeyCodeEnum.arrowDown }); + const tagRemovable = document.createElement('span'); + + tagRemovable.setAttribute('class', 'po-tag-remove'); + component.visibleTags = [tagRemovable, tagRemovable]; + spyOn(component, 'controlDropdownVisibility'); - spyOn(fakeEvent, 'preventDefault'); - const onKeyDown = component.onKeyDown(fakeEvent); + spyOn(event, 'preventDefault'); + + component.controlDropdownVisibility(true); + const onKeyDown = component.onKeyDown(event); expect(onKeyDown).toBeUndefined(); + expect(event.preventDefault).toHaveBeenCalled(); expect(component.controlDropdownVisibility).toHaveBeenCalledWith(true); }); @@ -281,24 +241,6 @@ describe('PoMultiselectComponent:', () => { expect(component.controlDropdownVisibility).not.toHaveBeenCalled(); }); - it('should call addKeyListener for PoKeyCodeEnum.left or PoKeyCodeEnum.right', () => { - const event = new KeyboardEvent('keydown', { keyCode: PoKeyCodeEnum.left }); - const tagRemovable = document.createElement('span'); - tagRemovable.setAttribute('class', 'po-tag-remove'); - - const tag = document.createElement('span'); - tag.setAttribute('class', 'po-tag'); - tag.appendChild(tagRemovable); - - const disclaimersFake = [tag, tag]; - spyOn(component, 'addKeyListener' as any); - spyOn(component['el'].nativeElement, 'querySelectorAll').and.returnValue(disclaimersFake); - - component.onKeyDown(event); - - expect(component['addKeyListener']).toHaveBeenCalled(); - }); - it('should return when event keyCode is PoKeyCodeEnum.tab and visibleTags.length > 1', () => { const event = new KeyboardEvent('keydown', { keyCode: PoKeyCodeEnum.tab }); const tagRemovable = document.createElement('span'); @@ -381,7 +323,7 @@ describe('PoMultiselectComponent:', () => { expect(component.visibleOptionsDropdown.length).toBe(1); }); - it('should remove item, call updateVisibleItems and callOnChange', () => { + it('closeTag: shouldnt remove item, call updateVisibleItems and callOnChange', () => { component.selectedOptions = [ { label: 'label', value: 1 }, { label: 'label2', value: 2 } @@ -395,6 +337,34 @@ describe('PoMultiselectComponent:', () => { expect(component.selectedOptions[0].value).toBe(2); }); + it('closeTag: should remove item, call updateVisibleItems and callOnChange', () => { + component.visibleTags = [ + { label: 'label10', value: 10 }, + { label: 'label11', value: 11 }, + { label: 'label12', value: 12 }, + { label: 'label13', value: 13 }, + { label: 'label14', value: 14 } + ]; + component.selectedOptions = [ + { label: 'label', value: 1 }, + { label: 'label2', value: 2 }, + { label: 'label3', value: 3 }, + { label: 'label4', value: 4 }, + { label: 'label5', value: 5 }, + { label: 'label6', value: 6 }, + { label: 'label7', value: 7 }, + { label: 'label8', value: 8 }, + { label: 'label9', value: 9 } + ]; + + spyOn(component, 'updateVisibleItems'); + spyOn(component, 'callOnChange'); + component['closeTag']('1+', 'click'); + expect(component.updateVisibleItems).toHaveBeenCalled(); + expect(component.callOnChange).toHaveBeenCalled(); + expect(component.selectedOptions[0].value).toBe(1); + }); + it('should call controlDropdownVisibility in wasClickedOnToggle', () => { component.dropdownOpen = true; fixture.detectChanges(); @@ -714,21 +684,49 @@ describe('PoMultiselectComponent:', () => { expect(closeSpy).toHaveBeenCalled(); }); - it('onBlur: should be called when blur event', () => { - component['onModelTouched '] = () => {}; + it('onKeyDownDropdown: should control dropdown visibility', () => { + const event = new KeyboardEvent('keydown', { key: 'Escape' }); + const controlDropdownVisibilitySpy = spyOn(component, 'controlDropdownVisibility'); + + component.onKeyDownDropdown(event, 0); + + expect(controlDropdownVisibilitySpy).toHaveBeenCalledWith(false); + }); + + it('onKeyDownDropdown: should do nothing for non-Escape key', () => { + const event = new KeyboardEvent('keydown', { key: 'Enter' }); + const preventDefaultSpy = spyOn(event, 'preventDefault'); + const controlDropdownVisibilitySpy = spyOn(component, 'controlDropdownVisibility'); + const focusSpy = spyOn(component.inputElement.nativeElement, 'focus'); + + component.onKeyDownDropdown(event, 0); + + expect(preventDefaultSpy).not.toHaveBeenCalled(); + expect(controlDropdownVisibilitySpy).not.toHaveBeenCalled(); + expect(focusSpy).not.toHaveBeenCalled(); + }); + + it('onBlur: should update aria-label if it contains "Unselected"', () => { + const inputEl = component.inputElement.nativeElement; + inputEl.setAttribute('aria-label', 'Unselected'); + component.label = 'New Label'; spyOn(component,