From 869cd2b3870fb91b381ac04eefad8dce8ce0bda1 Mon Sep 17 00:00:00 2001 From: Tifenn Guillas <tifenn.guillas@gmail.com> Date: Wed, 3 Nov 2021 11:23:39 +0100 Subject: [PATCH] Tests on cone search => DONE --- .../cone-search/cone-search.component.spec.ts | 113 ++++++++++++++++ .../cone-search/cone-search.component.ts | 19 ++- .../cone-search/dec.component.spec.ts | 123 ++++++++++++++++++ .../components/cone-search/dec.component.ts | 36 +++-- .../cone-search/ra.component.spec.ts | 32 +++-- 5 files changed, 297 insertions(+), 26 deletions(-) create mode 100644 client/src/app/instance/shared-search/components/cone-search/cone-search.component.spec.ts create mode 100644 client/src/app/instance/shared-search/components/cone-search/dec.component.spec.ts diff --git a/client/src/app/instance/shared-search/components/cone-search/cone-search.component.spec.ts b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.spec.ts new file mode 100644 index 00000000..0e341c06 --- /dev/null +++ b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.spec.ts @@ -0,0 +1,113 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Component, Input, ViewChild } from '@angular/core'; +import { FormGroup, ReactiveFormsModule } from '@angular/forms'; + +import { ConeSearchComponent } from './cone-search.component'; +import { ConeSearch, Resolver } from '../../../store/models'; + +describe('[Instance][SharedSearch][Components][ConeSearch] ConeSearchComponent', () => { + @Component({ + selector: `app-host`, + template: ` + <app-cone-search + [coneSearch]="coneSearch" + [resolver]="resolver" + [resolverIsLoading]="resolverIsLoading" + [resolverIsLoaded]="resolverIsLoaded"> + </app-cone-search>` + }) + class TestHostComponent { + @ViewChild(ConeSearchComponent, { static: false }) + public testedComponent: ConeSearchComponent; + public coneSearch: ConeSearch = undefined; + public resolver: Resolver = undefined; + public resolverIsLoading: boolean = false; + public resolverIsLoaded: boolean = false; + } + + @Component({ selector: 'app-resolver', template: '' }) + class ResolverStubComponent { + @Input() coneSearch: ConeSearch; + @Input() resolver: Resolver; + @Input() resolverIsLoading: boolean; + @Input() resolverIsLoaded: boolean; + } + + @Component({ selector: 'app-ra', template: '' }) + class RaStubComponent { + @Input() form: FormGroup; + @Input() unit: string; + @Input() resolver: Resolver; + } + + @Component({ selector: 'app-dec', template: '' }) + class DecStubComponent { + @Input() form: FormGroup; + @Input() unit: string; + @Input() resolver: Resolver; + } + + @Component({ selector: 'app-radius', template: '' }) + class RadiusStubComponent { + @Input() form: FormGroup; + } + + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture<TestHostComponent>; + let testedComponent: ConeSearchComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + TestHostComponent, + ConeSearchComponent, + ResolverStubComponent, + RaStubComponent, + DecStubComponent, + RadiusStubComponent + ], + imports: [ReactiveFormsModule] + }); + 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.resolver = { name: 'myObject', ra: 1, dec: 2 }; + testHostFixture.detectChanges(); + expect(spy).toHaveBeenCalledTimes(1); + expect(testedComponent.unit).toEqual('degree'); + expect(testedComponent.form.controls.ra.enabled).toBeTruthy(); + expect(testedComponent.form.controls.dec.enabled).toBeTruthy(); + expect(testedComponent.form.controls.radius.enabled).toBeTruthy(); + + testHostComponent.coneSearch = { ra: 1, dec: 2, radius: 3 }; + testHostFixture.detectChanges(); + expect(spy).toHaveBeenCalledTimes(2); + expect(testedComponent.form.controls.ra.value).toEqual(1); + expect(testedComponent.form.controls.dec.value).toEqual(2); + expect(testedComponent.form.controls.radius.value).toEqual(3); + expect(testedComponent.form.disabled).toBeTruthy(); + + testHostComponent.coneSearch = undefined; + testedComponent.unit = 'hms'; + testHostFixture.detectChanges(); + expect(spy).toHaveBeenCalledTimes(3); + expect(testedComponent.form.controls.ra_hms.enabled).toBeTruthy(); + expect(testedComponent.form.controls.dec_dms.enabled).toBeTruthy(); + }); + + it('#getConeSearch() should return cone search from form', () => { + testedComponent.form.controls.ra.setValue(1); + testedComponent.form.controls.dec.setValue(2); + testedComponent.form.controls.radius.setValue(3); + expect(testedComponent.getConeSearch()).toEqual({ ra: 1, dec: 2, radius: 3 }); + }); +}); diff --git a/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts index 0bd90e12..4da6389e 100644 --- a/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts +++ b/client/src/app/instance/shared-search/components/cone-search/cone-search.component.ts @@ -13,14 +13,16 @@ import { FormGroup, FormControl, Validators } from '@angular/forms'; import { ConeSearch, Resolver } from 'src/app/instance/store/models'; import { nanValidator, rangeValidator } from '../../validators'; -@Component({ - selector: 'app-cone-search', - templateUrl: 'cone-search.component.html' -}) /** * @class * @classdesc Cone search container. + * + * @implements OnChanges */ +@Component({ + selector: 'app-cone-search', + templateUrl: 'cone-search.component.html' +}) export class ConeSearchComponent implements OnChanges { @Input() coneSearch: ConeSearch; @Input() resolver: Resolver; @@ -46,13 +48,13 @@ export class ConeSearchComponent implements OnChanges { public unit = 'degree'; - ngOnChanges(changes: SimpleChanges) { + ngOnChanges(changes: SimpleChanges): void { if (changes.resolver && changes.resolver.currentValue) { this.unit = 'degree'; } if (changes.coneSearch && !changes.coneSearch.currentValue) { - if (this.unit = 'degree') { + if (this.unit == 'degree') { this.form.controls.ra.enable(); this.form.controls.dec.enable(); this.form.controls.radius.enable(); @@ -68,6 +70,11 @@ export class ConeSearchComponent implements OnChanges { } } + /** + * Returns cone-search from form. + * + * @return ConeSearch + */ getConeSearch(): ConeSearch { return { ra: this.form.controls.ra.value, diff --git a/client/src/app/instance/shared-search/components/cone-search/dec.component.spec.ts b/client/src/app/instance/shared-search/components/cone-search/dec.component.spec.ts new file mode 100644 index 00000000..72005d14 --- /dev/null +++ b/client/src/app/instance/shared-search/components/cone-search/dec.component.spec.ts @@ -0,0 +1,123 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Component, ViewChild } from '@angular/core'; +import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; + +import { of } from 'rxjs'; + +import { DecComponent } from './dec.component'; +import { Resolver } from '../../../store/models'; +import { nanValidator, rangeValidator } from '../../validators'; + +describe('[Instance][SharedSearch][Components][ConeSearch] DecComponent', () => { + let form = new FormGroup({ + dec: new FormControl('', [Validators.required, nanValidator, rangeValidator(-90, 90, 'DEC')]), + dec_dms: new FormGroup({ + d: new FormControl('', [Validators.required, nanValidator, rangeValidator(-90, 90, 'Degree')]), + m: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Minutes')]), + s: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')]) + }) + }); + + @Component({ + selector: `app-host`, + template: ` + <app-dec + [form]="form" + [unit]="unit" + [resolver]="resolver"> + </app-dec>` + }) + class TestHostComponent { + @ViewChild(DecComponent, { static: false }) + public testedComponent: DecComponent; + public form: FormGroup = form; + public unit: string = 'degree'; + public resolver: Resolver = undefined; + } + + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture<TestHostComponent>; + let testedComponent: DecComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + TestHostComponent, + DecComponent + ], + imports: [ReactiveFormsModule] + }); + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + testedComponent = testHostComponent.testedComponent; + }); + + it('should create the component', () => { + expect(testedComponent).toBeTruthy(); + }); + + it('#ngOnInit() should disable dec_dms control and convert degrees to HMS', () => { + testHostComponent.form.controls.dec.setValue(32.87); + expect(testedComponent.form.controls.dec_dms.disabled).toBeTruthy(); + setTimeout(function () { + expect(testedComponent.getDecDmsForm().controls.d.value).toEqual(32); + expect(testedComponent.getDecDmsForm().controls.m.value).toEqual(52); + expect(testedComponent.getDecDmsForm().controls.s.value).toEqual(12); + }, 300); + }); + + it('should call ngOnChanges and apply changes', () => { + testedComponent.decControlSubscription = of().subscribe(); + testedComponent.decDmsSubscription = of().subscribe(); + const spyDec = jest.spyOn(testedComponent.decControlSubscription, 'unsubscribe'); + const spy = jest.spyOn(testedComponent, 'ngOnChanges'); + testHostComponent.unit = 'hms'; + testHostFixture.detectChanges(); + expect(spy).toHaveBeenCalledTimes(1); + expect(testedComponent.form.controls.dec_dms.enabled).toBeTruthy(); + expect(testedComponent.form.controls.dec.disabled).toBeTruthy(); + expect(spyDec).toHaveBeenCalledTimes(1); + testHostComponent.unit = 'degree'; + testHostFixture.detectChanges(); + expect(spy).toHaveBeenCalledTimes(2); + expect(testedComponent.form.controls.dec_dms.disabled).toBeTruthy(); + expect(testedComponent.form.controls.dec.enabled).toBeTruthy(); + testHostComponent.resolver = { ra: 1, dec: 2, name: 'myObject' }; + testHostFixture.detectChanges(); + expect(spy).toHaveBeenCalledTimes(3); + expect(testedComponent.form.controls.dec.value).toEqual(2); + }); + + it('#getDecDmsForm() should return DEC DMS form control', () => { + const form: FormGroup = testedComponent.getDecDmsForm(); + expect(Object.keys(form.controls).length).toEqual(3); + expect(Object.keys(form.controls)).toContain('d'); + expect(Object.keys(form.controls)).toContain('m'); + expect(Object.keys(form.controls)).toContain('s'); + }); + + it('#deg2DMS(value) convert DEC from degree to D:MM:SS', () => { + testedComponent.deg2DMS(32.87); + expect(testedComponent.getDecDmsForm().controls.d.value).toBe(32); + expect(testedComponent.getDecDmsForm().controls.m.value).toBe(52); + expect(parseFloat(testedComponent.getDecDmsForm().controls.s.value)).toBe(12); + }); + + it('#DMS2Deg(dms) convert DEC from D:MM:SS to degree', () => { + testedComponent.DMS2Deg({ d: 32, m: 52, s: 12 }); + expect(testedComponent.form.controls.dec.value).toBe(32.87); + testedComponent.DMS2Deg({ d: -32, m: 52, s: 12 }); + expect(testedComponent.form.controls.dec.value).toBe(-32.87); + }); + + it('#ngOnDestroy() should unsubscribe from decControlSubscription and decDmsSubscription', () => { + testedComponent.decControlSubscription = of().subscribe(); + testedComponent.decDmsSubscription = of().subscribe(); + const spyDec = jest.spyOn(testedComponent.decControlSubscription, 'unsubscribe'); + const spyDecDms = jest.spyOn(testedComponent.decDmsSubscription, 'unsubscribe'); + testedComponent.ngOnDestroy(); + expect(spyDec).toHaveBeenCalledTimes(1); + expect(spyDecDms).toHaveBeenCalledTimes(1); + }); +}); diff --git a/client/src/app/instance/shared-search/components/cone-search/dec.component.ts b/client/src/app/instance/shared-search/components/cone-search/dec.component.ts index 193bc665..7dca838b 100644 --- a/client/src/app/instance/shared-search/components/cone-search/dec.component.ts +++ b/client/src/app/instance/shared-search/components/cone-search/dec.component.ts @@ -15,16 +15,20 @@ import { debounceTime } from 'rxjs/operators'; import { Resolver } from 'src/app/instance/store/models'; +/** + * @class + * @classdesc DEC component. + * + * @implements OnInit + * @implements OnChanges + * @implements OnDestroy + */ @Component({ selector: 'app-dec', templateUrl: 'dec.component.html', styleUrls: ['input-group.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) -/** - * @class - * @classdesc DEC component. - */ export class DecComponent implements OnInit, OnDestroy, OnChanges { @Input() form: FormGroup; @Input() unit: string; @@ -33,7 +37,7 @@ export class DecComponent implements OnInit, OnDestroy, OnChanges { public decControlSubscription: Subscription public decDmsSubscription: Subscription; - ngOnInit() { + ngOnInit(): void { this.form.controls.dec_dms.disable(); this.decControlSubscription = this.form.controls.dec.valueChanges.pipe(debounceTime(250)) .subscribe(deg => this.deg2DMS(deg)); @@ -62,11 +66,20 @@ export class DecComponent implements OnInit, OnDestroy, OnChanges { } } - getDecDmsForm() { - const decDmsForm = this.form.controls.dec_dms as FormGroup; - return decDmsForm; + /** + * Returns DEC form group. + * + * @return FormGroup + */ + getDecDmsForm(): FormGroup { + return this.form.controls.dec_dms as FormGroup; } + /** + * Converts DEC degree minute second from degree and sets Dec DMS fields. + * + * @param {number} deg - The degree value. + */ deg2DMS(deg: number): void { const hh = Math.trunc(deg); let tmp = (Math.abs(deg - hh)) * 60; @@ -79,6 +92,11 @@ export class DecComponent implements OnInit, OnDestroy, OnChanges { decDmsForm.controls.s.setValue(ss); } + /** + * Sets DEC degree from degree minute second and sets RA degree field. + * + * @param {d: number, m: number, s: number} dms - Coordinates in DMS. + */ DMS2Deg(dms: {d: number, m: number, s: number }): void { const tmp = ((dms.s / 60) + dms.m) / 60; let deg = tmp + Math.abs(dms.d); @@ -88,7 +106,7 @@ export class DecComponent implements OnInit, OnDestroy, OnChanges { this.form.controls.dec.setValue(deg); } - ngOnDestroy() { + ngOnDestroy(): void { if (this.decControlSubscription) this.decControlSubscription.unsubscribe(); if (this.decDmsSubscription) this.decDmsSubscription.unsubscribe(); } diff --git a/client/src/app/instance/shared-search/components/cone-search/ra.component.spec.ts b/client/src/app/instance/shared-search/components/cone-search/ra.component.spec.ts index efb1dc3e..bc5a055a 100644 --- a/client/src/app/instance/shared-search/components/cone-search/ra.component.spec.ts +++ b/client/src/app/instance/shared-search/components/cone-search/ra.component.spec.ts @@ -1,11 +1,12 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Component, ViewChild } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { of } from 'rxjs'; + import { RaComponent } from './ra.component'; -import { ConeSearch, Resolver } from '../../../store/models'; +import { Resolver } from '../../../store/models'; import { nanValidator, rangeValidator } from '../../validators'; -import { of } from 'rxjs'; describe('[Instance][SharedSearch][Components][ConeSearch] RaComponent', () => { let form = new FormGroup({ @@ -16,6 +17,7 @@ describe('[Instance][SharedSearch][Components][ConeSearch] RaComponent', () => { s: new FormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')]) }) }); + @Component({ selector: `app-host`, template: ` @@ -56,27 +58,35 @@ describe('[Instance][SharedSearch][Components][ConeSearch] RaComponent', () => { }); it('#ngOnInit() should disable ra_hms control and convert degrees to HMS', () => { + testedComponent.form.controls.ra.setValue(78.2); expect(testedComponent.form.controls.ra_hms.disabled).toBeTruthy(); + setTimeout(function () { + expect(testedComponent.getRaHmsForm().controls.h.value).toEqual(5); + expect(testedComponent.getRaHmsForm().controls.m.value).toEqual(12); + expect(testedComponent.getRaHmsForm().controls.s.value).toEqual(48); + }, 300); }); it('should call ngOnChanges and apply changes', () => { testedComponent.raControlSubscription = of().subscribe(); testedComponent.raHmsFormSubscription = of().subscribe(); const spyRa = jest.spyOn(testedComponent.raControlSubscription, 'unsubscribe'); - const spyRaHms = jest.spyOn(testedComponent.raHmsFormSubscription, 'unsubscribe'); const spy = jest.spyOn(testedComponent, 'ngOnChanges'); + testHostComponent.unit = 'hms'; + testHostFixture.detectChanges(); + expect(spy).toHaveBeenCalledTimes(1); + expect(testedComponent.form.controls.ra_hms.enabled).toBeTruthy(); + expect(testedComponent.form.controls.ra.disabled).toBeTruthy(); + expect(spyRa).toHaveBeenCalledTimes(1); testHostComponent.unit = 'degree'; testHostFixture.detectChanges(); - // expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(2); expect(testedComponent.form.controls.ra_hms.disabled).toBeTruthy(); expect(testedComponent.form.controls.ra.enabled).toBeTruthy(); - // expect(spyRaHms).toHaveBeenCalledTimes(1); - testHostComponent.unit = 'hms'; + testHostComponent.resolver = { ra: 1, dec: 2, name: 'myObject' }; testHostFixture.detectChanges(); - // expect(spy).toHaveBeenCalledTimes(2); - expect(testedComponent.form.controls.ra_hms.enabled).toBeTruthy(); - expect(testedComponent.form.controls.ra.disabled).toBeTruthy(); - // expect(spyRa).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(3); + expect(testedComponent.form.controls.ra.value).toEqual(1); }); it('#getRaHmsForm() should return RA HMS form control', () => { -- GitLab