-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into mobile-upgrade-latest
- Loading branch information
Showing
3 changed files
with
376 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { VirtualSelectOption } from 'src/app/shared/components/virtual-select/virtual-select-modal/virtual-select-option.interface'; | ||
|
||
export const virtualSelectOptionData: VirtualSelectOption = { | ||
label: 'Airlines', | ||
value: { | ||
code: null, | ||
created_at: '2023-07-20T09:58:39.922648+00:00', | ||
displayName: 'Airlines', | ||
enabled: true, | ||
fyle_category: 'Airlines', | ||
id: 264267, | ||
name: 'Airlines', | ||
org_id: 'orDsbzdz7I7k', | ||
sub_category: 'Airlines', | ||
updated_at: '2023-07-20T09:58:39.922648+00:00', | ||
}, | ||
selected: false, | ||
}; | ||
|
||
export const virtualSelectOptionData2: VirtualSelectOption = { | ||
label: 'Mail', | ||
value: { | ||
code: null, | ||
created_at: '2023-07-20T09:58:39.922648+00:00', | ||
displayName: 'Mail', | ||
enabled: true, | ||
fyle_category: 'Mail', | ||
id: 264265, | ||
name: 'Mail', | ||
org_id: 'orDsbzdz7I7k', | ||
sub_category: 'Mail', | ||
updated_at: '2023-07-20T09:58:39.922648+00:00', | ||
}, | ||
selected: false, | ||
}; | ||
|
||
export const virtualSelectOptionData3: VirtualSelectOption = { | ||
label: 'Train', | ||
value: { | ||
code: null, | ||
created_at: '2023-07-20T09:58:39.922648+00:00', | ||
displayName: 'Train', | ||
enabled: true, | ||
fyle_category: 'Train', | ||
id: 264255, | ||
name: 'Train', | ||
org_id: 'orDsbzdz7I7k', | ||
sub_category: 'Train', | ||
updated_at: '2023-07-20T09:58:39.922648+00:00', | ||
}, | ||
selected: false, | ||
}; | ||
|
||
export const virtualSelectOptionData4: VirtualSelectOption[] = [virtualSelectOptionData, virtualSelectOptionData2]; | ||
|
||
export const virtualSelectOptionData5: VirtualSelectOption[] = [ | ||
{ ...virtualSelectOptionData2 }, | ||
virtualSelectOptionData3, | ||
]; | ||
|
||
export const expectedVirtualSelectOptionData: VirtualSelectOption[] = [ | ||
{ label: 'None', value: null }, | ||
virtualSelectOptionData2, | ||
]; | ||
|
||
export const expectedSelectableOptionsData: VirtualSelectOption[] = [ | ||
{ ...virtualSelectOptionData2, isRecentlyUsed: true }, | ||
{ ...virtualSelectOptionData3, isRecentlyUsed: true }, | ||
virtualSelectOptionData, | ||
virtualSelectOptionData2, | ||
]; | ||
|
||
export const expectedFilteredOptionsData: VirtualSelectOption[] = [ | ||
{ label: 'None', value: null }, | ||
virtualSelectOptionData, | ||
virtualSelectOptionData2, | ||
{ label: 'Train', value: virtualSelectOptionData3, selected: true }, | ||
]; |
244 changes: 244 additions & 0 deletions
244
...red/components/virtual-select/virtual-select-modal/virtual-select-modal.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
import { ComponentFixture, TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; | ||
import { IonicModule, ModalController } from '@ionic/angular'; | ||
|
||
import { RecentLocalStorageItemsService } from 'src/app/core/services/recent-local-storage-items.service'; | ||
import { UtilityService } from 'src/app/core/services/utility.service'; | ||
import { NO_ERRORS_SCHEMA } from '@angular/core'; | ||
import { of, take } from 'rxjs'; | ||
import { VirtualSelectModalComponent } from './virtual-select-modal.component'; | ||
import { | ||
expectedFilteredOptionsData, | ||
expectedSelectableOptionsData, | ||
expectedVirtualSelectOptionData, | ||
virtualSelectOptionData, | ||
virtualSelectOptionData3, | ||
virtualSelectOptionData4, | ||
virtualSelectOptionData5, | ||
} from 'src/app/core/mock-data/virtual-select-option.data'; | ||
import { cloneDeep } from 'lodash'; | ||
import { getElementRef } from 'src/app/core/dom-helpers'; | ||
|
||
describe('VirtualSelectModalComponent', () => { | ||
let component: VirtualSelectModalComponent; | ||
let fixture: ComponentFixture<VirtualSelectModalComponent>; | ||
let modalController: jasmine.SpyObj<ModalController>; | ||
let recentLocalStorageItemsService: jasmine.SpyObj<RecentLocalStorageItemsService>; | ||
let utilityService: jasmine.SpyObj<UtilityService>; | ||
let inputElement: HTMLInputElement; | ||
|
||
beforeEach(waitForAsync(() => { | ||
const modalControllerSpy = jasmine.createSpyObj('ModalController', ['dismiss']); | ||
const recentLocalStorageItemsServiceSpy = jasmine.createSpyObj('RecentLocalStorageItemsService', ['get', 'post']); | ||
const utilityServiceSpy = jasmine.createSpyObj('UtilityService', ['searchArrayStream']); | ||
|
||
TestBed.configureTestingModule({ | ||
declarations: [VirtualSelectModalComponent], | ||
imports: [IonicModule.forRoot()], | ||
providers: [ | ||
{ | ||
provide: ModalController, | ||
useValue: modalControllerSpy, | ||
}, | ||
{ | ||
provide: RecentLocalStorageItemsService, | ||
useValue: recentLocalStorageItemsServiceSpy, | ||
}, | ||
{ | ||
provide: UtilityService, | ||
useValue: utilityServiceSpy, | ||
}, | ||
], | ||
schemas: [NO_ERRORS_SCHEMA], | ||
}).compileComponents(); | ||
|
||
fixture = TestBed.createComponent(VirtualSelectModalComponent); | ||
component = fixture.componentInstance; | ||
modalController = TestBed.inject(ModalController) as jasmine.SpyObj<ModalController>; | ||
recentLocalStorageItemsService = TestBed.inject( | ||
RecentLocalStorageItemsService | ||
) as jasmine.SpyObj<RecentLocalStorageItemsService>; | ||
utilityService = TestBed.inject(UtilityService) as jasmine.SpyObj<UtilityService>; | ||
component.enableSearch = true; | ||
component.searchBarRef = getElementRef(fixture, '.selection-modal--search-input'); | ||
})); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
|
||
describe('ngAfterViewInit():', () => { | ||
beforeEach(() => { | ||
spyOn(component, 'setSelectableOptions'); | ||
spyOn(component, 'setFilteredOptions'); | ||
fixture.detectChanges(); | ||
inputElement = component.searchBarRef.nativeElement; | ||
component.currentSelection = cloneDeep(virtualSelectOptionData); | ||
component.defaultLabelProp = 'label'; | ||
component.options = cloneDeep(virtualSelectOptionData4); | ||
}); | ||
|
||
it('should set filteredOptions$ equals to value returned by setFilteredOptions whenever input changes', fakeAsync(() => { | ||
component.setFilteredOptions = jasmine | ||
.createSpy() | ||
.and.returnValues(virtualSelectOptionData4, expectedVirtualSelectOptionData); | ||
component.nullOption = true; | ||
component.ngAfterViewInit(); | ||
inputElement.value = ''; | ||
inputElement.dispatchEvent(new Event('keyup')); | ||
tick(100); | ||
component.filteredOptions$.pipe(take(1)).subscribe((res) => { | ||
expect(res).toEqual(virtualSelectOptionData4); | ||
}); | ||
inputElement.value = 'ail'; | ||
inputElement.dispatchEvent(new Event('keyup')); | ||
|
||
tick(100); | ||
component.filteredOptions$.pipe(take(1)).subscribe((res) => { | ||
expect(res).toEqual(expectedVirtualSelectOptionData); | ||
}); | ||
})); | ||
|
||
it('should update recentlyUsedItems$', fakeAsync(() => { | ||
spyOn(component, 'getRecentlyUsedItems').and.returnValue(of(virtualSelectOptionData5)); | ||
utilityService.searchArrayStream.and.returnValues( | ||
() => of(virtualSelectOptionData5), | ||
() => of([virtualSelectOptionData5[1]]) | ||
); | ||
component.ngAfterViewInit(); | ||
inputElement.value = ''; | ||
inputElement.dispatchEvent(new Event('keyup')); | ||
|
||
tick(100); | ||
component.recentlyUsedItems$.pipe(take(1)).subscribe((res) => { | ||
expect(utilityService.searchArrayStream).toHaveBeenCalledWith(''); | ||
expect(res).toEqual(virtualSelectOptionData5); | ||
}); | ||
|
||
inputElement.value = 'tra'; | ||
inputElement.dispatchEvent(new Event('keyup')); | ||
|
||
tick(100); | ||
component.recentlyUsedItems$.pipe(take(1)).subscribe((res) => { | ||
expect(utilityService.searchArrayStream).toHaveBeenCalledWith('tra'); | ||
expect(res).toEqual([virtualSelectOptionData5[1]]); | ||
}); | ||
expect(utilityService.searchArrayStream).toHaveBeenCalledTimes(2); | ||
expect(component.getRecentlyUsedItems).toHaveBeenCalledTimes(2); | ||
})); | ||
|
||
it('should update the filteredOptions$ if searchBarRef is not defined', (done) => { | ||
component.enableSearch = false; | ||
component.nullOption = true; | ||
component.currentSelection = virtualSelectOptionData; | ||
fixture.detectChanges(); | ||
|
||
component.ngAfterViewInit(); | ||
expect(component.searchBarRef).toBeUndefined(); | ||
|
||
component.filteredOptions$.subscribe((res) => { | ||
expect(res).toEqual([{ label: 'None', value: null }, ...virtualSelectOptionData4]); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
it('onDoneClick(): should dismiss the modal', () => { | ||
component.onDoneClick(); | ||
expect(modalController.dismiss).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('clearValue(): should clear the value and trigger a keyup event', () => { | ||
spyOn(component, 'setSelectableOptions'); | ||
spyOn(component, 'setFilteredOptions'); | ||
fixture.detectChanges(); | ||
inputElement = component.searchBarRef.nativeElement; | ||
inputElement.value = 'example'; | ||
spyOn(inputElement, 'dispatchEvent'); | ||
fixture.detectChanges(); | ||
component.clearValue(); | ||
|
||
expect(component.value).toBe(''); | ||
expect(inputElement.value).toBe(''); | ||
expect(inputElement.dispatchEvent).toHaveBeenCalledOnceWith(new Event('keyup')); | ||
}); | ||
|
||
describe('getRecentlyUsedItems(): ', () => { | ||
const mockOptions = cloneDeep(virtualSelectOptionData4); | ||
const options = mockOptions; | ||
const mockRecentlyUsedItems = cloneDeep(virtualSelectOptionData5); | ||
const recentlyUsed = mockRecentlyUsedItems; | ||
const mockLocalStorageItems = cloneDeep(virtualSelectOptionData5); | ||
const localStorageItems = mockLocalStorageItems; | ||
const filteredItems = [mockOptions[1]]; | ||
|
||
it('should return recently used items from API if available', (done) => { | ||
component.recentlyUsed = recentlyUsed; | ||
component.options = []; | ||
component.getRecentlyUsedItems().subscribe((result) => { | ||
expect(recentLocalStorageItemsService.get).not.toHaveBeenCalled(); | ||
expect(result).toEqual(recentlyUsed); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return recently used items from local storage if not available from API', (done) => { | ||
const getSpy = recentLocalStorageItemsService.get.and.resolveTo(localStorageItems); | ||
component.options = options; | ||
component.recentlyUsed = null; | ||
component.currentSelection = virtualSelectOptionData; | ||
|
||
component.getRecentlyUsedItems().subscribe((result) => { | ||
expect(getSpy).toHaveBeenCalledOnceWith(component.cacheName); | ||
expect(result).toEqual(filteredItems); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
|
||
it('onElementSelect(): should call recentlocalstorage service and dismiss the modal', () => { | ||
component.cacheName = 'cache1'; | ||
const option = virtualSelectOptionData4[1]; | ||
component.onElementSelect(option); | ||
expect(recentLocalStorageItemsService.post).toHaveBeenCalledOnceWith('cache1', option, 'label'); | ||
expect(modalController.dismiss).toHaveBeenCalledOnceWith(option); | ||
}); | ||
|
||
it('saveToCacheAndUse(): should call onElementSelect', () => { | ||
spyOn(component, 'setSelectableOptions'); | ||
spyOn(component, 'setFilteredOptions'); | ||
fixture.detectChanges(); | ||
inputElement = component.searchBarRef.nativeElement; | ||
inputElement.value = 'example'; | ||
fixture.detectChanges(); | ||
spyOn(component, 'onElementSelect'); | ||
component.saveToCacheAndUse(); | ||
expect(component.onElementSelect).toHaveBeenCalledOnceWith({ | ||
label: 'example', | ||
value: 'example', | ||
selected: false, | ||
}); | ||
}); | ||
|
||
it('setSelectableOptions(): should update selectableOptions correctly', fakeAsync(() => { | ||
const mockFilteredOptions = virtualSelectOptionData4; | ||
const mockRecentlyUsedItems = virtualSelectOptionData5; | ||
component.filteredOptions$ = of(mockFilteredOptions); | ||
component.recentlyUsedItems$ = of(mockRecentlyUsedItems); | ||
component.setSelectableOptions(); | ||
tick(100); | ||
|
||
expect(component.selectableOptions).toEqual(expectedSelectableOptionsData); | ||
})); | ||
|
||
it('setFilteredOptions(): should update filteredOptions correctly', fakeAsync(() => { | ||
component.nullOption = true; | ||
component.currentSelection = cloneDeep(virtualSelectOptionData3); | ||
component.defaultLabelProp = 'label'; | ||
component.options = cloneDeep(virtualSelectOptionData4); | ||
|
||
const res = component.setFilteredOptions('ai'); | ||
tick(100); | ||
|
||
expect(res).toEqual(expectedFilteredOptionsData); | ||
})); | ||
}); |
Oops, something went wrong.