From ac7db4dc06c2567a96a680186e6a4cc5d0d3aad7 Mon Sep 17 00:00:00 2001 From: Tifenn Guillas <tifenn.guillas@gmail.com> Date: Fri, 15 Oct 2021 14:33:38 +0200 Subject: [PATCH] WIP: tests on checkbox component --- .../between-date.component.spec.ts | 98 +++++++++++++++ .../search-type/between-date.component.ts | 26 ++-- .../search-type/between.component.spec.ts | 115 +++++++++++++++++ .../criteria/search-type/between.component.ts | 12 +- .../search-type/checkbox.component.spec.ts | 108 ++++++++++++++++ .../search-type/checkbox.component.ts | 25 ++-- .../search-type/datalist.component.spec.ts | 119 ++++++++++++++++++ .../search-type/datalist.component.ts | 12 +- .../search-type/date.component.spec.ts | 115 +++++++++++++++++ .../criteria/search-type/date.component.ts | 14 ++- .../search-type/datetime.component.spec.ts | 15 +-- .../select-multiple.component.spec.ts | 2 +- 12 files changed, 617 insertions(+), 44 deletions(-) create mode 100644 client/src/app/instance/search/components/criteria/search-type/between-date.component.spec.ts create mode 100644 client/src/app/instance/search/components/criteria/search-type/between.component.spec.ts create mode 100644 client/src/app/instance/search/components/criteria/search-type/checkbox.component.spec.ts create mode 100644 client/src/app/instance/search/components/criteria/search-type/datalist.component.spec.ts create mode 100644 client/src/app/instance/search/components/criteria/search-type/date.component.spec.ts diff --git a/client/src/app/instance/search/components/criteria/search-type/between-date.component.spec.ts b/client/src/app/instance/search/components/criteria/search-type/between-date.component.spec.ts new file mode 100644 index 00000000..a0dceaf5 --- /dev/null +++ b/client/src/app/instance/search/components/criteria/search-type/between-date.component.spec.ts @@ -0,0 +1,98 @@ +import { Component, Input, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +import { BetweenDateComponent } from './between-date.component'; +import { BetweenCriterion } from '../../../../store/models/criterion'; +import { BsDatepickerModule } from 'ngx-bootstrap/datepicker'; + +describe('[Instance][Search][Component][Criteria][SearchType] BetweenDateComponent', () => { + @Component({ + selector: `app-host`, + template: ` + <app-between-date + [id]="id" + [operator]="operator" + [label]="label" + [criterion]="criterion"> + </app-between-date>` + }) + class TestHostComponent { + @ViewChild(BetweenDateComponent, { static: false }) + public testedComponent: BetweenDateComponent; + public id: number = undefined; + public operator: string = undefined; + public label: string = undefined; + public criterion: BetweenCriterion = undefined; + } + + @Component({ selector: 'app-operator', template: '' }) + class OperatorStubComponent { + @Input() operator: string; + @Input() searchType: string; + @Input() advancedForm: boolean; + @Input() disabled: boolean; + } + + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture<TestHostComponent>; + let testedComponent: BetweenDateComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + BetweenDateComponent, + TestHostComponent + ], + imports: [ + FormsModule, + ReactiveFormsModule, + BsDatepickerModule.forRoot() + ] + }); + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + testedComponent = testHostComponent.testedComponent; + }); + + it('should create the component', () => { + expect(testedComponent).toBeTruthy(); + }); + + it('should call ngOnChanges and apply changes', () => { + const spy = jest.spyOn(testedComponent, 'ngOnChanges'); + testHostComponent.criterion = { id: 1, type: 'between', operator: 'eq', min: '2019-02-17', max: '2021-04-12' } as BetweenCriterion; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.dateRange.value[0].getDate()).toEqual(17); + expect(testedComponent.form.controls.dateRange.value[0].getMonth()).toEqual(1); + expect(testedComponent.form.controls.dateRange.value[0].getFullYear()).toEqual(2019); + expect(testedComponent.form.controls.dateRange.value[1].getDate()).toEqual(12); + expect(testedComponent.form.controls.dateRange.value[1].getMonth()).toEqual(3); + expect(testedComponent.form.controls.dateRange.value[1].getFullYear()).toEqual(2021); + expect(testedComponent.form.disabled).toBeTruthy(); + testHostComponent.criterion = undefined; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.dateRange.value).toBeNull(); + expect(testedComponent.form.enabled).toBeTruthy(); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it('raises the add criterion event when clicked', () => { + testedComponent.id = 1; + const operator = 'eq'; + testedComponent.operator = operator; + const dateMin: Date = new Date('2019-02-17'); + const dateMax: Date = new Date('2021-04-12'); + testedComponent.form.controls.dateRange.setValue([dateMin, dateMax]); + const expectedCriterion = { id: testedComponent.id, type: 'between', operator, min: '2019-02-17', max: '2021-04-12' } as BetweenCriterion; + testedComponent.addCriterion.subscribe((event: BetweenCriterion) => expect(event).toEqual(expectedCriterion)); + testedComponent.emitAdd(); + }); + + it('#getDateString() should return a date as string', () => { + const dateString = '2019-02-17'; + const date = new Date(dateString); + expect(testedComponent.getDateString(date)).toEqual(dateString); + }); +}); diff --git a/client/src/app/instance/search/components/criteria/search-type/between-date.component.ts b/client/src/app/instance/search/components/criteria/search-type/between-date.component.ts index 9e0ab4d1..68f1dc17 100644 --- a/client/src/app/instance/search/components/criteria/search-type/between-date.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/between-date.component.ts @@ -7,21 +7,31 @@ * file that was distributed with this source code. */ -import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, SimpleChanges } from '@angular/core'; +import { + Component, + Input, + Output, + EventEmitter, + ChangeDetectionStrategy, + SimpleChanges, + OnChanges +} from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms'; import { Criterion, BetweenCriterion } from 'src/app/instance/store/models'; +/** + * @class + * @classdesc Between date search type component. + * + * @implements OnChanges + */ @Component({ selector: 'app-between-date', templateUrl: 'between-date.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc Between date search type component. - */ -export class BetweenDateComponent { +export class BetweenDateComponent implements OnChanges { @Input() id: number; @Input() operator: string; @Input() label: string; @@ -33,7 +43,7 @@ export class BetweenDateComponent { dateRange: new FormControl('', [Validators.required]) }); - ngOnChanges(changes: SimpleChanges) { + ngOnChanges(changes: SimpleChanges): void { if (changes.criterion && changes.criterion.currentValue) { const c = changes.criterion.currentValue as BetweenCriterion; this.form.controls.dateRange.setValue([new Date(c.min), new Date(c.max)]); @@ -54,7 +64,7 @@ export class BetweenDateComponent { emitAdd(): void { const dateMin = this.getDateString(this.form.controls.dateRange.value[0]); const dateMax = this.getDateString(this.form.controls.dateRange.value[1]); - const fd: BetweenCriterion = {id: this.id, type: 'between', min: dateMin, max: dateMax}; + const fd: BetweenCriterion = { id: this.id, type: 'between', min: dateMin, max: dateMax }; this.addCriterion.emit(fd); } diff --git a/client/src/app/instance/search/components/criteria/search-type/between.component.spec.ts b/client/src/app/instance/search/components/criteria/search-type/between.component.spec.ts new file mode 100644 index 00000000..638ad78a --- /dev/null +++ b/client/src/app/instance/search/components/criteria/search-type/between.component.spec.ts @@ -0,0 +1,115 @@ +import { Component, Input, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +import { TooltipModule } from 'ngx-bootstrap/tooltip'; + +import { BetweenComponent } from './between.component'; +import { BetweenCriterion } from '../../../../store/models/criterion'; + +describe('[Instance][Search][Component][Criteria][SearchType] BetweenComponent', () => { + @Component({ + selector: `app-host`, + template: ` + <app-between + [id]="id" + [label]="label" + [placeholderMin]="placeholderMin" + [placeholderMax]="placeholderMax" + [criterion]="criterion"> + </app-between>` + }) + class TestHostComponent { + @ViewChild(BetweenComponent, { static: false }) + public testedComponent: BetweenComponent; + public id: number = undefined; + public label: string = undefined; + public placeholderMin: string = undefined; + public placeholderMax: string = undefined; + public criterion: BetweenCriterion = undefined; + } + + @Component({ selector: 'app-operator', template: '' }) + class OperatorStubComponent { + @Input() operator: string; + @Input() searchType: string; + @Input() advancedForm: boolean; + @Input() disabled: boolean; + } + + @Component({ selector: 'app-help-like', template: '' }) + class HelpLikeStubComponent { } + + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture<TestHostComponent>; + let testedComponent: BetweenComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + BetweenComponent, + TestHostComponent, + // OperatorStubComponent, + // HelpLikeStubComponent + ], + imports: [ + FormsModule, + ReactiveFormsModule, + TooltipModule.forRoot() + ] + }); + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + testedComponent = testHostComponent.testedComponent; + }); + + it('should create the component', () => { + expect(testedComponent).toBeTruthy(); + }); + + it('should call ngOnChanges and apply changes', () => { + const spy = jest.spyOn(testedComponent, 'ngOnChanges'); + testHostComponent.criterion = { id: 1, type: 'between', operator: 'eq', min: 'one', max: 'two' } as BetweenCriterion; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.min.value).toEqual('one'); + expect(testedComponent.form.controls.max.value).toEqual('two'); + expect(testedComponent.form.disabled).toBeTruthy(); + testHostComponent.criterion = undefined; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.min.value).toBeNull(); + expect(testedComponent.form.controls.max.value).toBeNull(); + expect(testedComponent.form.enabled).toBeTruthy(); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it('raises the add criterion event when clicked', () => { + testedComponent.id = 1; + const operator = 'eq'; + testedComponent.form.controls.min.setValue('one'); + testedComponent.form.controls.max.setValue('two'); + const expectedCriterion = { id: testedComponent.id, type: 'between', operator, min: 'one', max: 'two' } as BetweenCriterion; + testedComponent.addCriterion.subscribe((event: BetweenCriterion) => expect(event).toEqual(expectedCriterion)); + testedComponent.emitAdd(); + }); + + it('#getPlaceholderMin() should fill the placeholder for the minimum value if defined', () => { + const placeholder = 'placeholder'; + testedComponent.placeholderMin = placeholder; + expect(testedComponent.getPlaceholderMin()).toEqual(placeholder); + }); + + it('#getPlaceholderMin() should not fill the placeholder for the minimum value if not defined', () => { + expect(testedComponent.getPlaceholderMin()).toEqual(''); + }); + + it('#getPlaceholderMax() should fill the placeholder for the maximum value if defined', () => { + const placeholder = 'placeholder'; + testedComponent.placeholderMax = placeholder; + expect(testedComponent.getPlaceholderMax()).toEqual(placeholder); + }); + + it('#getPlaceholderMax() should not fill the placeholder for the maximum value if not defined', () => { + expect(testedComponent.getPlaceholderMax()).toEqual(''); + }); +}); diff --git a/client/src/app/instance/search/components/criteria/search-type/between.component.ts b/client/src/app/instance/search/components/criteria/search-type/between.component.ts index bc1d7b62..842d5810 100644 --- a/client/src/app/instance/search/components/criteria/search-type/between.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/between.component.ts @@ -12,16 +12,18 @@ import { FormGroup, FormControl, Validators } from '@angular/forms'; import { Criterion, BetweenCriterion } from 'src/app/instance/store/models'; +/** + * @class + * @classdesc Between search type component. + * + * @implements OnChanges + */ @Component({ selector: 'app-between', templateUrl: 'between.component.html', styleUrls: ['operator.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc Between search type component. - */ export class BetweenComponent implements OnChanges { @Input() id: number; @Input() label: string; @@ -36,7 +38,7 @@ export class BetweenComponent implements OnChanges { max: new FormControl('', [Validators.required]) }); - ngOnChanges(changes: SimpleChanges) { + ngOnChanges(changes: SimpleChanges): void { if (changes.criterion && changes.criterion.currentValue) { this.form.patchValue(this.criterion); this.form.disable(); diff --git a/client/src/app/instance/search/components/criteria/search-type/checkbox.component.spec.ts b/client/src/app/instance/search/components/criteria/search-type/checkbox.component.spec.ts new file mode 100644 index 00000000..b080f0ef --- /dev/null +++ b/client/src/app/instance/search/components/criteria/search-type/checkbox.component.spec.ts @@ -0,0 +1,108 @@ +import { Component, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms'; + +import { NgSelectModule } from '@ng-select/ng-select'; + +import { CheckboxComponent } from './checkbox.component'; +import { SelectMultipleCriterion } from '../../../../store/models/criterion'; +import { Option } from '../../../../../metamodel/models'; +import { AbstractSearchComponent } from '../../../containers/abstract-search.component'; +import * as searchActions from '../../../../store/actions/search.actions'; + +describe('[Instance][Search][Component][Criteria][SearchType] CheckboxComponent', () => { + @Component({ + selector: `app-host`, + template: ` + <app-checkbox + [id]="id" + [label]="label" + [options]="options" + [criterion]="criterion"> + </app-checkbox>` + }) + class TestHostComponent { + @ViewChild(CheckboxComponent, { static: false }) + public testedComponent: CheckboxComponent; + public id: number = undefined; + public label: string = undefined; + public options: Option[] = []; + public criterion: SelectMultipleCriterion = undefined; + } + + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture<TestHostComponent>; + let testedComponent: CheckboxComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + CheckboxComponent, + TestHostComponent + ], + imports: [ + // NgSelectModule, + FormsModule, + ReactiveFormsModule + ] + }); + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + testedComponent = testHostComponent.testedComponent; + }); + + it('should create the component', () => { + expect(testedComponent).toBeTruthy(); + }); + + it.only('should execute ngOnInit lifecycle', () => { + testedComponent.options = [ + { label: 'One', value: 'one', display: 1 }, + { label: 'Two', value: 'two', display: 2 }, + { label: 'Three', value: 'three', display: 3 } + ]; + testedComponent.ngOnInit(); + console.log(testedComponent.options.length); + const formArray = testedComponent.form.controls.checkboxes as FormArray; + // console.log(formArray.controls[0]); + expect(testedComponent).toBeTruthy(); + }); + + // it('should call ngOnChanges and apply changes', () => { + // const spy = jest.spyOn(testedComponent, 'ngOnChanges'); + // const options: Option[] = [ + // { label: 'One', value: 'one', display: 1 }, + // { label: 'Two', value: 'two', display: 2 }, + // { label: 'Three', value: 'three', display: 3 } + // ]; + // testHostComponent.criterion = { id: 1, type: 'multiple', options } as SelectMultipleCriterion; + // testHostFixture.detectChanges(); + // expect(testedComponent.form.controls.select.value).toEqual(['one', 'two', 'three']); + // expect(testedComponent.form.disabled).toBeTruthy(); + // testHostComponent.criterion = undefined; + // testHostFixture.detectChanges(); + // expect(testedComponent.form.controls.select.value).toBeNull(); + // expect(testedComponent.form.enabled).toBeTruthy(); + // expect(spy).toHaveBeenCalledTimes(2); + // }); + + // it('#getCheckboxes() should return an array of checkbox', () => { + // const formArray: FormArray = null; + // expect(testedComponent.getCheckboxes()).toBeTruthy(); + // }); + + // it('raises the add criterion event when clicked', () => { + // testedComponent.id = 1; + // testedComponent.options = [ + // { label: 'One', value: 'one', display: 1 }, + // { label: 'Two', value: 'two', display: 2 }, + // { label: 'Three', value: 'three', display: 3 } + // ]; + // testedComponent.form.controls.select.setValue(['three']); + // const expectedValue = [{ label: 'Three', value: 'three', display: 3 }]; + // const expectedCriterion = { id: testedComponent.id, type: 'multiple', options: expectedValue } as SelectMultipleCriterion; + // testedComponent.addCriterion.subscribe((event: SelectMultipleCriterion) => expect(event).toEqual(expectedCriterion)); + // testedComponent.emitAdd(); + // }); +}); diff --git a/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts b/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts index 67d147fa..5f01e948 100644 --- a/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts @@ -13,16 +13,19 @@ import { FormGroup, FormArray, FormControl } from '@angular/forms'; import { Criterion, SelectMultipleCriterion } from 'src/app/instance/store/models'; import { Option } from 'src/app/metamodel/models'; +/** + * @class + * @classdesc Checkbox search type component. + * + * @implements OnInit + * @implements OnChanges + */ @Component({ selector: 'app-checkbox', templateUrl: 'checkbox.component.html', styleUrls: ['checkbox.component.scss', 'operator.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc Checkbox search type component. - */ export class CheckboxComponent implements OnInit, OnChanges { @Input() id: number; @Input() label: string; @@ -33,16 +36,17 @@ export class CheckboxComponent implements OnInit, OnChanges { public form = new FormGroup({ }); - ngOnInit() { + ngOnInit(): void { // Initialization of checkboxes (1 per option) const formControls: FormControl[] = []; for (let i = 0; i < this.options.length; i++) { formControls.push(new FormControl()); } this.form.addControl('checkboxes', new FormArray(formControls)); + console.log(this.form.controls.checkboxes.value.length); } - ngOnChanges(changes: SimpleChanges) { + ngOnChanges(changes: SimpleChanges): void { if (changes.criterion && changes.criterion.currentValue) { const multipleCriterion = this.criterion as SelectMultipleCriterion; @@ -60,7 +64,12 @@ export class CheckboxComponent implements OnInit, OnChanges { } } - getCheckboxes() { + /** + * Returns checkboxes form. + * + * @return FormArray + */ + getCheckboxes(): FormArray { return this.form.controls.checkboxes as FormArray; } @@ -72,7 +81,7 @@ export class CheckboxComponent implements OnInit, OnChanges { emitAdd(): void { const selected = this.getCheckboxes().value; const values = [...this.options.filter((option, index) => selected[index])]; - this.addCriterion.emit({id: this.id, type: 'multiple', options: values}); + this.addCriterion.emit({ id: this.id, type: 'multiple', options: values }); } /** diff --git a/client/src/app/instance/search/components/criteria/search-type/datalist.component.spec.ts b/client/src/app/instance/search/components/criteria/search-type/datalist.component.spec.ts new file mode 100644 index 00000000..4167d607 --- /dev/null +++ b/client/src/app/instance/search/components/criteria/search-type/datalist.component.spec.ts @@ -0,0 +1,119 @@ +import { Component, Input, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +import { TooltipModule } from 'ngx-bootstrap/tooltip'; + +import { DatalistComponent } from './datalist.component'; +import { FieldCriterion } from '../../../../store/models/criterion'; +import { Option } from '../../../../../metamodel/models'; + +describe('[Instance][Search][Component][Criteria][SearchType] DatalistComponent', () => { + @Component({ + selector: `app-host`, + template: ` + <app-datalist + [id]="id" + [operator]="operator" + [label]="label" + [placeholder]="placeholder" + [options]="options" + [criterion]="criterion" + [advancedForm]="advancedForm"> + </app-datalist>` + }) + class TestHostComponent { + @ViewChild(DatalistComponent, { static: false }) + public testedComponent: DatalistComponent; + public id: number = undefined; + public operator: string = undefined; + public label: string = undefined; + public placeholder: string = undefined; + public options: Option[] = undefined; + public criterion: FieldCriterion = undefined; + public advancedForm: boolean = false; + } + + @Component({ selector: 'app-operator', template: '' }) + class OperatorStubComponent { + @Input() operator: string; + @Input() searchType: string; + @Input() advancedForm: boolean; + @Input() disabled: boolean; + } + + @Component({ selector: 'app-help-like', template: '' }) + class HelpLikeStubComponent { } + + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture<TestHostComponent>; + let testedComponent: DatalistComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + DatalistComponent, + TestHostComponent, + OperatorStubComponent, + HelpLikeStubComponent + ], + imports: [ + FormsModule, + ReactiveFormsModule, + TooltipModule.forRoot() + ] + }); + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + testedComponent = testHostComponent.testedComponent; + }); + + it('should create the component', () => { + expect(testedComponent).toBeTruthy(); + }); + + it('should call ngOnChanges and apply changes', () => { + const spy = jest.spyOn(testedComponent, 'ngOnChanges'); + testHostComponent.criterion = { id: 1, type: 'field', operator: 'eq', value: 'myValue' } as FieldCriterion; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.value.value).toEqual('myValue'); + expect(testedComponent.form.disabled).toBeTruthy(); + testHostComponent.criterion = undefined; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.value.value).toBeNull(); + expect(testedComponent.form.enabled).toBeTruthy(); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it('#changeOperator() should change the operator', () => { + expect(testedComponent.operator).toBeUndefined(); + testedComponent.changeOperator('toto'); + expect(testedComponent.operator).toBe('toto'); + }); + + it('raises the add criterion event when clicked', () => { + testedComponent.id = 1; + const operator = 'eq'; + testedComponent.operator = operator; + testedComponent.form.controls.value.setValue('myValue'); + const expectedCriterion = { id: testedComponent.id, type: 'field', operator, value: 'myValue' } as FieldCriterion; + testedComponent.addCriterion.subscribe((event: FieldCriterion) => expect(event).toEqual(expectedCriterion)); + testedComponent.emitAdd(); + }); + + it('#getPlaceholder() should fill the placeholder if defined', () => { + const placeholder = 'placeholder'; + testedComponent.placeholder = placeholder; + expect(testedComponent.getPlaceholder()).toEqual(placeholder); + }); + + it('#getPlaceholder() should not fill the placeholder if not defined', () => { + expect(testedComponent.getPlaceholder()).toEqual(''); + }); + + it('#getDatalistId() should return an id', () => { + testedComponent.id = 1; + expect(testedComponent.getDatalistId()).toEqual('datalist_' + 1); + }); +}); diff --git a/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts b/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts index cb31dc15..dc1e1c6a 100644 --- a/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts @@ -13,15 +13,17 @@ import { FormGroup, FormControl, Validators } from '@angular/forms'; import { Criterion, FieldCriterion } from 'src/app/instance/store/models'; import { Option } from 'src/app/metamodel/models'; +/** + * @class + * @classdesc Datalist search type component. + * + * @implements OnChanges + */ @Component({ selector: 'app-datalist', templateUrl: 'datalist.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc Datalist search type component. - */ export class DatalistComponent implements OnChanges { @Input() id: number; @Input() operator: string; @@ -39,7 +41,7 @@ export class DatalistComponent implements OnChanges { disabledOperator: boolean; - ngOnChanges(changes: SimpleChanges) { + ngOnChanges(changes: SimpleChanges): void { if (changes.criterion && changes.criterion.currentValue) { this.form.patchValue(this.criterion); this.form.disable(); diff --git a/client/src/app/instance/search/components/criteria/search-type/date.component.spec.ts b/client/src/app/instance/search/components/criteria/search-type/date.component.spec.ts new file mode 100644 index 00000000..ee97c921 --- /dev/null +++ b/client/src/app/instance/search/components/criteria/search-type/date.component.spec.ts @@ -0,0 +1,115 @@ +import { Component, Input, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +import { DateComponent } from './date.component'; +import { FieldCriterion } from '../../../../store/models/criterion'; +import { BsDatepickerModule } from 'ngx-bootstrap/datepicker'; + +describe('[Instance][Search][Component][Criteria][SearchType] DateComponent', () => { + @Component({ + selector: `app-host`, + template: ` + <app-date + [id]="id" + [operator]="operator" + [label]="label" + [placeholder]="placeholder" + [criterion]="criterion" + [advancedForm]="advancedForm"> + </app-date>` + }) + class TestHostComponent { + @ViewChild(DateComponent, { static: false }) + public testedComponent: DateComponent; + public id: number = undefined; + public operator: string = undefined; + public label: string = undefined; + public placeholder: string = undefined; + public criterion: FieldCriterion = undefined; + public advancedForm: boolean = false; + } + + @Component({ selector: 'app-operator', template: '' }) + class OperatorStubComponent { + @Input() operator: string; + @Input() searchType: string; + @Input() advancedForm: boolean; + @Input() disabled: boolean; + } + + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture<TestHostComponent>; + let testedComponent: DateComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + DateComponent, + TestHostComponent, + OperatorStubComponent + ], + imports: [ + FormsModule, + ReactiveFormsModule, + BsDatepickerModule.forRoot() + ] + }); + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + testedComponent = testHostComponent.testedComponent; + }); + + it('should create the component', () => { + expect(testedComponent).toBeTruthy(); + }); + + it('should call ngOnChanges and apply changes', () => { + const spy = jest.spyOn(testedComponent, 'ngOnChanges'); + testHostComponent.criterion = { id: 1, type: 'field', operator: 'eq', value: '2019-02-17' } as FieldCriterion; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.date.value.getDate()).toEqual(17); + expect(testedComponent.form.controls.date.value.getMonth()).toEqual(1); + expect(testedComponent.form.controls.date.value.getFullYear()).toEqual(2019); + expect(testedComponent.form.disabled).toBeTruthy(); + testHostComponent.criterion = undefined; + testHostFixture.detectChanges(); + expect(testedComponent.form.controls.date.value).toBeNull(); + expect(testedComponent.form.enabled).toBeTruthy(); + expect(spy).toHaveBeenCalledTimes(2); + }); + + it('#changeOperator() should change the operator', () => { + expect(testedComponent.operator).toBeUndefined(); + testedComponent.changeOperator('toto'); + expect(testedComponent.operator).toBe('toto'); + }); + + it('raises the add criterion event when clicked', () => { + testedComponent.id = 1; + const operator = 'eq'; + testedComponent.operator = operator; + const date: Date = new Date('2019-02-17'); + testedComponent.form.controls.date.setValue(date); + const expectedCriterion = { id: testedComponent.id, type: 'field', operator, value: '2019-02-17' } as FieldCriterion; + testedComponent.addCriterion.subscribe((event: FieldCriterion) => expect(event).toEqual(expectedCriterion)); + testedComponent.emitAdd(); + }); + + it('#getPlaceholder() should fill the placeholder if defined', () => { + const placeholder = 'placeholder'; + testedComponent.placeholder = placeholder; + expect(testedComponent.getPlaceholder()).toEqual(placeholder); + }); + + it('#getPlaceholder() should not fill the placeholder if not defined', () => { + expect(testedComponent.getPlaceholder()).toEqual(''); + }); + + it('#getDateString() should return a date as string', () => { + const dateString = '2019-02-17'; + const date = new Date(dateString); + expect(testedComponent.getDateString(date)).toEqual(dateString); + }); +}); diff --git a/client/src/app/instance/search/components/criteria/search-type/date.component.ts b/client/src/app/instance/search/components/criteria/search-type/date.component.ts index d1f4f57c..cef1a631 100644 --- a/client/src/app/instance/search/components/criteria/search-type/date.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/date.component.ts @@ -12,15 +12,17 @@ import { FormGroup, FormControl, Validators } from '@angular/forms'; import { Criterion, FieldCriterion } from 'src/app/instance/store/models'; +/** + * @class + * @classdesc Date search type component. + * + * @implements OnChanges + */ @Component({ selector: 'app-date', templateUrl: 'date.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc Date search type component. - */ export class DateComponent implements OnChanges { @Input() id: number; @Input() operator: string; @@ -37,7 +39,7 @@ export class DateComponent implements OnChanges { disabledOperator: boolean; - ngOnChanges(changes: SimpleChanges) { + ngOnChanges(changes: SimpleChanges): void { if (changes.criterion && changes.criterion.currentValue) { const criterion = changes.criterion.currentValue as FieldCriterion; @@ -66,7 +68,7 @@ export class DateComponent implements OnChanges { * @fires EventEmitter<FieldCriterion> */ emitAdd(): void { - const fd = {id: this.id, type: 'field', operator: this.operator, value: this.getDateString(this.form.value.date)}; + const fd = { id: this.id, type: 'field', operator: this.operator, value: this.getDateString(this.form.value.date) }; this.addCriterion.emit(fd); } diff --git a/client/src/app/instance/search/components/criteria/search-type/datetime.component.spec.ts b/client/src/app/instance/search/components/criteria/search-type/datetime.component.spec.ts index b1b119a8..fa8f17a2 100644 --- a/client/src/app/instance/search/components/criteria/search-type/datetime.component.spec.ts +++ b/client/src/app/instance/search/components/criteria/search-type/datetime.component.spec.ts @@ -2,13 +2,10 @@ import { Component, Input, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { TooltipModule } from 'ngx-bootstrap/tooltip'; - import { DatetimeComponent } from './datetime.component'; import { FieldCriterion } from '../../../../store/models/criterion'; import { BsDatepickerModule } from 'ngx-bootstrap/datepicker'; import { NgSelectModule } from '@ng-select/ng-select'; -import { combineAll } from 'rxjs/operators'; describe('[Instance][Search][Component][Criteria][SearchType] DatetimeComponent', () => { @Component({ @@ -40,9 +37,6 @@ describe('[Instance][Search][Component][Criteria][SearchType] DatetimeComponent' @Input() disabled: boolean; } - @Component({ selector: 'app-help-like', template: '' }) - class HelpLikeStubComponent { } - let testHostComponent: TestHostComponent; let testHostFixture: ComponentFixture<TestHostComponent>; let testedComponent: DatetimeComponent; @@ -52,14 +46,12 @@ describe('[Instance][Search][Component][Criteria][SearchType] DatetimeComponent' declarations: [ DatetimeComponent, TestHostComponent, - OperatorStubComponent, - // HelpLikeStubComponent + OperatorStubComponent ], imports: [ FormsModule, ReactiveFormsModule, NgSelectModule, - // TooltipModule.forRoot(), BsDatepickerModule.forRoot() ] }); @@ -75,10 +67,11 @@ describe('[Instance][Search][Component][Criteria][SearchType] DatetimeComponent' it('should call ngOnChanges and apply changes', () => { const spy = jest.spyOn(testedComponent, 'ngOnChanges'); - const date: Date = new Date('2019-02-17'); testHostComponent.criterion = { id: 1, type: 'field', operator: 'eq', value: '2019-02-17 15:47' } as FieldCriterion; testHostFixture.detectChanges(); - expect(testedComponent.form.controls.date.value).toEqual(date); + expect(testedComponent.form.controls.date.value.getDate()).toEqual(17); + expect(testedComponent.form.controls.date.value.getMonth()).toEqual(1); + expect(testedComponent.form.controls.date.value.getFullYear()).toEqual(2019); expect(testedComponent.form.controls.hh.value).toEqual('15'); expect(testedComponent.form.controls.mm.value).toEqual('47'); expect(testedComponent.form.disabled).toBeTruthy(); diff --git a/client/src/app/instance/search/components/criteria/search-type/select-multiple.component.spec.ts b/client/src/app/instance/search/components/criteria/search-type/select-multiple.component.spec.ts index b89f4faf..9ad8f715 100644 --- a/client/src/app/instance/search/components/criteria/search-type/select-multiple.component.spec.ts +++ b/client/src/app/instance/search/components/criteria/search-type/select-multiple.component.spec.ts @@ -5,7 +5,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { NgSelectModule } from '@ng-select/ng-select'; import { SelectMultipleComponent } from './select-multiple.component'; -import { SelectMultipleCriterion } from '../../../../store/models/criterion'; +import { SelectMultipleCriterion } from '../../../../store/models/criterion'; import { Option } from '../../../../../metamodel/models'; describe('[Instance][Search][Component][Criteria][SearchType] SelectMultipleComponent', () => { -- GitLab