/*! * @license * Copyright 2019 Alfresco Software, Ltd. * * 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 { ComponentFixture, TestBed, discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing'; import { CoreTestingModule } from '../testing/core.testing.module'; import { SearchTextInputComponent } from './search-text-input.component'; import { DebugElement } from '@angular/core'; import { By } from '@angular/platform-browser'; import { Subject } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; import { UserPreferencesService } from '../services/user-preferences.service'; import { setupTestBed } from '../testing/setup-test-bed'; describe('SearchTextInputComponent', () => { let fixture: ComponentFixture; let component: SearchTextInputComponent; let debugElement: DebugElement; let element: HTMLElement; let userPreferencesService: UserPreferencesService; setupTestBed({ imports: [ TranslateModule.forRoot(), CoreTestingModule ] }); beforeEach(() => { fixture = TestBed.createComponent(SearchTextInputComponent); component = fixture.componentInstance; debugElement = fixture.debugElement; element = fixture.nativeElement; userPreferencesService = TestBed.inject(UserPreferencesService); component.focusListener = new Subject(); }); afterEach(() => { fixture.destroy(); }); describe('component rendering', () => { it('should display a search input field when specified', async () => { fixture.detectChanges(); await fixture.whenStable(); component.inputType = 'search'; fixture.detectChanges(); await fixture.whenStable(); expect(element.querySelectorAll('input[type="search"]').length).toBe(1); }); }); describe('expandable option false', () => { beforeEach(() => { component.expandable = false; }); it('search button should be hide', () => { fixture.detectChanges(); const searchButton: any = element.querySelector('#adf-search-button'); expect(searchButton).toBe(null); }); it('should not have animation', () => { userPreferencesService.setWithoutStore('textOrientation', 'rtl'); fixture.detectChanges(); expect(component.subscriptAnimationState.value).toBe('no-animation'); }); }); describe('search button', () => { it('should NOT display a autocomplete list control when configured not to', fakeAsync(() => { fixture.detectChanges(); tick(100); const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); component.subscriptAnimationState.value = 'active'; fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.value).toBe('active'); searchButton.triggerEventHandler('click', null); fixture.detectChanges(); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.value).toBe('inactive'); discardPeriodicTasks(); })); it('click on the search button should open the input box when is close', fakeAsync(() => { fixture.detectChanges(); tick(100); const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); searchButton.triggerEventHandler('click', null); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.value).toBe('active'); discardPeriodicTasks(); })); it('Search button should not change the input state too often', fakeAsync(() => { fixture.detectChanges(); tick(100); const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); component.subscriptAnimationState.value = 'active'; fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.value).toBe('active'); searchButton.triggerEventHandler('click', null); fixture.detectChanges(); tick(100); searchButton.triggerEventHandler('click', null); fixture.detectChanges(); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.value).toBe('inactive'); discardPeriodicTasks(); })); it('Search bar should close when user press ESC button', fakeAsync(() => { fixture.detectChanges(); tick(100); const inputDebugElement = debugElement.query(By.css('#adf-control-input')); component.subscriptAnimationState.value = 'active'; fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.value).toBe('active'); inputDebugElement.triggerEventHandler('keyup.escape', {}); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.value).toBe('inactive'); discardPeriodicTasks(); })); }); describe('toggle animation', () => { beforeEach(() => { fixture.detectChanges(); }); it('should have margin-left set when active and direction is ltr', fakeAsync(() => { userPreferencesService.setWithoutStore('textOrientation', 'ltr'); fixture.detectChanges(); const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); searchButton.triggerEventHandler('click', null); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.params).toEqual({ 'margin-left': 13 }); discardPeriodicTasks(); })); it('should have positive transform translateX set when inactive and direction is ltr', fakeAsync(() => { userPreferencesService.setWithoutStore('textOrientation', 'ltr'); component.subscriptAnimationState.value = 'active'; fixture.detectChanges(); const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); searchButton.triggerEventHandler('click', null); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.params).toEqual({ 'transform': 'translateX(82%)' }); discardPeriodicTasks(); })); it('should have margin-right set when active and direction is rtl', fakeAsync(() => { userPreferencesService.setWithoutStore('textOrientation', 'rtl'); fixture.detectChanges(); const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); searchButton.triggerEventHandler('click', null); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.params).toEqual({ 'margin-right': 13 }); discardPeriodicTasks(); })); it('should have negative transform translateX set when inactive and direction is rtl', fakeAsync(() => { userPreferencesService.setWithoutStore('textOrientation', 'rtl'); component.subscriptAnimationState.value = 'active'; fixture.detectChanges(); const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); searchButton.triggerEventHandler('click', null); tick(100); fixture.detectChanges(); tick(100); expect(component.subscriptAnimationState.params).toEqual({ 'transform': 'translateX(-82%)' }); discardPeriodicTasks(); })); it('should set browser autocomplete to on when configured', async () => { component.autocomplete = true; fixture.detectChanges(); await fixture.whenStable(); expect(element.querySelector('#adf-control-input').getAttribute('autocomplete')).toBe('on'); }); }); describe('Search visibility', () => { beforeEach(() => { userPreferencesService.setWithoutStore('textOrientation', 'ltr'); fixture.detectChanges(); }); it('should emit an event when the search becomes active', fakeAsync(() => { const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit'); component.toggleSearchBar(); tick(200); expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(true); })); it('should emit an event when the search becomes inactive', fakeAsync(() => { component.toggleSearchBar(); tick(200); expect(component.subscriptAnimationState.value).toEqual('active'); const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit'); component.toggleSearchBar(); tick(200); expect(component.subscriptAnimationState.value).toEqual('inactive'); expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(false); })); it('should reset emit when the search becomes inactive', fakeAsync(() => { const resetSpy = spyOn(component.reset, 'emit'); component.toggleSearchBar(); tick(200); expect(component.subscriptAnimationState.value).toEqual('active'); component.searchTerm = 'fake-search-term'; component.toggleSearchBar(); tick(200); expect(resetSpy).toHaveBeenCalled(); expect(component.searchTerm).toEqual(''); })); describe('Clear button', () => { beforeEach(fakeAsync(() => { fixture.detectChanges(); component.subscriptAnimationState.value = 'active'; fixture.detectChanges(); tick(200); })); it('should clear button be visible when showClearButton is set to true', async () => { component.showClearButton = true; fixture.detectChanges(); await fixture.whenStable(); const clearButton = fixture.debugElement.query(By.css('[data-automation-id="adf-clear-search-button"]')); expect(clearButton).not.toBeNull(); }); it('should clear button not be visible when showClearButton is set to false', () => { component.showClearButton = false; fixture.detectChanges(); const clearButton = fixture.debugElement.query(By.css('[data-automation-id="adf-clear-search-button"]')); expect(clearButton).toBeNull(); }); it('should reset the search when clicking the clear button', async () => { const resetEmitSpy = spyOn(component.reset, 'emit'); const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit'); component.searchTerm = 'fake-search-term'; component.showClearButton = true; fixture.detectChanges(); await fixture.whenStable(); const clearButton = fixture.debugElement.query(By.css('[data-automation-id="adf-clear-search-button"]')); clearButton.nativeElement.dispatchEvent(new MouseEvent('mousedown')); fixture.detectChanges(); await fixture.whenStable(); expect(resetEmitSpy).toHaveBeenCalled(); expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(false); expect(component.subscriptAnimationState.value).toEqual('inactive'); expect(component.searchTerm).toEqual(''); }); }); describe('Collapse on blur', () => { beforeEach(fakeAsync(() => { fixture.detectChanges(); component.toggleSearchBar(); tick(200); })); it('should collapse search on blur when the collapseOnBlur is set to true', fakeAsync (() => { const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit'); const resetEmitSpy = spyOn(component.reset, 'emit'); component.collapseOnBlur = true; component.searchTerm = 'fake-search-term'; component.onBlur({ relatedTarget: null }); tick(200); expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(false); expect(component.subscriptAnimationState.value).toEqual('inactive'); expect(component.searchTerm).toEqual(''); expect(resetEmitSpy).toHaveBeenCalled(); })); it('should not collapse search on blur when the collapseOnBlur is set to false', () => { const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit'); component.searchTerm = 'fake-search-term'; component.collapseOnBlur = false; component.onBlur({ relatedTarget: null }); expect(searchVisibilityChangeSpy).not.toHaveBeenCalled(); expect(component.subscriptAnimationState.value).toEqual('active'); expect(component.searchTerm).toEqual('fake-search-term'); }); }); }); });