diff --git a/client/src/app/instance/store/effects/search-multiple.effects.spec.ts b/client/src/app/instance/store/effects/search-multiple.effects.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..f09533cfcbcdb05c2fe22f05ecef33f76f9367b6 --- /dev/null +++ b/client/src/app/instance/store/effects/search-multiple.effects.spec.ts @@ -0,0 +1,715 @@ +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 { cold, hot } from 'jasmine-marbles'; +import { ToastrService } from 'ngx-toastr'; + +import { SearchMultipleEffects } from './search-multiple.effects'; +import { SearchService } from '../services/search.service'; +import * as searchActions from '../actions/search.actions'; +import * as fromSearch from '../reducers/search.reducer'; +import * as datasetSelector from '../../../metamodel/selectors/dataset.selector'; +import * as searchSelector from '../selectors/search.selector'; +import * as attributeActions from '../../../metamodel/actions/attribute.actions'; +import * as criteriaFamilyActions from '../../../metamodel/actions/criteria-family.actions'; +import * as outputFamilyActions from '../../../metamodel/actions/output-family.actions'; +import * as outputCategoryActions from '../../../metamodel/actions/output-category.actions'; +import * as attributeSelector from '../../../metamodel/selectors/attribute.selector'; +import * as coneSearchSelector from '../selectors/cone-search.selector'; +import * as coneSearchActions from '../actions/cone-search.actions'; +import { Criterion, PaginationOrder } from '../models'; +import * as searchMultipleSelector from '../selectors/search-multiple.selector'; +import * as instanceSelector from '../../../metamodel/selectors/instance.selector'; +import * as searchMultipleActions from '../actions/search-multiple.actions'; + +describe('SearchMultipleEffects', () => { + let actions = new Observable(); + let effects: SearchMultipleEffects; + let metadata: EffectsMetadata<SearchMultipleEffects>; + let searchService: SearchService; + let toastr: ToastrService; + let store: MockStore; + const initialState = { search: { ...fromSearch.initialState } }; + let mockSearchMultipleSelectorSelectPristine; + let mockSearchMultipleSelectorSelectSelectedDatasetsByRoute; + let mockConeSearchSelectorSelectConeSearchByRoute; + let mockInstanceSelectorSelectorSelectInstanceByRouteName; + let mockDatasetSelectorSelectAllConeSearchDatasets; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + SearchMultipleEffects, + { provide: SearchService, useValue: { + // retrieveData: jest.fn(), + retrieveDataLength: jest.fn() + }}, + { provide: ToastrService, useValue: { error: jest.fn() }}, + provideMockActions(() => actions), + provideMockStore({ initialState }), + ] + }).compileComponents(); + effects = TestBed.inject(SearchMultipleEffects); + metadata = getEffectsMetadata(effects); + searchService = TestBed.inject(SearchService); + toastr = TestBed.inject(ToastrService); + store = TestBed.inject(MockStore); + mockSearchMultipleSelectorSelectPristine = store.overrideSelector( + searchMultipleSelector.selectPristine,true + ); + mockSearchMultipleSelectorSelectSelectedDatasetsByRoute = store.overrideSelector( + searchMultipleSelector.selectSelectedDatasetsByRoute,'' + ); + mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector( + coneSearchSelector.selectConeSearchByRoute,'' + ); + mockInstanceSelectorSelectorSelectInstanceByRouteName = store.overrideSelector( + instanceSelector.selectInstanceByRouteName,{ + name: 'myInstance', + label: 'My Instance', + data_path: 'data/path', + config: { + design: { + design_color: 'green', + design_background_color: 'darker green', + design_logo: 'path/to/logo', + design_favicon: 'path/to/favicon' + }, + home: { + home_component: 'HomeComponent', + home_config: { + home_component_text: 'Description', + home_component_logo: 'path/to/logo' + } + }, + search: { + search_by_criteria_allowed: true, + search_by_criteria_label: 'Search', + search_multiple_allowed: true, + search_multiple_label: 'Search multiple', + search_multiple_all_datasets_selected: true + }, + documentation: { + documentation_allowed: true, + documentation_label: 'Documentation' + } + }, + nb_dataset_families: 1, + nb_datasets: 2 + } + ); + mockDatasetSelectorSelectAllConeSearchDatasets = store.overrideSelector( + searchSelector.selectOutputListByRoute,'' + ); + }); + + it('should be created', () => { + expect(effects).toBeTruthy(); + }); + + describe('initSearch$ effect', () => { + it('should dispatch the restartSearch action when dataset or cone search changed', () => { + mockSearchMultipleSelectorSelectPristine = store.overrideSelector( + searchMultipleSelector.selectPristine,true + ); + mockSearchMultipleSelectorSelectSelectedDatasetsByRoute = store.overrideSelector( + searchMultipleSelector.selectSelectedDatasetsByRoute,'' + ); + mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector( + coneSearchSelector.selectConeSearchByRoute,'' + ); + mockInstanceSelectorSelectorSelectInstanceByRouteName = store.overrideSelector( + instanceSelector.selectInstanceByRouteName,{ + name: 'myInstance', + label: 'My Instance', + data_path: 'data/path', + config: { + design: { + design_color: 'green', + design_background_color: 'darker green', + design_logo: 'path/to/logo', + design_favicon: 'path/to/favicon' + }, + home: { + home_component: 'HomeComponent', + home_config: { + home_component_text: 'Description', + home_component_logo: 'path/to/logo' + } + }, + search: { + search_by_criteria_allowed: true, + search_by_criteria_label: 'Search', + search_multiple_allowed: true, + search_multiple_label: 'Search multiple', + search_multiple_all_datasets_selected: true + }, + documentation: { + documentation_allowed: true, + documentation_label: 'Documentation' + } + }, + nb_dataset_families: 1, + nb_datasets: 2 + } + ); + mockDatasetSelectorSelectAllConeSearchDatasets = store.overrideSelector( + searchSelector.selectOutputListByRoute,'' + ); + + const action = searchMultipleActions.initSearch(); + actions = hot('-a', { a: action }); + const expected = cold('-(bc)', { + b: coneSearchActions.deleteConeSearch(), + c: searchMultipleActions.restartSearch() + }); + + expect(effects.initSearch$).toBeObservable(expected); + }); + + // it('should dispatch a bunch of actions when a dataset is selected or a page is reloaded', () => { + // mockDatasetSelectorSelectDatasetNameByRoute = store.overrideSelector( + // datasetSelector.selectDatasetNameByRoute, 'myDatasetName' + // ); + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine,true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset,'myDatasetName' + // ); + // + // const action = searchActions.initSearch(); + // actions = hot('-a', { a: action }); + // const expected = cold('-(bcdef)', { + // b: searchActions.changeCurrentDataset({ currentDataset: 'myDatasetName' }), + // c: attributeActions.loadAttributeList(), + // d: criteriaFamilyActions.loadCriteriaFamilyList(), + // e: outputFamilyActions.loadOutputFamilyList(), + // f: outputCategoryActions.loadOutputCategoryList() + // }); + // + // expect(effects.initSearch$).toBeObservable(expected); + // }); + // + // it('should dispatch a bunch of actions when a dataset is selected or a page is reloaded with steps checked', () => { + // mockDatasetSelectorSelectDatasetNameByRoute = store.overrideSelector( + // datasetSelector.selectDatasetNameByRoute, 'myDatasetName' + // ); + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine,true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset,'myDatasetName' + // ); + // mockSearchSelectorSelectStepsByRoute = store.overrideSelector( + // searchSelector.selectStepsByRoute, '111' + // ); + // + // const action = searchActions.initSearch(); + // actions = hot('-a', { a: action }); + // const expected = cold('-(bcdefghi)', { + // b: searchActions.changeCurrentDataset({ currentDataset: 'myDatasetName' }), + // c: attributeActions.loadAttributeList(), + // d: criteriaFamilyActions.loadCriteriaFamilyList(), + // e: outputFamilyActions.loadOutputFamilyList(), + // f: outputCategoryActions.loadOutputCategoryList(), + // g: searchActions.checkCriteria(), + // h: searchActions.checkOutput(), + // i: searchActions.checkResult() + // }); + // + // expect(effects.initSearch$).toBeObservable(expected); + // }); + // + // it('should dispatch a resetSearch action when user get back to search module', () => { + // mockDatasetSelectorSelectDatasetNameByRoute = store.overrideSelector( + // datasetSelector.selectDatasetNameByRoute, '' + // ); + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine,false + // ); + // + // const action = searchActions.initSearch(); + // const outcome = searchActions.resetSearch(); + // + // actions = hot('-a', { a: action }); + // const expected = cold('-b', { b: outcome }); + // + // expect(effects.initSearch$).toBeObservable(expected); + // }); + // + // it('should not dispatch action when step changed on same search', () => { + // mockDatasetSelectorSelectDatasetNameByRoute = store.overrideSelector( + // datasetSelector.selectDatasetNameByRoute, '' + // ); + // + // const action = searchActions.initSearch(); + // const outcome = { type: '[No Action] Init Search' }; + // + // actions = hot('-a', { a: action }); + // const expected = cold('-b', { b: outcome }); + // + // expect(effects.initSearch$).toBeObservable(expected); + // }); + }); + + describe('restartSearch$ effect', () => { + it('should dispatch the initSearch action', () => { + const action = searchMultipleActions.restartSearch(); + const outcome = searchMultipleActions.initSearch(); + + actions = hot('-a', { a: action }); + const expected = cold('-b', { b: outcome }); + + expect(effects.restartSearch$).toBeObservable(expected); + }); + }); + + // describe('loadDefaultFormParameters$ effect', () => { + // it('should not dispatch action if params already loaded', () => { + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine, false + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset, 'myDataset' + // ); + // + // const action = searchActions.loadDefaultFormParameters(); + // const outcome = { type: '[No Action] Load Default Form Parameters' }; + // + // actions = hot('-a', { a: action }); + // const expected = cold('-b', { b: outcome }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // + // it('should not dispatch action if no dataset selected', () => { + // const action = searchActions.loadDefaultFormParameters(); + // const outcome = { type: '[No Action] Load Default Form Parameters' }; + // + // actions = hot('-a', { a: action }); + // const expected = cold('-b', { b: outcome }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // + // it('should dispatch a bunch of actions to update search', () => { + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine, true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset, 'myDataset' + // ); + // + // const action = searchActions.loadDefaultFormParameters(); + // actions = hot('-a', { a: action }); + // + // const defaultCriteriaList = []; + // const defaultConeSearch = null; + // const defaultOutputList = []; + // const expected = cold('-(bcde)', { + // b: searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }), + // c: coneSearchActions.addConeSearch({ coneSearch: defaultConeSearch }), + // d: searchActions.updateOutputList({ outputList: defaultOutputList }), + // e: searchActions.markAsDirty() + // }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // + // it('should set a default criteria list', () => { + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine, true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset, 'myDataset' + // ); + // mockAttributeSelectorSelectAllAttributes = store.overrideSelector( + // attributeSelector.selectAllAttributes, [ + // { + // id: 1, + // name: 'att1', + // label: 'attribute1', + // form_label: 'Attribute 1', + // output_display: 1, + // criteria_display: 1, + // search_type: 'field', + // operator: 'eq', + // type: 'string', + // min: 'one', + // display_detail: 1, + // id_criteria_family: 1, + // id_output_category: 1 + // }, + // { + // id: 2, + // name: 'att2', + // label: 'attribute2', + // form_label: 'Attribute 2', + // output_display: 1, + // criteria_display: 1, + // search_type: 'field', + // operator: 'eq', + // type: 'string', + // min: 'two', + // display_detail: 1, + // id_criteria_family: 2, + // id_output_category: 1 + // } + // ] + // ); + // + // 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'} + // ]; + // const defaultConeSearch = null; + // const defaultOutputList = []; + // const expected = cold('-(bcde)', { + // b: searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }), + // c: coneSearchActions.addConeSearch({ coneSearch: defaultConeSearch }), + // d: searchActions.updateOutputList({ outputList: defaultOutputList }), + // e: searchActions.markAsDirty() + // }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // + // it('should set criteria list from URL', () => { + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine, true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset, 'myDataset' + // ); + // mockAttributeSelectorSelectAllAttributes = store.overrideSelector( + // attributeSelector.selectAllAttributes, [ + // { + // id: 1, + // name: 'att1', + // label: 'attribute1', + // form_label: 'Attribute 1', + // output_display: 1, + // criteria_display: 1, + // search_type: 'field', + // operator: 'eq', + // type: 'string', + // min: 'one', + // display_detail: 1, + // id_criteria_family: 1, + // id_output_category: 1 + // }, + // { + // id: 2, + // name: 'att2', + // label: 'attribute2', + // form_label: 'Attribute 2', + // output_display: 1, + // criteria_display: 1, + // search_type: 'field', + // operator: 'eq', + // type: 'string', + // min: 'two', + // display_detail: 1, + // id_criteria_family: 2, + // id_output_category: 1 + // } + // ] + // ); + // mockSearchSelectorSelectCriteriaListByRoute = store.overrideSelector( + // searchSelector.selectCriteriaListByRoute, '1::eq::un;2::eq::deux' + // ); + // + // const action = searchActions.loadDefaultFormParameters(); + // actions = hot('-a', { a: action }); + // + // const criteriaList = [ + // {'id':1,'type':'field','operator':'eq','value':'un'}, + // {'id':2,'type':'field','operator':'eq','value':'deux'} + // ]; + // const defaultConeSearch = null; + // const defaultOutputList = []; + // const expected = cold('-(bcde)', { + // b: searchActions.updateCriteriaList({ criteriaList: criteriaList }), + // c: coneSearchActions.addConeSearch({ coneSearch: defaultConeSearch }), + // d: searchActions.updateOutputList({ outputList: defaultOutputList }), + // e: searchActions.markAsDirty() + // }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // + // it('should set cone search from URL', () => { + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine, true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset, 'myDataset' + // ); + // mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector( + // coneSearchSelector.selectConeSearchByRoute, '1:2:3' + // ); + // + // const action = searchActions.loadDefaultFormParameters(); + // actions = hot('-a', { a: action }); + // + // const defaultCriteriaList = []; + // const coneSearch = { ra: 1, dec: 2, radius: 3 }; + // const defaultOutputList = []; + // const expected = cold('-(bcde)', { + // b: searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }), + // c: coneSearchActions.addConeSearch({ coneSearch: coneSearch }), + // d: searchActions.updateOutputList({ outputList: defaultOutputList }), + // e: searchActions.markAsDirty() + // }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // + // it('should set a default output list', () => { + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine, true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset, 'myDataset' + // ); + // mockAttributeSelectorSelectAllAttributes = store.overrideSelector( + // attributeSelector.selectAllAttributes, [ + // { + // id: 1, + // name: 'att1', + // label: 'attribute1', + // form_label: 'Attribute 1', + // output_display: 1, + // criteria_display: 1, + // search_type: 'field', + // operator: 'eq', + // type: 'string', + // display_detail: 1, + // selected: true, + // id_criteria_family: 1, + // id_output_category: 1 + // }, + // { + // id: 2, + // name: 'att2', + // label: 'attribute2', + // form_label: 'Attribute 2', + // output_display: 1, + // criteria_display: 1, + // search_type: 'field', + // operator: 'eq', + // type: 'string', + // display_detail: 1, + // selected: true, + // id_criteria_family: 2, + // id_output_category: 1 + // } + // ] + // ); + // + // const action = searchActions.loadDefaultFormParameters(); + // actions = hot('-a', { a: action }); + // + // const defaultCriteriaList = []; + // const defaultConeSearch = null; + // const defaultOutputList = [1, 2]; + // const expected = cold('-(bcde)', { + // b: searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }), + // c: coneSearchActions.addConeSearch({ coneSearch: defaultConeSearch }), + // d: searchActions.updateOutputList({ outputList: defaultOutputList }), + // e: searchActions.markAsDirty() + // }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // + // it('should set output list from URL', () => { + // mockSearchSelectorSelectPristine = store.overrideSelector( + // searchSelector.selectPristine, true + // ); + // mockSearchSelectorSelectCurrentDataset = store.overrideSelector( + // searchSelector.selectCurrentDataset, 'myDataset' + // ); + // mockSearchSelectorSelectOutputListByRoute = store.overrideSelector( + // searchSelector.selectOutputListByRoute, '1;2;3' + // ); + // + // const action = searchActions.loadDefaultFormParameters(); + // actions = hot('-a', { a: action }); + // + // const defaultCriteriaList = []; + // const defaultConeSearch = null; + // const outputList = [1, 2, 3]; + // const expected = cold('-(bcde)', { + // b: searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }), + // c: coneSearchActions.addConeSearch({ coneSearch: defaultConeSearch }), + // d: searchActions.updateOutputList({ outputList: outputList }), + // e: searchActions.markAsDirty() + // }); + // + // expect(effects.loadDefaultFormParameters$).toBeObservable(expected); + // }); + // }); + + // describe('retrieveDataLength$ effect', () => { + // it('should dispatch the retrieveDataLengthSuccess action on success', () => { + // const action = searchActions.retrieveDataLength(); + // const outcome = searchActions.retrieveDataLengthSuccess({ length: 5 }); + // + // actions = hot('-a', { a: action }); + // const response = cold('-b|', { b: [{ nb: 5 }] }); + // const expected = cold('--c', { c: outcome }); + // searchService.retrieveDataLength = jest.fn(() => response); + // + // expect(effects.retrieveDataLength$).toBeObservable(expected); + // }); + // + // it('should dispatch the retrieveDataLengthFail action on failure', () => { + // const action = searchActions.retrieveDataLength(); + // const error = new Error(); + // const outcome = searchActions.retrieveDataLengthFail(); + // + // actions = hot('-a', { a: action }); + // const response = cold('-#|', {}, error); + // const expected = cold('--b', { b: outcome }); + // searchService.retrieveDataLength = jest.fn(() => response); + // + // expect(effects.retrieveDataLength$).toBeObservable(expected); + // }); + // + // it('should pass correct query to the service', () => { + // mockDatasetSelectorSelectDatasetNameByRoute = store.overrideSelector( + // datasetSelector.selectDatasetNameByRoute, 'myDataset' + // ); + // mockSearchSelectorSelectCriteriaList = store.overrideSelector( + // searchSelector.selectCriteriaList, [{'id':1,'type':'field','operator':'eq','value':'one'} as Criterion] + // ); + // mockConeSearchSelectorSelectConeSearch = store.overrideSelector( + // coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 } + // ); + // + // jest.spyOn(searchService, 'retrieveDataLength'); + // + // const action = searchActions.retrieveDataLength(); + // const outcome = searchActions.retrieveDataLengthSuccess({ length: 5 }); + // + // actions = hot('-a', { a: action }); + // const response = cold('-b|', { b: [{ nb: 5 }] }); + // const expected = cold('--c', { c: outcome }); + // searchService.retrieveDataLength = jest.fn(() => response); + // + // expect(effects.retrieveDataLength$).toBeObservable(expected); + // expect(searchService.retrieveDataLength).toHaveBeenCalledTimes(1); + // expect(searchService.retrieveDataLength).toHaveBeenCalledWith('myDataset?a=count&c=1::eq::one&cs=1:2:3'); + // }); + // }); + + describe('retrieveDataLengthFail$ effect', () => { + it('should not dispatch', () => { + expect(metadata.retrieveDataLengthFail$).toEqual( + expect.objectContaining({ dispatch: false }) + ); + }); + + it('should display a error notification', () => { + const spy = jest.spyOn(toastr, 'error'); + const action = searchMultipleActions.retrieveDataLengthFail(); + + actions = hot('a', { a: action }); + const expected = cold('a', { a: action }); + + expect(effects.retrieveDataLengthFail$).toBeObservable(expected); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith('Loading Failed', 'The search multiple data length loading failed'); + }); + }); + + // describe('retrieveData$ effect', () => { + // it('should dispatch the retrieveDataSuccess action on success', () => { + // const action = searchActions.retrieveData( { + // pagination: { dname: 'myDatasetName', page: 1, nbItems: 10, sortedCol: 1, order: PaginationOrder.a } + // }); + // const outcome = searchActions.retrieveDataSuccess({ data: ['data'] }); + // + // actions = hot('-a', { a: action }); + // const response = cold('-b|', { b: ['data'] }); + // const expected = cold('--c', { c: outcome }); + // searchService.retrieveData = jest.fn(() => response); + // + // expect(effects.retrieveData$).toBeObservable(expected); + // }); + // + // it('should dispatch the retrieveDataFail action on failure', () => { + // const action = searchActions.retrieveData({ + // pagination: { dname: 'myDatasetName', page: 1, nbItems: 10, sortedCol: 1, order: PaginationOrder.a } + // }); + // const error = new Error(); + // const outcome = searchActions.retrieveDataFail(); + // + // actions = hot('-a', { a: action }); + // const response = cold('-#|', {}, error); + // const expected = cold('--b', { b: outcome }); + // searchService.retrieveData = jest.fn(() => response); + // + // expect(effects.retrieveData$).toBeObservable(expected); + // }); + // + // it('should pass correct query to the service', () => { + // mockDatasetSelectorSelectDatasetNameByRoute = store.overrideSelector( + // datasetSelector.selectDatasetNameByRoute, 'myDataset' + // ); + // mockSearchSelectorSelectCriteriaList = store.overrideSelector( + // searchSelector.selectCriteriaList, [{'id':1,'type':'field','operator':'eq','value':'one'} as Criterion] + // ); + // mockConeSearchSelectorSelectConeSearch = store.overrideSelector( + // coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 } + // ); + // mockSearchSelectorSelectOutputList = store.overrideSelector( + // searchSelector.selectOutputList, [1, 2] + // ); + // + // jest.spyOn(searchService, 'retrieveData'); + // + // const action = searchActions.retrieveData({ + // pagination: { dname: 'myDatasetName', page: 1, nbItems: 10, sortedCol: 1, order: PaginationOrder.a } + // }); + // const outcome = searchActions.retrieveDataSuccess({ data: ['data'] }); + // + // actions = hot('-a', { a: action }); + // const response = cold('-b|', { b: ['data'] }); + // const expected = cold('--c', { c: outcome }); + // searchService.retrieveData = jest.fn(() => response); + // + // expect(effects.retrieveData$).toBeObservable(expected); + // expect(searchService.retrieveData).toHaveBeenCalledTimes(1); + // expect(searchService.retrieveData).toHaveBeenCalledWith('myDataset?a=1;2&c=1::eq::one&cs=1:2:3&p=10:1&o=1:a'); + // }); + // }); + + // describe('retrieveDataFail$ effect', () => { + // it('should not dispatch', () => { + // expect(metadata.retrieveDataFail$).toEqual( + // expect.objectContaining({ dispatch: false }) + // ); + // }); + // + // it('should display a error notification', () => { + // const spy = jest.spyOn(toastr, 'error'); + // const action = searchActions.retrieveDataFail(); + // + // actions = hot('a', { a: action }); + // const expected = cold('a', { a: action }); + // + // expect(effects.retrieveDataFail$).toBeObservable(expected); + // expect(spy).toHaveBeenCalledTimes(1); + // expect(spy).toHaveBeenCalledWith('Loading Failed', 'The search data loading failed'); + // }); + // }); +}); diff --git a/client/src/app/instance/store/effects/search-multiple.effects.ts b/client/src/app/instance/store/effects/search-multiple.effects.ts index 84382d44732bfb1c719f7d0cbaa96e4326c693a3..8fd7a53c3b63b22bcd960f4016cb002cd33d69ad 100644 --- a/client/src/app/instance/store/effects/search-multiple.effects.ts +++ b/client/src/app/instance/store/effects/search-multiple.effects.ts @@ -26,7 +26,11 @@ import * as coneSearchSelector from '../selectors/cone-search.selector'; @Injectable() export class SearchMultipleEffects { - initSearch$ = createEffect(() => + + /** + * Calls actions to initialize search multiple. + */ + initSearch$ = createEffect((): any => this.actions$.pipe( ofType(searchMultipleActions.initSearch), concatLatestFrom(() => [ @@ -86,14 +90,20 @@ export class SearchMultipleEffects { ) ); - restartSearch$ = createEffect(() => + /** + * Calls actions to restart search multiple. + */ + restartSearch$ = createEffect((): any => this.actions$.pipe( ofType(searchMultipleActions.restartSearch), map(() => searchMultipleActions.initSearch()) ) ); - retrieveDataLength$ = createEffect(() => + /** + * Calls actions to retrieve data length. + */ + retrieveDataLength$ = createEffect((): any => this.actions$.pipe( ofType(searchMultipleActions.retrieveDataLength), concatLatestFrom(() => [ @@ -116,11 +126,14 @@ export class SearchMultipleEffects { ) ); - retrieveDataLengthFail$ = createEffect(() => + /** + * Displays retrieve data length error notification. + */ + retrieveDataLengthFail$ = createEffect(() => this.actions$.pipe( ofType(searchMultipleActions.retrieveDataLengthFail), tap(() => this.toastr.error('Loading Failed', 'The search multiple data length loading failed')) - ), { dispatch: false} + ), { dispatch: false } ); constructor(