From a25db8fec7be9e6d3d40666b81eaf430c06ca085 Mon Sep 17 00:00:00 2001 From: dangapay <divin.angapay@lam.fr> Date: Wed, 18 Jan 2023 11:16:45 +0100 Subject: [PATCH] add test for instance -> store -> effects --- .../store/effects/archive.effects.spec.ts | 164 ++++++ .../store/effects/cone-search.effects.spec.ts | 22 +- .../app/instance/store/effects/index.spec.ts | 17 + .../store/effects/search.effects.spec.ts | 550 ++++++++++-------- 4 files changed, 499 insertions(+), 254 deletions(-) create mode 100644 client/src/app/instance/store/effects/archive.effects.spec.ts create mode 100644 client/src/app/instance/store/effects/index.spec.ts diff --git a/client/src/app/instance/store/effects/archive.effects.spec.ts b/client/src/app/instance/store/effects/archive.effects.spec.ts new file mode 100644 index 00000000..e983c239 --- /dev/null +++ b/client/src/app/instance/store/effects/archive.effects.spec.ts @@ -0,0 +1,164 @@ +/** + * This file is part of Anis Client. + * + * @copyright Laboratoire d'Astrophysique de Marseille / CNRS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { TestBed } from '@angular/core/testing'; +import { provideMockActions } from '@ngrx/effects/testing'; +import { EffectsMetadata, getEffectsMetadata } from '@ngrx/effects'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { Observable, of, Subject, throwError } from 'rxjs'; +import { cold, hot } from 'jasmine-marbles'; +import { ToastrService } from 'ngx-toastr'; +import * as fromArchive from 'src/app/instance/store/reducers/archive.reducer'; +import { ArchiveEffects } from './archive.effects'; +import { ArchiveService } from '../services/archive.service'; +import { AppConfigService } from 'src/app/app-config.service'; +import * as archiveActions from '../actions/archive.actions'; +import * as searchActions from '../actions/search.actions'; +import * as searchSelector from '../selectors/search.selector'; +import * as fromSharedUtils from 'src/app/shared/utils'; + +describe('[Instance][Store] ArchiveEffects', () => { + let actions = new Observable(); + let effects: ArchiveEffects; + let metadata: EffectsMetadata<ArchiveEffects>; + let archiveService: ArchiveService; + let toastr: ToastrService; + let store: MockStore; + const initialState = { + coneSearch: { ...fromArchive.initialState } + }; + let mockSearchSelectorSelectCurrentDataset; + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + ArchiveEffects, + { provide: ArchiveService, useValue: { retrieveCoordinates: jest.fn() } }, + { provide: ToastrService, useValue: { error: jest.fn() } }, + { provide: AppConfigService, useValue: { apiUrl: 'test' } }, + provideMockActions(() => actions), + provideMockStore({ initialState }), + + ] + }); + effects = TestBed.inject(ArchiveEffects); + metadata = getEffectsMetadata(effects); + archiveService = TestBed.inject(ArchiveService); + toastr = TestBed.inject(ToastrService); + store = TestBed.inject(MockStore); + }); + + it('effect should be created', () => { + expect(effects).toBeTruthy(); + }); + describe('startTaskCreateArchive$ effect', () => { + it('should start create archive', () => { + let param = { datasetName: 'test', fileId: '', filename: 'test' } + const action = archiveActions.startTaskCreateArchive({ query: 'test' }); + const completion = archiveActions.startTaskCreateArchiveSuccess(param); + archiveService.startTaskCreateArchive = jest.fn().mockImplementation(() => of({ archive_id: '', archive_name: 'test', datasetName: 'test' })); + mockSearchSelectorSelectCurrentDataset = store.overrideSelector(searchSelector.selectCurrentDataset, 'test'); + actions = cold('a', { a: action }); + const expected = cold('a', { a: completion }) + expect(effects.startTaskCreateArchive$).toBeObservable(expected); + }); + it('should trigger startTaskCreateArchiveFail', () => { + const action = archiveActions.startTaskCreateArchive({ query: 'test' }); + const completion = archiveActions.startTaskCreateArchiveFail(); + archiveService.startTaskCreateArchive = jest.fn().mockImplementation((error) => throwError(() => error)); + actions = cold('a', { a: action }); + const expected = cold('a', { a: completion }) + expect(effects.startTaskCreateArchive$).toBeObservable(expected); + }); + + + }); + describe('startTaskCreateArchiveFail$ effect', () => { + it('should trigger fail toast error', () => { + const spy = jest.spyOn(toastr, 'error'); + const action = archiveActions.startTaskCreateArchiveFail(); + actions = hot('a', { a: action }); + expect(effects.startTaskCreateArchiveFail$).toBeObservable(cold('a', { a: action })); + expect(spy).toHaveBeenCalledTimes(1); + + }); + + }); + describe('isArchiveAvailable$ effect', () => { + it('should trigger isArchiveAvailableSuccess action', () => { + let param = { datasetName: 'test', fileId: '', filename: 'test' } + // @ts-ignore + effects.kill$ = new Subject(); + let spy = jest.spyOn(fromSharedUtils, 'getHost'); + spy.mockImplementation(() => 'test'); + const action = archiveActions.isArchiveAvailable(param) + const completion = archiveActions.isArchiveAvailableSuccess({ filename: 'test', url: 'test/download-archive/test/' }); + archiveService.isArchiveAvailable = jest.fn().mockImplementation(() => of({ archive_is_available: true })); + actions = cold('a', { a: action }); + const expected = cold('a', { a: completion }) + expect(effects.isArchiveAvailable$).toBeObservable(expected); + + }); + it('should trigger [No Action] Is Archive Available action', () => { + let param = { datasetName: 'test', fileId: '', filename: 'test' } + const action = archiveActions.isArchiveAvailable(param) + const completion = { type: '[No Action] Is Archive Available' }; + archiveService.isArchiveAvailable = jest.fn().mockImplementation(() => of({ archive_is_available: false })); + actions = cold('a', { a: action }); + const expected = cold('a', { a: completion }) + expect(effects.isArchiveAvailable$).toBeObservable(expected); + + }); + it('should trigger isArchiveAvailableFail action', () => { + let param = { datasetName: 'test', fileId: '', filename: 'test' } + const action = archiveActions.isArchiveAvailable(param) + const completion = archiveActions.isArchiveAvailableFail(); + archiveService.isArchiveAvailable = jest.fn().mockImplementation(() => of({ archive_is_available: true })); + actions = cold('a', { a: action }); + const expected = cold('a', { a: completion }) + expect(effects.isArchiveAvailable$).toBeObservable(expected); + + }); + + }); + describe('isArchiveAvailableSuccess$ effect', () => { + it('should trigger downloadFile action ', () => { + const action = archiveActions.isArchiveAvailableSuccess({ filename: 'test', url: 'test' }); + actions = hot('a', { a: action }); + const completion = searchActions.downloadFile({ filename: 'test', url: 'test' }); + expect(effects.isArchiveAvailableSuccess$).toBeObservable(cold('a', { a: completion })); + + }); + }); + describe('isArchiveAvailableFail$ effect', () => { + it('should trigger fail toast error', () => { + const spy = jest.spyOn(toastr, 'error'); + const action = archiveActions.isArchiveAvailableFail(); + actions = hot('a', { a: action }); + expect(effects.isArchiveAvailableFail$).toBeObservable(cold('a', { a: action })); + expect(spy).toHaveBeenCalledTimes(1); + + }); + + }); + describe('resetArchive$ effect', () => { + it('should call unsuscribe on kill', () => { + //@ts-ignore + effects.kill$ = new Subject(); + //@ts-ignore + let spy = jest.spyOn(effects.kill$, 'unsubscribe'); + const action = archiveActions.resetArchive(); + actions = hot('a', { a: action }); + expect(effects.resetArchive$).toBeObservable(cold('a', { a: action })); + expect(spy).toHaveBeenCalledTimes(1); + + }); + + }); + +}); diff --git a/client/src/app/instance/store/effects/cone-search.effects.spec.ts b/client/src/app/instance/store/effects/cone-search.effects.spec.ts index 1033c5b6..c952b912 100644 --- a/client/src/app/instance/store/effects/cone-search.effects.spec.ts +++ b/client/src/app/instance/store/effects/cone-search.effects.spec.ts @@ -2,7 +2,7 @@ import { TestBed } from '@angular/core/testing'; import { provideMockActions } from '@ngrx/effects/testing'; import { EffectsMetadata, getEffectsMetadata } from '@ngrx/effects'; -import { provideMockStore } from '@ngrx/store/testing'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { Observable } from 'rxjs'; import { cold, hot } from 'jasmine-marbles'; import { ToastrService } from 'ngx-toastr'; @@ -10,8 +10,9 @@ import { ToastrService } from 'ngx-toastr'; import { ConeSearchEffects } from './cone-search.effects'; import { ConeSearchService } from '../services/cone-search.service'; import * as coneSearchActions from '../actions/cone-search.actions'; -import { Resolver } from '../models'; +import { ConeSearch, Resolver } from '../models'; import * as fromConeSearch from 'src/app/instance/store/reducers/cone-search.reducer'; +import * as coneSearchSelector from '../selectors/cone-search.selector'; describe('[Instance][Store] ConeSearchEffects', () => { let actions = new Observable(); @@ -22,12 +23,13 @@ describe('[Instance][Store] ConeSearchEffects', () => { const initialState = { coneSearch: { ...fromConeSearch.initialState } }; - + let mockConeSearchSelectorSelectConeSearch; + let store: MockStore; beforeEach(() => { TestBed.configureTestingModule({ providers: [ ConeSearchEffects, - { provide: ConeSearchService, useValue: { retrieveCoordinates: jest.fn() }}, + { provide: ConeSearchService, useValue: { retrieveCoordinates: jest.fn() } }, { provide: ToastrService, useValue: { error: jest.fn() } }, provideMockActions(() => actions), provideMockStore({ initialState }) @@ -37,6 +39,7 @@ describe('[Instance][Store] ConeSearchEffects', () => { metadata = getEffectsMetadata(effects); coneSearchService = TestBed.inject(ConeSearchService); toastr = TestBed.inject(ToastrService); + store = TestBed.inject(MockStore); }); it('should be created', () => { @@ -112,7 +115,18 @@ describe('[Instance][Store] ConeSearchEffects', () => { expect(effects.retrieveCoordinates$).toBeObservable(expected); }); }); + describe('retrieveCoordinatesSuccess$', () => { + it('should dispatch the updateConesearch action', () => { + let coneSearch: ConeSearch = { ra: 10, dec: 5, radius: 5 }; + mockConeSearchSelectorSelectConeSearch = store.overrideSelector(coneSearchSelector.selectConeSearch, coneSearch); + const action = coneSearchActions.retrieveCoordinatesSuccess({resolver: {ra: 10, dec: 5, name : 'test'}}); + const outcome = coneSearchActions.updateConeSearch({ coneSearch }); + actions = cold('a', { a: action }); + let expected = cold('a', { a: outcome }); + expect(effects.retrieveCoordinatesSuccess$).toBeObservable(expected); + }); + }) describe('retrieveCoordinatesFail$ effect', () => { it('should not dispatch', () => { expect(metadata.retrieveCoordinatesFail$).toEqual( diff --git a/client/src/app/instance/store/effects/index.spec.ts b/client/src/app/instance/store/effects/index.spec.ts new file mode 100644 index 00000000..cac77bdb --- /dev/null +++ b/client/src/app/instance/store/effects/index.spec.ts @@ -0,0 +1,17 @@ +/** + * This file is part of Anis Client. + * + * @copyright Laboratoire d'Astrophysique de Marseille / CNRS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { instanceEffects } from "." + +describe('[instance][store][effects] index', () => { + it('test index', () => { + expect(instanceEffects.length).toEqual(5); + }) + +}) \ No newline at end of file diff --git a/client/src/app/instance/store/effects/search.effects.spec.ts b/client/src/app/instance/store/effects/search.effects.spec.ts index f5c164ad..22d91486 100644 --- a/client/src/app/instance/store/effects/search.effects.spec.ts +++ b/client/src/app/instance/store/effects/search.effects.spec.ts @@ -3,7 +3,7 @@ import { TestBed } from '@angular/core/testing'; import { provideMockActions } from '@ngrx/effects/testing'; import { EffectsMetadata, getEffectsMetadata } from '@ngrx/effects'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { cold, hot } from 'jasmine-marbles'; import { ToastrService } from 'ngx-toastr'; import { KeycloakService } from 'keycloak-angular'; @@ -24,6 +24,8 @@ import * as coneSearchActions from '../actions/cone-search.actions'; import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-search-config.selector'; import * as coneSearchConfigActions from 'src/app/metamodel/actions/cone-search-config.actions'; import { Criterion, PaginationOrder } from '../models'; +import * as authSelector from 'src/app/auth/auth.selector'; +import FileSaver from 'file-saver'; describe('[Instance][Store] SearchEffects', () => { let actions = new Observable(); @@ -31,7 +33,6 @@ describe('[Instance][Store] SearchEffects', () => { let metadata: EffectsMetadata<SearchEffects>; let searchService: SearchService; let toastr: ToastrService; - let keycloak: KeycloakService; let store: MockStore; const initialState = { search: { ...fromSearch.initialState } }; let mockDatasetSelectorSelectDatasetNameByRoute; @@ -46,17 +47,23 @@ describe('[Instance][Store] SearchEffects', () => { let mockSearchSelectorSelectOutputListByRoute; let mockSearchSelectorSelectOutputList; let mocksSearchSelectorSelectConeSearchConfig; + let mockAttributeSelectorSelectAttributeListIsLoaded; + let mockConeSearchConfigSelectorSelectConeSearchConfigIsLoaded; + let mockAuthSelectorSelectIsAuthenticated; + let keycloak = { getToken: jest.fn().mockImplementation(() => Promise.resolve('test'))}; beforeEach(() => { TestBed.configureTestingModule({ providers: [ SearchEffects, - { provide: SearchService, useValue: { + { + provide: SearchService, useValue: { retrieveData: jest.fn(), retrieveDataLength: jest.fn() - }}, - { provide: ToastrService, useValue: { error: jest.fn() }}, - { provide: KeycloakService, useValue: { getToken: jest.fn() }}, + } + }, + { provide: ToastrService, useValue: { error: jest.fn() } }, + { provide: KeycloakService, useValue: keycloak }, provideMockActions(() => actions), provideMockStore({ initialState }) ] @@ -67,40 +74,40 @@ describe('[Instance][Store] SearchEffects', () => { toastr = TestBed.inject(ToastrService); store = TestBed.inject(MockStore); mockDatasetSelectorSelectDatasetNameByRoute = store.overrideSelector( - datasetSelector.selectDatasetNameByRoute,'' + datasetSelector.selectDatasetNameByRoute, '' ); mockSearchSelectorSelectCurrentDataset = store.overrideSelector( - searchSelector.selectCurrentDataset,'' + searchSelector.selectCurrentDataset, '' ); mockSearchSelectorSelectPristine = store.overrideSelector( - searchSelector.selectPristine,true + searchSelector.selectPristine, true ); mockAttributeSelectorSelectAllAttributes = store.overrideSelector( - attributeSelector.selectAllAttributes,[] + attributeSelector.selectAllAttributes, [] ); mockSearchSelectorSelectStepsByRoute = store.overrideSelector( - searchSelector.selectStepsByRoute,'' + searchSelector.selectStepsByRoute, '' ); mockSearchSelectorSelectCriteriaListByRoute = store.overrideSelector( - searchSelector.selectCriteriaListByRoute,'' + searchSelector.selectCriteriaListByRoute, '' ); mockSearchSelectorSelectCriteriaList = store.overrideSelector( - searchSelector.selectCriteriaList,[] + searchSelector.selectCriteriaList, [] ); mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector( - coneSearchSelector.selectConeSearchByRoute,'' + coneSearchSelector.selectConeSearchByRoute, '' ); mockConeSearchSelectorSelectConeSearch = store.overrideSelector( - coneSearchSelector.selectConeSearch,{ ra: 1, dec: 2, radius: 3 } + coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 } ); mockSearchSelectorSelectOutputListByRoute = store.overrideSelector( - searchSelector.selectOutputListByRoute,'' + searchSelector.selectOutputListByRoute, '' ); mockSearchSelectorSelectOutputList = store.overrideSelector( - searchSelector.selectOutputList,[] + searchSelector.selectOutputList, [] ); mocksSearchSelectorSelectConeSearchConfig = store.overrideSelector( - coneSearchConfigSelector.selectConeSearchConfig,null + coneSearchConfigSelector.selectConeSearchConfig, null ); }); @@ -114,7 +121,7 @@ describe('[Instance][Store] SearchEffects', () => { datasetSelector.selectDatasetNameByRoute, 'myNewDataset' ); mockSearchSelectorSelectCurrentDataset = store.overrideSelector( - searchSelector.selectCurrentDataset,'myOldDataset' + searchSelector.selectCurrentDataset, 'myOldDataset' ); const action = searchActions.initSearch(); @@ -131,10 +138,10 @@ describe('[Instance][Store] SearchEffects', () => { datasetSelector.selectDatasetNameByRoute, 'myDatasetName' ); mockSearchSelectorSelectPristine = store.overrideSelector( - searchSelector.selectPristine,true + searchSelector.selectPristine, true ); mockSearchSelectorSelectCurrentDataset = store.overrideSelector( - searchSelector.selectCurrentDataset,'myDatasetName' + searchSelector.selectCurrentDataset, 'myDatasetName' ); const action = searchActions.initSearch(); @@ -157,10 +164,10 @@ describe('[Instance][Store] SearchEffects', () => { datasetSelector.selectDatasetNameByRoute, 'myDatasetName' ); mockSearchSelectorSelectPristine = store.overrideSelector( - searchSelector.selectPristine,true + searchSelector.selectPristine, true ); mockSearchSelectorSelectCurrentDataset = store.overrideSelector( - searchSelector.selectCurrentDataset,'myDatasetName' + searchSelector.selectCurrentDataset, 'myDatasetName' ); mockSearchSelectorSelectStepsByRoute = store.overrideSelector( searchSelector.selectStepsByRoute, '111' @@ -189,7 +196,7 @@ describe('[Instance][Store] SearchEffects', () => { datasetSelector.selectDatasetNameByRoute, '' ); mockSearchSelectorSelectPristine = store.overrideSelector( - searchSelector.selectPristine,false + searchSelector.selectPristine, false ); const action = searchActions.initSearch(); @@ -230,7 +237,33 @@ describe('[Instance][Store] SearchEffects', () => { expect(effects.restartSearch$).toBeObservable(expected); }); }); + describe('resetSearch$ effect', () => { + it('should dispatch resetAttributeList and resetConeSearchConfig actions', () => { + let action = searchActions.resetSearch(); + actions = hot('a', { a: action }); + const expected = cold('(bc)', { + b: attributeActions.resetAttributeList(), + c: coneSearchConfigActions.resetConeSearchConfig(), + }); + + + expect(effects.resetSearch$).toBeObservable(expected); + + }) + + }); + describe('tryLoadDefaultFormParameters$ effect', () => { + it('should dispatch loadDefaultFormParameters action', () => { + mockAttributeSelectorSelectAttributeListIsLoaded = store.overrideSelector(attributeSelector.selectAttributeListIsLoaded, true); + mockConeSearchConfigSelectorSelectConeSearchConfigIsLoaded = store.overrideSelector(coneSearchConfigSelector.selectConeSearchConfigIsLoaded, true); + let action = searchActions.tryLoadDefaultFormParameters(); + actions = hot('a', { a: action }); + const expected = cold('a', { a: searchActions.loadDefaultFormParameters() }); + expect(effects.tryLoadDefaultFormParameters$).toBeObservable(expected); + }) + + }); describe('loadDefaultFormParameters$ effect', () => { it('should not dispatch action if params already loaded', () => { mockSearchSelectorSelectPristine = store.overrideSelector( @@ -292,87 +325,87 @@ describe('[Instance][Store] SearchEffects', () => { ); mockAttributeSelectorSelectAllAttributes = store.overrideSelector( attributeSelector.selectAllAttributes, [ - { - id: 1, - name: 'att1', - label: 'attribute1', - form_label: 'Attribute 1', - description: null, - primary_key: true, - type: 'string', - search_type: 'field', - operator: 'eq', - dynamic_operator: false, - min: 'one', - max: null, - placeholder_min: null, - placeholder_max: null, - criteria_display: 1, - output_display: 1, - selected: false, - renderer: null, - renderer_config: null, - order_by: true, - archive: false, - detail_display: 1, - detail_renderer: null, - detail_renderer_config: null, - options: null, - vo_utype: null, - vo_ucd: null, - vo_unit: null, - vo_description: null, - vo_datatype: null, - vo_size: null, - id_criteria_family: 1, - id_output_category: null, - id_detail_output_category: null - }, - { - id: 2, - name: 'att2', - label: 'attribute2', - form_label: 'Attribute 2', - description: null, - primary_key: false, - type: 'string', - search_type: 'field', - operator: 'eq', - dynamic_operator: false, - min: 'two', - max: null, - placeholder_min: null, - placeholder_max: null, - criteria_display: 1, - output_display: 1, - selected: false, - renderer: null, - renderer_config: null, - order_by: true, - archive: false, - detail_display: 1, - detail_renderer: null, - detail_renderer_config: null, - options: null, - vo_utype: null, - vo_ucd: null, - vo_unit: null, - vo_description: null, - vo_datatype: null, - vo_size: null, - id_criteria_family: 2, - id_output_category: null, - id_detail_output_category: null - } - ] + { + id: 1, + name: 'att1', + label: 'attribute1', + form_label: 'Attribute 1', + description: null, + primary_key: true, + type: 'string', + search_type: 'field', + operator: 'eq', + dynamic_operator: false, + min: 'one', + max: null, + placeholder_min: null, + placeholder_max: null, + criteria_display: 1, + output_display: 1, + selected: false, + renderer: null, + renderer_config: null, + order_by: true, + archive: false, + detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, + options: null, + vo_utype: null, + vo_ucd: null, + vo_unit: null, + vo_description: null, + vo_datatype: null, + vo_size: null, + id_criteria_family: 1, + id_output_category: null, + id_detail_output_category: null + }, + { + id: 2, + name: 'att2', + label: 'attribute2', + form_label: 'Attribute 2', + description: null, + primary_key: false, + type: 'string', + search_type: 'field', + operator: 'eq', + dynamic_operator: false, + min: 'two', + max: null, + placeholder_min: null, + placeholder_max: null, + criteria_display: 1, + output_display: 1, + selected: false, + renderer: null, + renderer_config: null, + order_by: true, + archive: false, + detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, + options: null, + vo_utype: null, + vo_ucd: null, + vo_unit: null, + vo_description: null, + vo_datatype: null, + vo_size: null, + id_criteria_family: 2, + id_output_category: null, + id_detail_output_category: null + } + ] ); const action = searchActions.loadDefaultFormParameters(); actions = hot('-a', { a: action }); const defaultCriteriaList = [ - {'id':1,'type':'field','operator':'eq','value':'one'}, - {'id':2,'type':'field','operator':'eq','value':'two'} + { 'id': 1, 'type': 'field', 'operator': 'eq', 'value': 'one' }, + { 'id': 2, 'type': 'field', 'operator': 'eq', 'value': 'two' } ]; const defaultConeSearch = null; const defaultOutputList = []; @@ -395,79 +428,79 @@ describe('[Instance][Store] SearchEffects', () => { ); mockAttributeSelectorSelectAllAttributes = store.overrideSelector( attributeSelector.selectAllAttributes, [ - { - id: 1, - name: 'att1', - label: 'attribute1', - form_label: 'Attribute 1', - description: null, - primary_key: true, - type: 'string', - search_type: 'field', - operator: 'eq', - dynamic_operator: false, - min: 'one', - max: null, - placeholder_min: null, - placeholder_max: null, - criteria_display: 1, - output_display: null, - selected: false, - renderer: null, - renderer_config: null, - order_by: true, - archive: false, - detail_display: 1, - detail_renderer: null, - detail_renderer_config: null, - options: null, - vo_utype: null, - vo_ucd: null, - vo_unit: null, - vo_description: null, - vo_datatype: null, - vo_size: null, - id_criteria_family: 1, - id_output_category: null, - id_detail_output_category: null - }, - { - id: 2, - name: 'att2', - label: 'attribute2', - form_label: 'Attribute 2', - description: null, - primary_key: false, - type: 'string', - search_type: 'field', - operator: 'eq', - dynamic_operator: false, - min: 'two', - max: null, - placeholder_min: null, - placeholder_max: null, - criteria_display: 1, - output_display: null, - selected: false, - renderer: null, - renderer_config: null, - order_by: true, - archive: false, - detail_display: 1, - detail_renderer: null, - detail_renderer_config: null, - options: null, - vo_utype: null, - vo_ucd: null, - vo_unit: null, - vo_description: null, - vo_datatype: null, - vo_size: null, - id_criteria_family: 2, - id_output_category: null, - id_detail_output_category: null - } - ] + { + id: 1, + name: 'att1', + label: 'attribute1', + form_label: 'Attribute 1', + description: null, + primary_key: true, + type: 'string', + search_type: 'field', + operator: 'eq', + dynamic_operator: false, + min: 'one', + max: null, + placeholder_min: null, + placeholder_max: null, + criteria_display: 1, + output_display: null, + selected: false, + renderer: null, + renderer_config: null, + order_by: true, + archive: false, + detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, + options: null, + vo_utype: null, + vo_ucd: null, + vo_unit: null, + vo_description: null, + vo_datatype: null, + vo_size: null, + id_criteria_family: 1, + id_output_category: null, + id_detail_output_category: null + }, + { + id: 2, + name: 'att2', + label: 'attribute2', + form_label: 'Attribute 2', + description: null, + primary_key: false, + type: 'string', + search_type: 'field', + operator: 'eq', + dynamic_operator: false, + min: 'two', + max: null, + placeholder_min: null, + placeholder_max: null, + criteria_display: 1, + output_display: null, + selected: false, + renderer: null, + renderer_config: null, + order_by: true, + archive: false, + detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, + options: null, + vo_utype: null, + vo_ucd: null, + vo_unit: null, + vo_description: null, + vo_datatype: null, + vo_size: null, + id_criteria_family: 2, + id_output_category: null, + id_detail_output_category: null + } + ] ); mockSearchSelectorSelectCriteriaListByRoute = store.overrideSelector( searchSelector.selectCriteriaListByRoute, '1::eq::un;2::eq::deux' @@ -480,8 +513,8 @@ describe('[Instance][Store] SearchEffects', () => { actions = hot('-a', { a: action }); const criteriaList = [ - {'id':1,'type':'field','operator':'eq','value':'un'}, - {'id':2,'type':'field','operator':'eq','value':'deux'} + { 'id': 1, 'type': 'field', 'operator': 'eq', 'value': 'un' }, + { 'id': 2, 'type': 'field', 'operator': 'eq', 'value': 'deux' } ]; const defaultConeSearch = null; const defaultOutputList = [1, 2, 3]; @@ -531,79 +564,79 @@ describe('[Instance][Store] SearchEffects', () => { ); mockAttributeSelectorSelectAllAttributes = store.overrideSelector( attributeSelector.selectAllAttributes, [ - { - id: 1, - name: 'att1', - label: 'attribute1', - form_label: 'Attribute 1', - description: null, - primary_key: true, - type: 'string', - search_type: 'field', - operator: 'eq', - dynamic_operator: false, - min: null, - max: null, - placeholder_min: null, - placeholder_max: null, - criteria_display: 1, - output_display: 1, - selected: true, - renderer: null, - renderer_config: null, - order_by: true, - archive: false, - detail_display: 1, - detail_renderer: null, - detail_renderer_config: null, - options: null, - vo_utype: null, - vo_ucd: null, - vo_unit: null, - vo_description: null, - vo_datatype: null, - vo_size: null, - id_criteria_family: 1, - id_output_category: 1, - id_detail_output_category: null - }, - { - id: 2, - name: 'att2', - label: 'attribute2', - form_label: 'Attribute 2', - description: null, - primary_key: false, - type: 'string', - search_type: 'field', - operator: 'eq', - dynamic_operator: false, - min: null, - max: null, - placeholder_min: null, - placeholder_max: null, - criteria_display: 1, - output_display: 1, - selected: true, - renderer: null, - renderer_config: null, - order_by: true, - archive: false, - detail_display: 1, - detail_renderer: null, - detail_renderer_config: null, - options: null, - vo_utype: null, - vo_ucd: null, - vo_unit: null, - vo_description: null, - vo_datatype: null, - vo_size: null, - id_criteria_family: 2, - id_output_category: 1, - id_detail_output_category: null - } - ] + { + id: 1, + name: 'att1', + label: 'attribute1', + form_label: 'Attribute 1', + description: null, + primary_key: true, + type: 'string', + search_type: 'field', + operator: 'eq', + dynamic_operator: false, + min: null, + max: null, + placeholder_min: null, + placeholder_max: null, + criteria_display: 1, + output_display: 1, + selected: true, + renderer: null, + renderer_config: null, + order_by: true, + archive: false, + detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, + options: null, + vo_utype: null, + vo_ucd: null, + vo_unit: null, + vo_description: null, + vo_datatype: null, + vo_size: null, + id_criteria_family: 1, + id_output_category: 1, + id_detail_output_category: null + }, + { + id: 2, + name: 'att2', + label: 'attribute2', + form_label: 'Attribute 2', + description: null, + primary_key: false, + type: 'string', + search_type: 'field', + operator: 'eq', + dynamic_operator: false, + min: null, + max: null, + placeholder_min: null, + placeholder_max: null, + criteria_display: 1, + output_display: 1, + selected: true, + renderer: null, + renderer_config: null, + order_by: true, + archive: false, + detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, + options: null, + vo_utype: null, + vo_ucd: null, + vo_unit: null, + vo_description: null, + vo_datatype: null, + vo_size: null, + id_criteria_family: 2, + id_output_category: 1, + id_detail_output_category: null + } + ] ); const action = searchActions.loadDefaultFormParameters(); @@ -681,7 +714,7 @@ describe('[Instance][Store] SearchEffects', () => { datasetSelector.selectDatasetNameByRoute, 'myDataset' ); mockSearchSelectorSelectCriteriaList = store.overrideSelector( - searchSelector.selectCriteriaList, [{'id':1,'type':'field','operator':'eq','value':'one'} as Criterion] + searchSelector.selectCriteriaList, [{ 'id': 1, 'type': 'field', 'operator': 'eq', 'value': 'one' } as Criterion] ); mockConeSearchSelectorSelectConeSearch = store.overrideSelector( coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 } @@ -725,7 +758,7 @@ describe('[Instance][Store] SearchEffects', () => { describe('retrieveData$ effect', () => { it('should dispatch the retrieveDataSuccess action on success', () => { - const action = searchActions.retrieveData( { + const action = searchActions.retrieveData({ pagination: { dname: 'myDatasetName', page: 1, nbItems: 10, sortedCol: 1, order: PaginationOrder.a } }); const outcome = searchActions.retrieveDataSuccess({ data: ['data'] }); @@ -758,7 +791,7 @@ describe('[Instance][Store] SearchEffects', () => { datasetSelector.selectDatasetNameByRoute, 'myDataset' ); mockSearchSelectorSelectCriteriaList = store.overrideSelector( - searchSelector.selectCriteriaList, [{'id':1,'type':'field','operator':'eq','value':'one'} as Criterion] + searchSelector.selectCriteriaList, [{ 'id': 1, 'type': 'field', 'operator': 'eq', 'value': 'one' } as Criterion] ); mockConeSearchSelectorSelectConeSearch = store.overrideSelector( coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 } @@ -804,4 +837,21 @@ describe('[Instance][Store] SearchEffects', () => { expect(spy).toHaveBeenCalledWith('Loading Failed', 'The search data loading failed'); }); }); + describe('downloadFile$ effect', () => { + + it('should call getToken() on keycload if user is authenticated', () => { + mockAuthSelectorSelectIsAuthenticated = store.overrideSelector(authSelector.selectIsAuthenticated, true); + let spy = jest.spyOn(keycloak, 'getToken'); + // TODO: mock FileSaver + jest.mock('file-saver', () => ({ + FileSaver: { saveAs: jest.fn() } + })); + const action = searchActions.downloadFile({ filename: 'test', url: 'test?test' }); + actions = hot('(a)', { a: action }); + const expected = cold('a', { a: [action, true] }); + expect(effects.downloadFile$).toBeObservable(expected); + expect(spy).toHaveBeenCalledTimes(1); + + }); + }); }); -- GitLab