From 8ce8fccb49a3c082c9fde5f20335af8e85b41584 Mon Sep 17 00:00:00 2001 From: elinuxhenrik Date: Tue, 23 Feb 2021 12:54:22 +0100 Subject: [PATCH] Add test coverage to NoTypePolicyInstanceDialog Change-Id: I8b403959ea76b0306824806c1ce551fc0d0ad564 Signed-off-by: elinuxhenrik Issue-ID: NONRTRIC-406 --- .../ei-coordinator.component.spec.ts | 4 +- webapp-frontend/src/app/interceptor.mock.ts | 9 - webapp-frontend/src/app/interfaces/ric.ts | 4 + webapp-frontend/src/app/mock/ric2.json | 11 ++ webapp-frontend/src/app/mock/rics.json | 4 - .../no-type-policy-instance-dialog.component.html | 17 +- ...o-type-policy-instance-dialog.component.spec.ts | 188 +++++++++++++++++++++ .../no-type-policy-instance-dialog.component.ts | 35 ++-- .../policy-instance-dialog.component.html | 2 +- .../policy-instance-dialog.component.ts | 15 +- .../src/app/services/policy/policy.service.ts | 4 +- 11 files changed, 240 insertions(+), 53 deletions(-) delete mode 100644 webapp-frontend/src/app/mock/rics.json create mode 100644 webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.spec.ts diff --git a/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts b/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts index b1007c2..9a47b4b 100644 --- a/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts +++ b/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts @@ -17,11 +17,11 @@ * limitations under the License. * ========================LICENSE_END=================================== */ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations' import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; -import {HarnessLoader} from '@angular/cdk/testing'; +import { HarnessLoader } from '@angular/cdk/testing'; import { MatIconModule } from '@angular/material/icon'; import { MatInputHarness } from '@angular/material/input/testing' import { MatTableModule } from '@angular/material/table'; diff --git a/webapp-frontend/src/app/interceptor.mock.ts b/webapp-frontend/src/app/interceptor.mock.ts index 9c31ed8..72423ca 100644 --- a/webapp-frontend/src/app/interceptor.mock.ts +++ b/webapp-frontend/src/app/interceptor.mock.ts @@ -36,7 +36,6 @@ import * as eiproducerstatus2 from './mock/ei-producer-status2.json'; import * as policytypesList from './mock/policy-types.json'; import * as policytypes1 from './mock/policy-type1.json'; import * as policyinstanceedit from './mock/policy-instance-edit.json'; -import * as rics from './mock/rics.json'; import * as ric1 from './mock/ric1.json'; import * as ric2 from './mock/ric2.json'; @@ -105,14 +104,6 @@ const urls = [ url: '/a1-policy/v2/rics?policytype_id=', json: ric2 }, - { - url: 'api/policy/rics?policyType=1', - json: rics - }, - { - url: 'api/policy/rics?policyType=2', - json: rics - }, { url: '/ei-producer/v1/eiproducers', json: eiProducerIds diff --git a/webapp-frontend/src/app/interfaces/ric.ts b/webapp-frontend/src/app/interfaces/ric.ts index 7c115af..4ee2b15 100644 --- a/webapp-frontend/src/app/interfaces/ric.ts +++ b/webapp-frontend/src/app/interfaces/ric.ts @@ -20,6 +20,10 @@ // Models of data used by the Policy Control +export interface Rics { + rics: Ric[] +} + export interface Ric { ric_id: string; managed_element_ids: any[]; diff --git a/webapp-frontend/src/app/mock/ric2.json b/webapp-frontend/src/app/mock/ric2.json index f6e36e8..c320f48 100644 --- a/webapp-frontend/src/app/mock/ric2.json +++ b/webapp-frontend/src/app/mock/ric2.json @@ -10,6 +10,17 @@ "" ], "state": "AVAILABLE" + }, + { + "ric_id": "ric3", + "managed_element_ids": [ + "kista_1", + "kista_2" + ], + "policytype_ids": [ + "" + ], + "state": "AVAILABLE" } ] } \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/rics.json b/webapp-frontend/src/app/mock/rics.json deleted file mode 100644 index 0fa4446..0000000 --- a/webapp-frontend/src/app/mock/rics.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - "ric1", - "ric2" -] \ No newline at end of file diff --git a/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.html b/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.html index 5605271..a24264f 100644 --- a/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.html +++ b/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.html @@ -19,7 +19,7 @@ -->
@@ -39,11 +38,11 @@ - - - {{ric.ric_id}} + + {{ric}}
- - - +
diff --git a/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.spec.ts b/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.spec.ts new file mode 100644 index 0000000..3a940c7 --- /dev/null +++ b/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.spec.ts @@ -0,0 +1,188 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2019 Nordix Foundation + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================LICENSE_END=================================== + */ + +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { ComponentFixture, TestBed } from "@angular/core/testing"; +import { HarnessLoader } from "@angular/cdk/testing"; +import { MatButtonModule } from '@angular/material/button'; +import { MatButtonHarness } from '@angular/material/button/testing'; +import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatSelectModule } from '@angular/material/select'; +import { MatSelectHarness } from '@angular/material/select/testing'; +import { MatInputModule } from '@angular/material/input'; +import { MatInputHarness } from '@angular/material/input/testing'; +import { of } from "rxjs/observable/of"; +import { ReactiveFormsModule } from "@angular/forms"; +import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed"; +import { ToastrModule } from "ngx-toastr"; + +import { PolicyService } from "../services/policy/policy.service"; +import { ErrorDialogService } from "../services/ui/error-dialog.service"; +import { UiService } from "../services/ui/ui.service"; +import { NoTypePolicyInstanceDialogComponent } from "./no-type-policy-instance-dialog.component"; +import { Ric } from "../interfaces/ric"; + +describe('NoTypePolicyInstanceDialogComponent', () => { + let component: NoTypePolicyInstanceDialogComponent; + let fixture: ComponentFixture; + let loader: HarnessLoader; + let policyServiceSpy: jasmine.SpyObj; + let errDialogServiceSpy: jasmine.SpyObj; + const ric1: Ric = { ric_id: 'ric1', managed_element_ids: [ 'me1' ], policytype_ids: [ 'type1' ], state: ''}; + const ric2: Ric = { ric_id: 'ric2', managed_element_ids: [ 'me1' ], policytype_ids: [ 'type1' ], state: ''}; + + beforeEach(async () => { + policyServiceSpy = jasmine.createSpyObj('PolicyService', [ 'putPolicy', 'getRics' ]); + errDialogServiceSpy = jasmine.createSpyObj('ErrorDialogService', [ 'displayError' ]); + + policyServiceSpy.getRics.and.returnValue(of({ rics: [ ric1, ric2 ] })); + + TestBed.configureTestingModule({ + imports: [ + BrowserAnimationsModule, + MatButtonModule, + MatDialogModule, + MatInputModule, + MatSelectModule, + ReactiveFormsModule, + ToastrModule.forRoot() + ], + declarations: [ + NoTypePolicyInstanceDialogComponent + ], + providers: [ + { provide: MatDialogRef, useValue: component }, + { provide: PolicyService, useValue: policyServiceSpy }, + { provide: ErrorDialogService, useValue: errDialogServiceSpy }, + { provide: MAT_DIALOG_DATA, useValue: true }, + UiService + ] + }); + }); + + describe('content when creating policy', () => { + beforeEach(async () => { + ({ fixture, component, loader } = compileAndGetComponents(fixture, component, loader)); + }); + + it('should contain oran logo and create title and no instance info', async () => { + let ele = fixture.debugElement.nativeElement.querySelector('img'); + expect(ele.src).toContain('assets/oran-logo.png'); + + ele = fixture.debugElement.nativeElement.querySelector('text'); + expect(ele.childNodes[0].childNodes[0].textContent).toEqual('Create new policy instance of < No type >'); + + ele = fixture.debugElement.nativeElement.querySelector('#instanceInfo'); + expect(ele).toBeFalsy(); + }); + + it('should contain enabled Target selection with no ric selected and json should be empty', async () => { + let ricSelector: MatSelectHarness = await loader.getHarness(MatSelectHarness.with({selector: '#ricSelector'})); + + expect(await ricSelector.isEmpty()).toBeTruthy(); + expect(await ricSelector.isDisabled()).toBeFalsy(); + await ricSelector.open(); + const count = (await ricSelector.getOptions()).length; + expect(count).toEqual(2); + + let jsonTextArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({selector: '#policyJsonTextArea'})); + expect(await jsonTextArea.isDisabled()).toBeFalsy(); + const actualJson: string = await jsonTextArea.getValue(); + expect(actualJson).toEqual(''); + }); + + it('should contain disabled Format and Submit buttons and enabled Close button', async () => { + component.ngOnInit(); + + let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#formatButton'})); + expect(await formatButton.isDisabled()).toBeTruthy(); + expect(await formatButton.getText()).toEqual('Format JSON'); + + let closeButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#closeButton'})); + expect(await closeButton.isDisabled()).toBeFalsy(); + expect(await closeButton.getText()).toEqual('Close'); + + let submitButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#submitButton'})); + expect(await submitButton.isDisabled()).toBeTruthy(); + expect(await submitButton.getText()).toEqual('Submit'); + }); + }); + + describe('content when editing policy', () => { + beforeEach(async () => { + const policyData = { + createSchema: "{}", + instanceId: "instanceId", + instanceJson: '{"qosObjectives": {"priorityLevel": 3100}}', + name: "name", + ric: "ric1" + }; + TestBed.overrideProvider(MAT_DIALOG_DATA, {useValue: policyData }); // Should be provided with a policy + ({ fixture, component, loader } = compileAndGetComponents(fixture, component, loader)); + }); + + it('should contain oran logo and instance info', async () => { + let ele = fixture.debugElement.nativeElement.querySelector('img'); + expect(ele.src).toContain('assets/oran-logo.png'); + + ele = fixture.debugElement.nativeElement.querySelector('text'); + expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title + + ele = fixture.debugElement.nativeElement.querySelector('#instanceInfo'); + expect(ele).toBeTruthy(); + expect(ele.innerText).toEqual('[ric1] Instance ID: instanceId'); + }); + + it('should contain json and no Target selection', async () => { + let ele = fixture.debugElement.nativeElement.querySelector('#ricSelector'); + expect(ele).toBeFalsy(); + + let jsonTextArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({selector: '#policyJsonTextArea'})); + expect(await jsonTextArea.isDisabled()).toBeFalsy(); + const actualJson: string = await jsonTextArea.getValue(); + expect(actualJson).toContain('qosObjectives'); + }); + + it('should contain enabled Format, Submit and Close buttons', async () => { + let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#formatButton'})); + expect(await formatButton.isDisabled()).toBeFalsy(); + expect(await formatButton.getText()).toEqual('Format JSON'); + + let closeButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#closeButton'})); + expect(await closeButton.isDisabled()).toBeFalsy(); + expect(await closeButton.getText()).toEqual('Close'); + + let submitButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#submitButton'})); + expect(await submitButton.isDisabled()).toBeFalsy(); + expect(await submitButton.getText()).toEqual('Submit'); + }); + + }); +}); + +function compileAndGetComponents(fixture: ComponentFixture, component: NoTypePolicyInstanceDialogComponent, loader: HarnessLoader) { + TestBed.compileComponents(); + + fixture = TestBed.createComponent(NoTypePolicyInstanceDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + loader = TestbedHarnessEnvironment.loader(fixture); + return { fixture, component, loader }; +} diff --git a/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.ts b/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.ts index 288ba2e..1d525c2 100644 --- a/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.ts +++ b/webapp-frontend/src/app/policy-control/no-type-policy-instance-dialog.component.ts @@ -19,14 +19,14 @@ */ import { Component, Inject, OnInit } from '@angular/core'; import { FormControl, FormGroup, Validators, ValidatorFn, AbstractControl } from '@angular/forms'; -import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { PolicyService } from '../services/policy/policy.service'; import { NotificationService } from '../services/ui/notification.service'; import { UiService } from '../services/ui/ui.service'; import { HttpErrorResponse } from '@angular/common/http'; import { ErrorDialogService } from '../services/ui/error-dialog.service'; import * as uuid from 'uuid'; -import { Ric } from '../interfaces/ric'; +import { Rics } from '../interfaces/ric'; import { CreatePolicyInstance } from '../interfaces/policy.types'; @Component({ @@ -41,9 +41,10 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { policyJson: string; darkMode: boolean; ric: string; - allRics: Ric[]; + allRicIds: string[] = []; constructor( + public dialogRef: MatDialogRef, private policySvc: PolicyService, private errorService: ErrorDialogService, private notificationService: NotificationService, @@ -68,7 +69,7 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { ]) }); if (!this.policyInstanceId) { - this.fetchRics(); + this.getRicIds(); } } @@ -81,11 +82,12 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { this.policyInstanceId = uuid.v4(); } const self: NoTypePolicyInstanceDialogComponent = this; - let createPolicyInstance = this.createPolicyInstance(this.policyJsonTextArea.value); + let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(this.policyJsonTextArea.value); this.policySvc.putPolicy(createPolicyInstance).subscribe( { next(_) { self.notificationService.success('Policy without type:' + self.policyInstanceId + ' submitted'); + self.dialogRef.close(); }, error(error: HttpErrorResponse) { self.errorService.displayError('Submit failed: ' + error.error); @@ -94,7 +96,7 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { }); } - private createPolicyInstance(policyJson: string) { + private createPolicyInstance(policyJson: string): CreatePolicyInstance { let createPolicyInstance = {} as CreatePolicyInstance; createPolicyInstance.policy_data = JSON.parse(policyJson); createPolicyInstance.policy_id = this.policyInstanceId; @@ -104,22 +106,19 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { return createPolicyInstance; } - private fetchRics() { + getRicIds() { const self: NoTypePolicyInstanceDialogComponent = this; this.policySvc.getRics('').subscribe( { - next(value: Ric[]) { - self.allRics = value; - console.log(value); - }, - error(error: HttpErrorResponse) { - self.errorService.displayError('Fetching of rics failed: ' + error.message); - }, - complete() { } + next(value: Rics) { + value.rics.forEach(ric => { + self.allRicIds.push(ric.ric_id); + }); + } }); } - private formatJsonString(jsonToFormat: any) { + private formatJsonString(jsonToFormat: any): string { return JSON.stringify(jsonToFormat, null, 2); } @@ -135,11 +134,13 @@ export function jsonValidator(): ValidatorFn { }; } -export function isJsonValid(json: string) { +export function isJsonValid(json: string): boolean { try { if (json != null) { JSON.parse(json); return true; + } else { + return false; } } catch (jsonError) { return false; diff --git a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html index a533ed0..76a9ae0 100644 --- a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html +++ b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.html @@ -45,7 +45,7 @@ - + {{ric.ric_id}} diff --git a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts index 70c1057..eaaeff5 100644 --- a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts +++ b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts @@ -31,7 +31,7 @@ import { UiService } from '../services/ui/ui.service'; import { HttpErrorResponse } from '@angular/common/http'; import { FormGroup, FormControl, Validators } from '@angular/forms'; import { ChangeDetectorRef } from '@angular/core'; -import { Ric } from '../interfaces/ric'; +import { Ric, Rics } from '../interfaces/ric'; @Component({ @@ -93,14 +93,10 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit { const self: PolicyInstanceDialogComponent = this; this.dataService.getRics(this.policyTypeName).subscribe( { - next(value: Ric[]) { - self.allRics = value; + next(value: Rics) { + self.allRics = value.rics; console.log(value); - }, - error(error: HttpErrorResponse) { - self.errorService.displayError('Fetching of rics failed: ' + error.message); - }, - complete() { } + } }); } @@ -148,12 +144,13 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit { } const policyJson: string = this.prettyLiveFormData; const self: PolicyInstanceDialogComponent = this; - let createPolicyInstance = this.createPolicyInstance(policyJson); + let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(policyJson); this.dataService.putPolicy(createPolicyInstance).subscribe( { next(_) { self.notificationService.success('Policy ' + self.policyTypeName + ':' + self.policyInstanceId + ' submitted'); + self.dialogRef.close(); }, error(error: HttpErrorResponse) { self.errorService.displayError('Submit failed: ' + error.error); diff --git a/webapp-frontend/src/app/services/policy/policy.service.ts b/webapp-frontend/src/app/services/policy/policy.service.ts index 5ffff13..72375e8 100644 --- a/webapp-frontend/src/app/services/policy/policy.service.ts +++ b/webapp-frontend/src/app/services/policy/policy.service.ts @@ -24,7 +24,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { CreatePolicyInstance, PolicyInstance, PolicyInstanceAck, PolicyInstances, PolicyStatus, PolicyType, PolicyTypes } from '../../interfaces/policy.types'; import { ControlpanelSuccessTransport } from '../../interfaces/controlpanel.types'; -import { Ric } from 'src/app/interfaces/ric'; +import { Ric, Rics } from 'src/app/interfaces/ric'; /** * Services for calling the policy endpoints. @@ -109,7 +109,7 @@ export class PolicyService { } - getRics(policyTypeId: string): Observable { + getRics(policyTypeId: string): Observable { const url = this.buildPath('rics') + '?policytype_id=' + policyTypeId; return this.httpClient.get(url); } -- 2.16.6