diff --git a/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.spec.ts b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3d293e62fa7b846ca8684ae45e809d37bbab8b7 --- /dev/null +++ b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.spec.ts @@ -0,0 +1,79 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Component, Input } from '@angular/core'; + +import { TooltipModule } from 'ngx-bootstrap/tooltip'; + +import { DatasetListComponent } from './dataset-list.component'; +import { DATASET_FAMILY_LIST, DATASET_LIST } from '../../../../../test-data'; +import { Dataset, DatasetFamily, Survey } from '../../../../metamodel/models'; + +describe('[Instance][SearchMultiple][Component][Datasets] DatasetListComponent', () => { + @Component({ selector: 'app-datasets-by-family', template: '' }) + class DatasetsByFamilyStubComponent { + @Input() datasetFamily: DatasetFamily; + @Input() datasetList: Dataset[]; + @Input() surveyList: Survey[]; + @Input() selectedDatasets: string[]; + @Input() isAllSelected: boolean; + @Input() isAllUnselected: boolean; + } + + let component: DatasetListComponent; + let fixture: ComponentFixture<DatasetListComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + DatasetListComponent, + DatasetsByFamilyStubComponent + ], + imports: [TooltipModule.forRoot()] + }); + fixture = TestBed.createComponent(DatasetListComponent); + component = fixture.componentInstance; + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('#getDatasetFamilyList() should return sorted survey list', () => { + component.datasetList = DATASET_LIST; + component.datasetFamilyList = DATASET_FAMILY_LIST; + const sortedDatasetFamilyList: DatasetFamily[] = component.getDatasetFamilyList(); + expect(sortedDatasetFamilyList.length).toBe(1); + expect(sortedDatasetFamilyList[0].label).toBe('My first dataset family'); + }); + + it('#getDatasetsByFamily() should return dataset list for the given dataset family', () => { + component.datasetList = DATASET_LIST; + const datasetList: Dataset[] = component.getDatasetsByFamily(1); + expect(datasetList.length).toBe(2); + expect(datasetList[0].name).toBe('myDataset'); + expect(datasetList[1].name).toBe('anotherDataset'); + }); + + it('#getIsAllSelected() should return true if all datasets of the given dataset family are selected', () => { + component.datasetList = DATASET_LIST; + component.selectedDatasets = ['myDataset', 'anotherDataset']; + expect(component.getIsAllSelected(1)).toBeTruthy(); + }); + + it('#getIsAllSelected() should return false if not all datasets of the given dataset family are selected', () => { + component.datasetList = DATASET_LIST; + component.selectedDatasets = ['myDataset']; + expect(component.getIsAllSelected(1)).toBeFalsy(); + }); + + it('#getIsAllUnselected() should return true if all datasets of the given dataset family are not selected', () => { + component.datasetList = DATASET_LIST; + component.selectedDatasets = []; + expect(component.getIsAllUnselected(1)).toBeTruthy(); + }); + + it('#getIsAllUnselected() should return false if not all datasets of the given dataset family are not selected', () => { + component.datasetList = DATASET_LIST; + component.selectedDatasets = ['myDataset']; + expect(component.getIsAllUnselected(1)).toBeFalsy(); + }); +}); diff --git a/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts index f01569abfd679097f564b04a1563c52806e6957e..164643d464f61a837f192f0ba9efb969b0aca732 100644 --- a/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts +++ b/client/src/app/instance/search-multiple/components/datasets/dataset-list.component.ts @@ -11,15 +11,15 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from import { Dataset, DatasetFamily, Survey } from 'src/app/metamodel/models'; +/** + * @class + * @classdesc Dataset list component. + */ @Component({ selector: 'app-dataset-list', templateUrl: 'dataset-list.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc Search multiple dataset list component. - */ export class DatasetListComponent { @Input() datasetFamilyList: DatasetFamily[]; @Input() datasetList: Dataset[]; @@ -28,9 +28,9 @@ export class DatasetListComponent { @Output() updateSelectedDatasets: EventEmitter<string[]> = new EventEmitter(); /** - * Returns dataset family list sorted by display, that contains datasets with cone search enabled. + * Returns dataset family list that contains datasets with cone search enabled. * - * @return Family[] + * @return DatasetFamily[] */ getDatasetFamilyList(): DatasetFamily[] { const familyId: number[] = []; diff --git a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.spec.ts b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9f29194b0cbc7f35acc8ce20ee0fdea9b1791745 --- /dev/null +++ b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.spec.ts @@ -0,0 +1,69 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TooltipModule } from 'ngx-bootstrap/tooltip'; + +import { DatasetsByFamilyComponent } from './datasets-by-family.component'; +import { DATASET_LIST, SURVEY_LIST } from '../../../../../test-data'; + +describe('[Instance][SearchMultiple][Component][Datasets] DatasetsByFamilyComponent', () => { + let component: DatasetsByFamilyComponent; + let fixture: ComponentFixture<DatasetsByFamilyComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [DatasetsByFamilyComponent], + imports: [TooltipModule.forRoot()] + }); + fixture = TestBed.createComponent(DatasetsByFamilyComponent); + component = fixture.componentInstance; + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('#isSelected() should return true if the given dataset is selected', () => { + component.selectedDatasets = ['toto']; + expect(component.isSelected('toto')).toBeTruthy(); + }); + + it('#isSelected() should return false if the given dataset is not selected', () => { + component.selectedDatasets = []; + expect(component.isSelected('toto')).toBeFalsy(); + }); + + it('#toggleSelection() should remove the given dataset from selectedDatasets and raise updateSelectedDatasets event', () => { + component.selectedDatasets = ['toto']; + const expectedSelectedDatasets = []; + component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets)); + component.toggleSelection('toto'); + }); + + it('#toggleSelection() should add the given dataset to selectedDatasets and raise updateSelectedDatasets event', () => { + component.selectedDatasets = []; + const expectedSelectedDatasets = ['toto']; + component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets)); + component.toggleSelection('toto'); + }); + + it('#selectAll() should add all datasets to selectedDatasets and raise updateSelectedDatasets event', () => { + component.datasetList = DATASET_LIST.filter(d => d.id_dataset_family === 1); + component.selectedDatasets = []; + const expectedSelectedDatasets = ['myDataset', 'anotherDataset']; + component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets)); + component.selectAll(); + }); + + it('#unselectAll() should remove all datasets to selectedDatasets and raise updateSelectedDatasets event', () => { + component.datasetList = DATASET_LIST.filter(d => d.id_dataset_family === 1); + component.selectedDatasets = ['myDataset', 'anotherDataset']; + const expectedSelectedDatasets = []; + component.updateSelectedDatasets.subscribe((event: string[]) => expect(event).toEqual(expectedSelectedDatasets)); + component.unselectAll(); + }); + + it('#getSurveyDescription() should return the description of the given survey', () => { + component.surveyList = SURVEY_LIST; + expect(component.getSurveyDescription('survey-one')).toEqual('This is the description of first survey'); + }); +}); diff --git a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts index 8a1a260c5e72f0f86b46ee6910c9e76f1bfe5976..85cb44b08f04300feebeaf717f9593d1c167f857 100644 --- a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts +++ b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.ts @@ -11,6 +11,10 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEn import { Dataset, DatasetFamily, Survey } from 'src/app/metamodel/models'; +/** + * @class + * @classdesc Datasets by family component. + */ @Component({ selector: 'app-datasets-by-family', templateUrl: 'datasets-by-family.component.html', @@ -18,10 +22,6 @@ import { Dataset, DatasetFamily, Survey } from 'src/app/metamodel/models'; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -/** - * @class - * @classdesc Search multiple datasets by family component. - */ export class DatasetsByFamilyComponent { @Input() datasetFamily: DatasetFamily; @Input() datasetList: Dataset[]; diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..a86e34f952555f07fd597b550583aadb210a5313 --- /dev/null +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts @@ -0,0 +1,54 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { ProgressBarMultipleComponent } from './progress-bar-multiple.component'; +import { INSTANCE } from '../../../../test-data'; + +describe('[Instance][SearchMultiple][Component] ProgressBarMultipleComponent', () => { + let component: ProgressBarMultipleComponent; + let fixture: ComponentFixture<ProgressBarMultipleComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ProgressBarMultipleComponent], + imports: [RouterTestingModule] + }); + fixture = TestBed.createComponent(ProgressBarMultipleComponent); + component = fixture.componentInstance; + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('#getStepClass() should return correct step class', () => { + let style = component.getStepClass(); + expect(style).toBe('positionStep'); + component.currentStep = 'position'; + style = component.getStepClass(); + expect(style).toBe('positionStep'); + component.currentStep = 'datasets'; + style = component.getStepClass(); + expect(style).toBe('datasetsStep'); + component.currentStep = 'result'; + style = component.getStepClass(); + expect(style).toBe('resultStep'); + }); + + it('#getNavItemAStyle() should return correct style for navigation link', () => { + component.currentStep = 'step'; + component.instance = INSTANCE; + expect(component.getNavItemAStyle('', false)).toBeNull(); + expect(component.getNavItemAStyle('step', true)).toEqual({ color: 'green' }); + }); + + it('#getNavItemIconCircleStyle() should return correct style for icon circle', () => { + component.currentStep = 'step'; + component.instance = INSTANCE; + expect(component.getNavItemIconCircleStyle('', false)).toEqual({ }); + const expectedWithStep = { 'border-color': 'green', 'background-color': 'green' }; + expect(component.getNavItemIconCircleStyle('step', false)).toEqual(expectedWithStep); + const expectedWithChecked = { 'border-color': 'green', 'color': 'green' }; + expect(component.getNavItemIconCircleStyle('', true)).toEqual(expectedWithChecked); + }); +}); diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts index ece4925478828db29a2a9df8e097e3287ca2900e..0fbeafa0d654dac7fc133ccde1ee597140fbc43a 100644 --- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts @@ -12,16 +12,16 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; import { Instance } from 'src/app/metamodel/models'; import { ConeSearch, SearchMultipleQueryParams } from 'src/app/instance/store/models'; +/** + * @class + * @classdesc Progress bar multiple component. + */ @Component({ selector: 'app-progress-bar-multiple', templateUrl: 'progress-bar-multiple.component.html', styleUrls: ['progress-bar-multiple.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc Search multiple progress bar component. - */ export class ProgressBarMultipleComponent { @Input() instance: Instance; @Input() currentStep: string; @@ -50,17 +50,30 @@ export class ProgressBarMultipleComponent { } } - getNavItemAStyle(currentStep: string, checked: boolean) { + /** + * Returns navigation link style. + * + * @param {string} currentStep - The current step. + * @param {boolean} checked - The checked status of current step. + * + * @return { color: string } | null + */ + getNavItemAStyle(currentStep: string, checked: boolean): { color: string } | null { if (this.currentStep === currentStep || checked) { - return { - 'color': this.instance.config.design.design_color - } - } else { - return null; + return { 'color': this.instance.config.design.design_color } } + return null; } - getNavItemIconCircleStyle(currentStep: string, checked: boolean) { + /** + * Returns navigation icon circle style. + * + * @param {string} currentStep - The current step. + * @param {boolean} checked - The checked status of current step. + * + * @return any + */ + getNavItemIconCircleStyle(currentStep: string, checked: boolean): any { let style = {}; if (this.currentStep === currentStep) { style['border-color'] = this.instance.config.design.design_color; diff --git a/client/src/app/instance/search-multiple/components/result/overview.component.spec.ts b/client/src/app/instance/search-multiple/components/result/overview.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..68532aaec60f06a8f61abcca51d232d1e4ab345b --- /dev/null +++ b/client/src/app/instance/search-multiple/components/result/overview.component.spec.ts @@ -0,0 +1,60 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { OverviewComponent } from './overview.component'; +import { Dataset, DatasetFamily } from '../../../../metamodel/models'; +import { DATASET_FAMILY_LIST, DATASET_LIST } from '../../../../../test-data'; + +describe('[Instance][SearchMultiple][Component][Result] OverviewComponent', () => { + let component: OverviewComponent; + let fixture: ComponentFixture<OverviewComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [OverviewComponent], + imports: [RouterTestingModule] + }); + fixture = TestBed.createComponent(OverviewComponent); + component = fixture.componentInstance; + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('#getTotalObject() should return the sum of results for each dataset', () => { + component.dataLength = [{ datasetName: 'firstDataset', length: 1 }, { datasetName: 'secondDataset', length: 1 }]; + expect(component.getTotalObject()).toEqual(2); + }); + + it('#getTotalDatasets() should return count datasets with results', () => { + component.dataLength = [{ datasetName: 'firstDataset', length: 1 }, { datasetName: 'secondDataset', length: 1 }]; + expect(component.getTotalDatasets()).toEqual(2); + }); + + it('#getSortedDatasetFamilyList() should return sorted dataset family list with selected datasets in it', () => { + component.selectedDatasets = ['myDataset', 'anotherDataset']; + component.datasetList = DATASET_LIST; + component.datasetFamilyList = DATASET_FAMILY_LIST; + const sortedDatasetFamilyList: DatasetFamily[] = component.getSortedDatasetFamilyList(); + expect(sortedDatasetFamilyList.length).toEqual(1); + expect(sortedDatasetFamilyList[0].label).toBe('My first dataset family'); + }); + + it('#getSelectedDatasetsByFamily() should return selected dataset that belongs to the given dataset family', () => { + component.selectedDatasets = ['myDataset']; + component.datasetList = DATASET_LIST; + const selectedDatasets: Dataset[] = component.getSelectedDatasetsByFamily(1); + expect(selectedDatasets.length).toEqual(1); + }); + + it('#getCountByDataset() should return count for the given dataset', () => { + component.dataLength = [{ datasetName: 'firstDataset', length: 1 }, { datasetName: 'secondDataset', length: 2 }]; + expect(component.getCountByDataset('firstDataset')).toEqual(1); + }); + + it('#getCsQueryParams() should return cone search query parameters', () => { + component.coneSearch = { ra: 1, dec: 2, radius: 3 }; + expect(component.getCsQueryParams()).toEqual({ cs: '1:2:3' }); + }); +}); diff --git a/client/src/app/instance/search-multiple/components/result/overview.component.ts b/client/src/app/instance/search-multiple/components/result/overview.component.ts index e85af4d2feed7f641e352c6f5a998a7a596899c8..25fc216d76b3bebd419f902d9044c8366502d70d 100644 --- a/client/src/app/instance/search-multiple/components/result/overview.component.ts +++ b/client/src/app/instance/search-multiple/components/result/overview.component.ts @@ -12,6 +12,10 @@ import { Component, Input } from '@angular/core'; import { DatasetFamily, Dataset } from 'src/app/metamodel/models'; import { ConeSearch, SearchMultipleDatasetLength, SearchMultipleQueryParams } from 'src/app/instance/store/models'; +/** + * @class + * @classdesc Overview component. + */ @Component({ selector: 'app-overview', templateUrl: 'overview.component.html' @@ -37,7 +41,7 @@ export class OverviewComponent { } /** - * Returns total number of datasets with results. + * Returns count of datasets with results. * * @return number */ @@ -46,9 +50,9 @@ export class OverviewComponent { } /** - * Returns dataset families sorted by display, that contains selected datasets. + * Returns dataset families that contains selected datasets. * - * @return Family[] + * @return DatasetFamily[] */ getSortedDatasetFamilyList(): DatasetFamily[] { let datasetFamiliesWithSelectedDataset: DatasetFamily[] = []; @@ -76,7 +80,7 @@ export class OverviewComponent { } /** - * Returns the result number for the given dataset name. + * Returns the result count for the given dataset name. * * @param {string} dname - The dataset name. * @@ -86,9 +90,12 @@ export class OverviewComponent { return this.dataLength.find(datasetLength => datasetLength.datasetName === dname).length; } - getCsQueryParams() { - return { - cs: `${this.coneSearch.ra}:${this.coneSearch.dec}:${this.coneSearch.radius}` - } + /** + * Returns the cone search query parameters. + * + * @return { cs: string } + */ + getCsQueryParams(): { cs: string } { + return { cs: `${this.coneSearch.ra}:${this.coneSearch.dec}:${this.coneSearch.radius}` } } } diff --git a/client/src/app/instance/search-multiple/components/summary-multiple.component.ts b/client/src/app/instance/search-multiple/components/summary-multiple.component.ts index f3c81c65583c54b279ac34be54f4ed7a170d82d7..fb6900bee9918b8a0ff344e25a881f3b67224841 100644 --- a/client/src/app/instance/search-multiple/components/summary-multiple.component.ts +++ b/client/src/app/instance/search-multiple/components/summary-multiple.component.ts @@ -14,7 +14,7 @@ import { Dataset, DatasetFamily } from 'src/app/metamodel/models'; /** * @class - * @classdesc Summary multiple summary component. + * @classdesc Summary multiple component. */ @Component({ selector: 'app-summary-multiple', diff --git a/client/src/test-data.ts b/client/src/test-data.ts index f5d9108c5bfeefe35391a1cc998d709c81378851..683df725204adfb4dd6fa6fb5975530dbfef8c0d 100644 --- a/client/src/test-data.ts +++ b/client/src/test-data.ts @@ -1,4 +1,59 @@ -import { Attribute, Dataset, DatasetFamily, OutputCategory } from './app/metamodel/models'; +import { Attribute, Dataset, DatasetFamily, Instance, OutputCategory, Survey } from './app/metamodel/models'; + +export const SURVEY_LIST: Survey[] = [ + { + name: 'survey-one', + label: 'First survey', + description: 'This is the description of first survey', + link: 'http://survey-one.com', + manager: 'Marylin Monroe', + id_database: 1, + nb_datasets: 1 + }, + { + name: 'survey-two', + label: 'Second survey', + description: 'This is the description of second survey', + link: 'http://survey-two.com', + manager: 'FA', + id_database: 2, + nb_datasets: 2 + } +]; + +export const INSTANCE: Instance = { + 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: false, + search_by_criteria_label: 'Search', + search_multiple_allowed: false, + search_multiple_label: 'Search multiple', + search_multiple_all_datasets_selected: false + }, + documentation: { + documentation_allowed: false, + documentation_label: 'Documentation' + } + }, + nb_dataset_families: 1, + nb_datasets: 2 +}; export const DATASET_FAMILY_LIST: DatasetFamily[] = [ { id: 2, label: 'My second dataset family', display: 2, opened: false },