Skip to content

Commit

Permalink
Merge branch 'master' into mobile-upgrade-latest
Browse files Browse the repository at this point in the history
  • Loading branch information
rupam-seal committed Sep 23, 2023
2 parents 472d2b0 + cefbbd6 commit 8b70cb5
Show file tree
Hide file tree
Showing 3 changed files with 376 additions and 46 deletions.
78 changes: 78 additions & 0 deletions src/app/core/mock-data/virtual-select-option.data.ts
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 },
];
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);
}));
});
Loading

0 comments on commit 8b70cb5

Please sign in to comment.