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..ed415dad1fe4868f45a89b6451b1e40a623f3d86
--- /dev/null
+++ b/client/src/app/instance/store/effects/search-multiple.effects.spec.ts
@@ -0,0 +1,572 @@
+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 fromSearchMultiple from '../reducers/search-multiple.reducer';
+import * as fromInstance from '../../../metamodel/reducers/instance.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 { ConeSearch, Criterion, PaginationOrder, SearchMultipleDatasetLength } 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 = {
+        metamodel: { instance: { ...fromInstance.initialState }},
+        instance: {
+            search: {...fromSearch.initialState},
+            searchMultiple: {...fromSearchMultiple.initialState}
+        }
+    };
+    let mockSearchMultipleSelectorSelectPristine;
+    let mockSearchMultipleSelectorSelectSelectedDatasetsByRoute;
+    let mockSearchMultipleSelectorSelectSelectedDatasets;
+    let mockConeSearchSelectorSelectConeSearchByRoute;
+    let mockConeSearchSelectorSelectConeSearch;
+    let mockInstanceSelectorSelectorSelectInstanceByRouteName;
+    let mockDatasetSelectorSelectAllConeSearchDatasets;
+
+    beforeEach(() => {
+        TestBed.configureTestingModule({
+            providers: [
+                SearchMultipleEffects,
+                { provide: SearchService, useValue: { 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,''
+        );
+        mockSearchMultipleSelectorSelectSelectedDatasets = store.overrideSelector(
+            searchMultipleSelector.selectSelectedDatasets, []
+        );
+        mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector(
+            coneSearchSelector.selectConeSearchByRoute,''
+        );
+        mockConeSearchSelectorSelectConeSearch = store.overrideSelector(
+            coneSearchSelector.selectConeSearch,undefined
+        );
+        mockInstanceSelectorSelectorSelectInstanceByRouteName = store.overrideSelector(
+            instanceSelector.selectInstanceByRouteName,undefined
+        );
+        mockDatasetSelectorSelectAllConeSearchDatasets = store.overrideSelector(
+            datasetSelector.selectAllConeSearchDatasets,[]
+        );
+    });
+
+    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,false
+            );
+            mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector(
+                coneSearchSelector.selectConeSearchByRoute,''
+            );
+
+            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 not dispatch action when default form parameters already loaded or no dataset selected', () => {
+            mockSearchMultipleSelectorSelectPristine = store.overrideSelector(
+                searchMultipleSelector.selectPristine,false
+            );
+            mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector(
+                coneSearchSelector.selectConeSearchByRoute,'1:2:3'
+            );
+
+            const action = searchMultipleActions.initSearch();
+            actions = hot('-a', { a: action });
+            const expected = cold('-b', { b: { type: '[No Action] Load Default Form Parameters' } });
+
+            expect(effects.initSearch$).toBeObservable(expected);
+        });
+
+        it('should dispatch a bunch of actions when page is reloaded with cone search in it', () => {
+            mockSearchMultipleSelectorSelectPristine = store.overrideSelector(
+                searchMultipleSelector.selectPristine,true
+            );
+            mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector(
+                coneSearchSelector.selectConeSearchByRoute,'1:2:3'
+            );
+            mockSearchMultipleSelectorSelectSelectedDatasetsByRoute = store.overrideSelector(
+                searchMultipleSelector.selectSelectedDatasetsByRoute,''
+            );
+            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: false
+                        },
+                        documentation: {
+                            documentation_allowed: true,
+                            documentation_label: 'Documentation'
+                        }
+                    },
+                    nb_dataset_families: 1,
+                    nb_datasets: 2
+                }
+            );
+
+            const coneSearch: ConeSearch = { ra: 1, dec: 2, radius: 3 };
+
+            const action = searchMultipleActions.initSearch();
+            actions = hot('-a', { a: action });
+            const expected = cold('-(bc)', {
+                b: searchMultipleActions.markAsDirty(),
+                c: coneSearchActions.addConeSearch({ coneSearch })
+            });
+
+            expect(effects.initSearch$).toBeObservable(expected);
+        });
+
+        it('should dispatch a bunch of actions when page is reloaded with selected datasets in it', () => {
+            mockSearchMultipleSelectorSelectPristine = store.overrideSelector(
+                searchMultipleSelector.selectPristine,true
+            );
+            mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector(
+                coneSearchSelector.selectConeSearchByRoute,''
+            );
+            mockSearchMultipleSelectorSelectSelectedDatasetsByRoute = store.overrideSelector(
+                searchMultipleSelector.selectSelectedDatasetsByRoute,'d1;d2'
+            );
+
+            const selectedDatasets: string[] = ['d1', 'd2'];
+
+            const action = searchMultipleActions.initSearch();
+            actions = hot('-a', { a: action });
+            const expected = cold('-(bcd)', {
+                b: searchMultipleActions.markAsDirty(),
+                c: searchMultipleActions.updateSelectedDatasets({ selectedDatasets }),
+                d: searchMultipleActions.checkDatasets()
+            });
+
+            expect(effects.initSearch$).toBeObservable(expected);
+        });
+
+        it('should dispatch a bunch of actions when page is reloaded with default selected datasets', () => {
+            mockSearchMultipleSelectorSelectPristine = store.overrideSelector(
+                searchMultipleSelector.selectPristine,true
+            );
+            mockConeSearchSelectorSelectConeSearchByRoute = store.overrideSelector(
+                coneSearchSelector.selectConeSearchByRoute,''
+            );
+            mockSearchMultipleSelectorSelectSelectedDatasetsByRoute = store.overrideSelector(
+                searchMultipleSelector.selectSelectedDatasetsByRoute,''
+            );
+            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(
+                datasetSelector.selectAllConeSearchDatasets, [
+                    {
+                        name: 'myDataset',
+                        table_ref: '',
+                        label: '',
+                        description: '',
+                        display: 1,
+                        data_path: '',
+                        survey_name: '',
+                        id_dataset_family: 1,
+                        public: true,
+                        full_data_path: '',
+                        config: {
+                            images: [],
+                            survey: {
+                                survey_enabled: true,
+                                survey_label: ''
+                            },
+                            cone_search: {
+                                cone_search_enabled: true,
+                                cone_search_opened: true,
+                                cone_search_column_ra: 1,
+                                cone_search_column_dec: 2,
+                                cone_search_plot_enabled: true,
+                                cone_search_sdss_enabled: true,
+                                cone_search_sdss_display: 1,
+                                cone_search_background: []
+                            },
+                            download: {
+                                download_enabled: true,
+                                download_opened: true,
+                                download_csv: true,
+                                download_ascii: true,
+                                download_vo: true,
+                                download_archive: true
+                            },
+                            summary: {
+                                summary_enabled: true,
+                                summary_opened: true
+                            },
+                            server_link: {
+                                server_link_enabled: true,
+                                server_link_opened: true
+                            },
+                            samp: {
+                                samp_enabled: true,
+                                samp_opened: true
+                            },
+                            datatable: {
+                                datatable_enabled: true,
+                                datatable_opened: true,
+                                datatable_selectable_rows: true
+                            }
+                        }
+                    }
+                ]
+            );
+
+            const selectedDatasets: string[] = ['myDataset'];
+
+            const action = searchMultipleActions.initSearch();
+            actions = hot('-a', { a: action });
+            const expected = cold('-(bc)', {
+                b: searchMultipleActions.markAsDirty(),
+                c: searchMultipleActions.updateSelectedDatasets({ selectedDatasets })
+            });
+
+            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('retrieveDataLength$ effect', () => {
+        it('should dispatch the retrieveDataLengthSuccess action on success', () => {
+            mockSearchMultipleSelectorSelectSelectedDatasets = store.overrideSelector(
+                searchMultipleSelector.selectSelectedDatasets, ['myDataset']
+            );
+            mockConeSearchSelectorSelectConeSearch = store.overrideSelector(
+                coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 }
+            );
+
+            const dataLength: SearchMultipleDatasetLength[] = [{ datasetName: 'myDataset', length: 1 }];
+            const action = searchMultipleActions.retrieveDataLength();
+            const outcome = searchMultipleActions.retrieveDataLengthSuccess({ dataLength });
+
+            actions = hot('-a', { a: action });
+            const response = cold('-b|', { b: [{ nb: 1 }] });
+            const expected = cold('---c', { c: outcome });
+            searchService.retrieveDataLength = jest.fn(() => response);
+
+            expect(effects.retrieveDataLength$).toBeObservable(expected);
+        });
+
+        it('should dispatch the retrieveDataLengthFail action on failure', () => {
+            mockSearchMultipleSelectorSelectSelectedDatasets = store.overrideSelector(
+                searchMultipleSelector.selectSelectedDatasets, ['myDataset']
+            );
+            mockConeSearchSelectorSelectConeSearch = store.overrideSelector(
+                coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 }
+            );
+
+            const action = searchMultipleActions.retrieveDataLength();
+            const error = new Error();
+            const outcome = searchMultipleActions.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', () => {
+            mockSearchMultipleSelectorSelectSelectedDatasets = store.overrideSelector(
+                searchMultipleSelector.selectSelectedDatasets, ['myDataset', 'myOtherDataset']
+            );
+            mockConeSearchSelectorSelectConeSearch = store.overrideSelector(
+                coneSearchSelector.selectConeSearch, { ra: 1, dec: 2, radius: 3 }
+            );
+
+            const dataLength: SearchMultipleDatasetLength[] = [
+                { datasetName: 'myDataset', length: 1 },
+                { datasetName: 'myOtherDataset', length: 1 }
+            ];
+
+            jest.spyOn(searchService, 'retrieveDataLength');
+
+            const action = searchMultipleActions.retrieveDataLength();
+            const outcome = searchMultipleActions.retrieveDataLengthSuccess({ dataLength });
+
+            actions = hot('-a', { a: action });
+            const response = cold('-b|', { b: [{ nb: 1 }] });
+            const expected = cold('---c', { c: outcome });
+            searchService.retrieveDataLength = jest.fn(() => response);
+
+            expect(effects.retrieveDataLength$).toBeObservable(expected);
+            expect(searchService.retrieveDataLength).toHaveBeenCalledTimes(2);
+            expect(searchService.retrieveDataLength).toHaveBeenCalledWith('myDataset?a=count&cs=1:2:3');
+            expect(searchService.retrieveDataLength).toHaveBeenCalledWith('myOtherDataset?a=count&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..2cd1eeab2499f9ad5e1ca91ba7d6dfda8768c8f1 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(() => [
@@ -37,16 +41,16 @@ export class SearchMultipleEffects {
                 this.store.select(datasetSelector.selectAllConeSearchDatasets)
             ]),
             mergeMap(([action, pristine, coneSearchByRoute, selectedDatasetsByRoute, instance, datasetList]) => {
+                // Restart search
                 if (!pristine && !coneSearchByRoute) {
-                    // Restart search
                     return [
                         coneSearchActions.deleteConeSearch(),
                         searchMultipleActions.restartSearch()
                     ];
                 }
 
+                // Default form parameters already loaded or no dataset selected
                 if (!pristine) {
-                    // Default form parameters already loaded or no dataset selected
                     return of({ type: '[No Action] Load Default Form Parameters' });
                 }
 
@@ -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(
diff --git a/client/src/app/instance/store/models/criterion.model.ts b/client/src/app/instance/store/models/criterion.model.ts
index a6118e881162183a5c5bcbf1a4b63b5ad72ec2e9..95f9d974ce488501c9af3e0b868c91b3be1f2ac8 100644
--- a/client/src/app/instance/store/models/criterion.model.ts
+++ b/client/src/app/instance/store/models/criterion.model.ts
@@ -17,8 +17,9 @@ import {
 import { Attribute } from 'src/app/metamodel/models';
 
 /**
- * @class
- * @classdesc Criterion class.
+ * Interface for criterion.
+ *
+ * @interface Criterion
  */
 export interface Criterion {
     id: number;
diff --git a/client/src/app/instance/store/models/criterion/select-multiple-criterion.model.ts b/client/src/app/instance/store/models/criterion/select-multiple-criterion.model.ts
index 90fc0ae7499ea8d2f68ba3571503474e74a18532..e1da198fb35d9069df0126c9d1abb91439a8fae9 100644
--- a/client/src/app/instance/store/models/criterion/select-multiple-criterion.model.ts
+++ b/client/src/app/instance/store/models/criterion/select-multiple-criterion.model.ts
@@ -11,10 +11,9 @@ import { Criterion } from '../criterion.model';
 import { Option } from 'src/app/metamodel/models/option.model';
 
 /**
- * @class
- * @classdesc Select multiple criterion class.
+ * Interface for select multiple criterion.
  *
- * @implements Criterion
+ * @interface SelectMultipleCriterion
  */
 export interface SelectMultipleCriterion extends Criterion {
     id: number;
diff --git a/client/src/app/instance/store/models/search-multiple-dataset-data.ts b/client/src/app/instance/store/models/search-multiple-dataset-data.ts
index fa25ed88176093d7840cdd984c476aed52b25ed3..0f3d0d86928cb33b5ca735f14aea4fc281b1d4da 100644
--- a/client/src/app/instance/store/models/search-multiple-dataset-data.ts
+++ b/client/src/app/instance/store/models/search-multiple-dataset-data.ts
@@ -7,6 +7,11 @@
  * file that was distributed with this source code.
  */
 
+/**
+ * Interface for search multiple data.
+ *
+ * @interface SearchMultipleDatasetData
+ */
 export interface SearchMultipleDatasetData {
     datasetName: string;
     data: any[];
diff --git a/client/src/app/instance/store/models/search-multiple-dataset-length.ts b/client/src/app/instance/store/models/search-multiple-dataset-length.ts
index 75961a0d5c68acd8878099d32715c9a4c9143242..73a3e0de377302eeefc85bbd15f42be7a7882c46 100644
--- a/client/src/app/instance/store/models/search-multiple-dataset-length.ts
+++ b/client/src/app/instance/store/models/search-multiple-dataset-length.ts
@@ -7,6 +7,11 @@
  * file that was distributed with this source code.
  */
 
+/**
+ * Interface for search multiple data length.
+ *
+ * @interface SearchMultipleDatasetLength
+ */
 export interface SearchMultipleDatasetLength {
     datasetName: string;
     length: number;
diff --git a/client/src/app/instance/store/reducers/search-multiple.reducer.spec.ts b/client/src/app/instance/store/reducers/search-multiple.reducer.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5e3ce85eec3702448d7061a4d49d6d11bc0254a9
--- /dev/null
+++ b/client/src/app/instance/store/reducers/search-multiple.reducer.spec.ts
@@ -0,0 +1,363 @@
+import { Action } from '@ngrx/store';
+
+import * as fromSearchMultiple from './search-multiple.reducer';
+import * as searchMultipleActions from '../actions/search-multiple.actions';
+import { SearchMultipleDatasetData, SearchMultipleDatasetLength } from '../models';
+
+describe('SearchMultiple reducer', () => {
+    it('unknown action should return the default state', () => {
+        const { initialState } = fromSearchMultiple;
+        const action = { type: 'Unknown' };
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state).toBe(initialState);
+    });
+
+    it('restartSearch action should set currentStep to \'position\'', () => {
+        const { initialState } = fromSearchMultiple;
+        const action = searchMultipleActions.restartSearch();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toEqual('position');
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('changeStep action should change the currentStep', () => {
+        const { initialState } = fromSearchMultiple;
+        const action = searchMultipleActions.changeStep({ step: 'myStep' });
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toEqual('myStep');
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('markAsDirty action should set pristine to false', () => {
+        const { initialState } = fromSearchMultiple;
+        const action = searchMultipleActions.markAsDirty();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeFalsy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('checkDatasets action should set datasetsStepChecked to true', () => {
+        const { initialState } = fromSearchMultiple;
+        const action = searchMultipleActions.checkDatasets();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeTruthy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('checkResult action should set resultStepChecked to true', () => {
+        const { initialState } = fromSearchMultiple;
+        const action = searchMultipleActions.checkResult();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeTruthy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('updateSelectedDatasets action should set selectedDatasets', () => {
+        const { initialState } = fromSearchMultiple;
+        const selectedDatasets: string[] = ['myDataset'];
+        const action = searchMultipleActions.updateSelectedDatasets({ selectedDatasets });
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(1);
+        expect(state.selectedDatasets).toEqual(selectedDatasets);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('retrieveDataLength action should set dataLengthIsLoading to true and dataLengthIsLoaded to false', () => {
+        const initialState = {
+            ...fromSearchMultiple.initialState,
+            dataLengthIsLoaded: true
+        };
+        const action = searchMultipleActions.retrieveDataLength();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeTruthy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('retrieveDataLengthSuccess action should set dataLength, set dataLengthIsLoading to true and dataLengthIsLoaded to false', () => {
+        const initialState = {
+            ...fromSearchMultiple.initialState,
+            dataLengthIsLoading: true
+        };
+        const dataLength: SearchMultipleDatasetLength[] = [{ datasetName: 'myDataset', length: 1 }];
+        const action = searchMultipleActions.retrieveDataLengthSuccess({ dataLength });
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeTruthy();
+        expect(state.dataLength.length).toEqual(1);
+        expect(state.dataLength).toEqual(dataLength);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('retrieveDataLengthFail action should set dataLengthIsLoading to false', () => {
+        const initialState = {
+            ...fromSearchMultiple.initialState,
+            dataLengthIsLoading: true
+        };
+        const action = searchMultipleActions.retrieveDataLengthFail();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('retrieveData action should set dataIsLoading to true and dataIsLoaded to false', () => {
+        const initialState = {
+            ...fromSearchMultiple.initialState,
+            dataIsLoaded: true
+        };
+        const action = searchMultipleActions.retrieveData();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeTruthy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('retrieveDataSuccess action should set data, set dataIsLoading to false and dataIsLoaded to true', () => {
+        const initialState = {
+            ...fromSearchMultiple.initialState,
+            dataIsLoading: true
+        };
+        const data: SearchMultipleDatasetData[] = [{ datasetName: 'myDataset', data: ['myData'] }];
+        const action = searchMultipleActions.retrieveDataSuccess({ data });
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeTruthy();
+        expect(state.data.length).toEqual(1);
+        expect(state.data).toEqual(data);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('retrieveDataFail action should set dataIsLoading to false', () => {
+        const initialState = {
+            ...fromSearchMultiple.initialState,
+            dataIsLoading: true
+        };
+        const action = searchMultipleActions.retrieveDataFail();
+        const state = fromSearchMultiple.searchMultipleReducer(initialState, action);
+
+        expect(state.pristine).toBeTruthy();
+        expect(state.currentStep).toBeNull();
+        expect(state.positionStepChecked).toBeFalsy();
+        expect(state.datasetsStepChecked).toBeFalsy();
+        expect(state.resultStepChecked).toBeFalsy();
+        expect(state.selectedDatasets.length).toEqual(0);
+        expect(state.dataLengthIsLoading).toBeFalsy();
+        expect(state.dataLengthIsLoaded).toBeFalsy();
+        expect(state.dataLength.length).toEqual(0);
+        expect(state.dataIsLoading).toBeFalsy();
+        expect(state.dataIsLoaded).toBeFalsy();
+        expect(state.data.length).toEqual(0);
+        expect(state).not.toBe(initialState);
+    });
+
+    it('should get pristine', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectPristine(state)).toBeTruthy();
+    });
+
+    it('should get currentStep', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectCurrentStep(state)).toBeNull();
+    });
+
+    it('should get positionStepChecked', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectPositionStepChecked(state)).toBeFalsy();
+    });
+
+    it('should get datasetsStepChecked', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectDatasetsStepChecked(state)).toBeFalsy();
+    });
+
+    it('should get resultStepChecked', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectResultStepChecked(state)).toBeFalsy();
+    });
+
+    it('should get selectedDatasets', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectSelectedDatasets(state).length).toEqual(0);
+    });
+
+    it('should get dataLengthIsLoading', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectDataLengthIsLoading(state)).toBeFalsy();
+    });
+
+    it('should get dataLengthIsLoaded', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectDataLengthIsLoaded(state)).toBeFalsy();
+    });
+
+    it('should get dataLength', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectDataLength(state).length).toEqual(0);
+    });
+
+    it('should get dataIsLoading', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectDataIsLoading(state)).toBeFalsy();
+    });
+
+    it('should get dataIsLoaded', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectDataIsLoaded(state)).toBeFalsy();
+    });
+
+    it('should get data', () => {
+        const action = {} as Action;
+        const state =  fromSearchMultiple.searchMultipleReducer(undefined, action);
+
+        expect(fromSearchMultiple.selectData(state).length).toEqual(0);
+    });
+});
diff --git a/client/src/app/instance/store/reducers/search-multiple.reducer.ts b/client/src/app/instance/store/reducers/search-multiple.reducer.ts
index bd73fbba1df15c2853d55d21157e8a7f30fb1dbb..d5cf3af087b2055e2b0caa99b846102e2c363ba2 100644
--- a/client/src/app/instance/store/reducers/search-multiple.reducer.ts
+++ b/client/src/app/instance/store/reducers/search-multiple.reducer.ts
@@ -12,9 +12,15 @@ import { createReducer, on } from '@ngrx/store';
 import { SearchMultipleDatasetLength, SearchMultipleDatasetData } from '../models';
 import * as searchMultipleActions from '../actions/search-multiple.actions';
 
+/**
+ * Interface for search multiple state.
+ *
+ * @interface State
+ */
 export interface State {
     pristine: boolean;
     currentStep: string;
+    // TODO: remove unused positionStepChecked variable
     positionStepChecked: boolean;
     datasetsStepChecked: boolean;
     resultStepChecked: boolean;
diff --git a/client/src/app/instance/store/selectors/search-multiple.selector.spec.ts b/client/src/app/instance/store/selectors/search-multiple.selector.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b21c4ac104900ee2b3b3beef6ad151141cf8007
--- /dev/null
+++ b/client/src/app/instance/store/selectors/search-multiple.selector.spec.ts
@@ -0,0 +1,115 @@
+import * as searchMultipleSelector from './search-multiple.selector';
+import * as fromSearchMultiple from '../reducers/search-multiple.reducer';
+import * as fromConeSearch from '../reducers/cone-search.reducer';
+import { ConeSearch } from '../models';
+
+describe('Search multiple selector', () => {
+    it('should get selectPristine', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectPristine(state)).toBeTruthy();
+    });
+
+    it('should get currentStep', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectCurrentStep(state)).toBeNull();
+    });
+
+    it('should get positionStepChecked', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectPositionStepChecked(state)).toBeFalsy();
+    });
+
+    it('should get datasetsStepChecked', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectDatasetsStepChecked(state)).toBeFalsy();
+    });
+
+    it('should get resultStepChecked', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectResultStepChecked(state)).toBeFalsy();
+    });
+
+    it('should get selectedDatasets', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectSelectedDatasets(state).length).toEqual(0);
+    });
+
+    it('should get dataLengthIsLoading', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectDataLengthIsLoading(state)).toBeFalsy();
+    });
+
+    it('should get dataLengthIsLoaded', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectDataLengthIsLoaded(state)).toBeFalsy();
+    });
+
+    it('should get dataLength', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectDataLength(state).length).toEqual(0);
+    });
+
+    it('should get dataIsLoading', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectDataIsLoading(state)).toBeFalsy();
+    });
+
+    it('should get dataIsLoaded', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectDataIsLoaded(state)).toBeFalsy();
+    });
+
+    it('should get data', () => {
+        const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}};
+        expect(searchMultipleSelector.selectData(state).length).toEqual(0);
+    });
+
+    it('should get queryParams', () => {
+        const state = {
+            instance: {
+                searchMultiple: { ...fromSearchMultiple.initialState },
+                coneSearch: { ...fromConeSearch.initialState }
+            }
+        };
+        const expected = { };
+
+        expect(searchMultipleSelector.selectQueryParams(state)).toEqual(expected);
+    });
+
+    it('should get queryParams with cone search', () => {
+        const coneSearch: ConeSearch = { ra: 3, dec: 4, radius: 5 };
+        const state = {
+            instance: {
+                searchMultiple: { ...fromSearchMultiple.initialState },
+                coneSearch: {
+                    ...fromConeSearch.initialState,
+                    coneSearch
+                }
+            }
+        };
+        const expected = { cs: '3:4:5' };
+
+        expect(searchMultipleSelector.selectQueryParams(state)).toEqual(expected);
+    });
+
+    it('should get queryParams with datasets', () => {
+        const selectedDatasets: string[] = ['d1', 'd2'];
+        const state = {
+            instance: {
+                searchMultiple: {
+                    ...fromSearchMultiple.initialState,
+                    selectedDatasets
+                },
+                coneSearch: { ...fromConeSearch.initialState }
+            }
+        };
+        const expected = { d: 'd1;d2' };
+
+        expect(searchMultipleSelector.selectQueryParams(state)).toEqual(expected);
+    });
+
+    it('should get steps by route', () => {
+        const state = { router: { state: { queryParams: { d: 'd1;d2' }}}};
+        expect(searchMultipleSelector.selectSelectedDatasetsByRoute(state)).toEqual('d1;d2');
+    });
+});