From 3fe1dac7e8d82e2e9dedb52e82f45e493d0ff6de Mon Sep 17 00:00:00 2001 From: elinuxhenrik Date: Thu, 25 Mar 2021 12:55:31 +0100 Subject: [PATCH] Add tests of PolicyInstanceDialog Change-Id: I0f9e9d2bc09991344e89d472ef42d407277b178a Signed-off-by: elinuxhenrik Issue-ID: NONRTRIC-394 --- webapp-frontend/package.json | 3 +- .../no-type-policy-editor.component.ts | 1 + .../policy-instance-dialog.component.spec.ts | 213 ++++++++++++++------- .../policy-instance-dialog.component.ts | 13 +- 4 files changed, 146 insertions(+), 84 deletions(-) diff --git a/webapp-frontend/package.json b/webapp-frontend/package.json index 8ed13a4..16f2687 100644 --- a/webapp-frontend/package.json +++ b/webapp-frontend/package.json @@ -60,9 +60,10 @@ "karma-coverage-istanbul-reporter": "^2.1.1", "karma-jasmine": "~1.1.2", "karma-jasmine-html-reporter": "^0.2.2", + "ng-mocks": "^11.9.1", "protractor": "^7.0.0", "ts-node": "~7.0.0", - "tslint": "~5.11.0", + "tslint": "^6.1.3", "typescript": "~3.8.3" }, "comments": { diff --git a/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.ts b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.ts index 5d2398c..877e0e3 100644 --- a/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.ts +++ b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.ts @@ -54,6 +54,7 @@ export class NoTypePolicyEditorComponent implements OnInit { this.jsonValidator(), ]) ); + if (!this.policyJson) this.policyJson = "{}"; } get policyJsonTextArea(): AbstractControl { diff --git a/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.spec.ts b/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.spec.ts index e9b4c58..3bd9cd7 100644 --- a/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.spec.ts +++ b/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.spec.ts @@ -30,24 +30,24 @@ import { } from "@angular/material/dialog"; import { MatSelectModule } from "@angular/material/select"; import { MatInputModule } from "@angular/material/input"; -import { AbstractControl, ReactiveFormsModule } from "@angular/forms"; +import { ReactiveFormsModule } from "@angular/forms"; import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed"; import { ToastrModule } from "ngx-toastr"; +import { MockComponent } from "ng-mocks"; import { PolicyService } from "../../services/policy/policy.service"; import { ErrorDialogService } from "../../services/ui/error-dialog.service"; import { UiService } from "../../services/ui/ui.service"; import { PolicyInstanceDialogComponent } from "./policy-instance-dialog.component"; -import { - ChangeDetectorRef, - Component, - CUSTOM_ELEMENTS_SCHEMA, - Input, -} from "@angular/core"; +import { ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; import { TypedPolicyEditorComponent } from "../typed-policy-editor/typed-policy-editor.component"; import { RicSelectorComponent } from "../ric-selector/ric-selector.component"; import { NoTypePolicyEditorComponent } from "../no-type-policy-editor/no-type-policy-editor.component"; import { By } from "@angular/platform-browser"; +import { CreatePolicyInstance } from "src/app/interfaces/policy.types"; +import { of } from "rxjs"; +import { NotificationService } from "src/app/services/ui/notification.service"; +import * as uuid from "uuid"; describe("PolicyInstanceDialogComponent", () => { const untypedSchema = "{}"; @@ -57,14 +57,20 @@ describe("PolicyInstanceDialogComponent", () => { let component: PolicyInstanceDialogComponent; let fixture: ComponentFixture; let loader: HarnessLoader; + let dialogRefSpy: MatDialogRef; let policyServiceSpy: jasmine.SpyObj; let errDialogServiceSpy: jasmine.SpyObj; + let notificationServiceSpy: NotificationService; beforeEach(async () => { + dialogRefSpy = jasmine.createSpyObj("MatDialogRef", ["close"]); policyServiceSpy = jasmine.createSpyObj("PolicyService", ["putPolicy"]); errDialogServiceSpy = jasmine.createSpyObj("ErrorDialogService", [ "displayError", ]); + notificationServiceSpy = jasmine.createSpyObj("NotificationService", [ + "success", + ]); TestBed.configureTestingModule({ imports: [ @@ -79,22 +85,41 @@ describe("PolicyInstanceDialogComponent", () => { schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [ PolicyInstanceDialogComponent, - RicSelectorStubComponent, - NoTypePolicyEditorStubComponent, - TypedPolicyEditorStubComponent, + MockComponent(RicSelectorComponent), + MockComponent(NoTypePolicyEditorComponent), + MockComponent(TypedPolicyEditorComponent), ], providers: [ ChangeDetectorRef, - { provide: MatDialogRef, useValue: component }, + { provide: MatDialogRef, useValue: dialogRefSpy }, { provide: PolicyService, useValue: policyServiceSpy }, { provide: ErrorDialogService, useValue: errDialogServiceSpy }, + { provide: NotificationService, useValue: notificationServiceSpy }, { provide: MAT_DIALOG_DATA, useValue: true }, UiService, ], }); }); - describe("content when creating policy without type", () => { + it("should set correct dark mode from UIService", () => { + const policyData = { + createSchema: untypedSchema, + }; + TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy + ({ fixture, component, loader } = compileAndGetComponents( + fixture, + component, + loader + )); + const uiService: UiService = TestBed.inject(UiService); + expect(component.darkMode).toBeTruthy(); + + uiService.darkModeState.next(false); + fixture.detectChanges(); + expect(component.darkMode).toBeFalsy(); + }); + + describe("creating policy without type", () => { beforeEach(async () => { const policyData = { createSchema: untypedSchema, @@ -105,6 +130,7 @@ describe("PolicyInstanceDialogComponent", () => { component, loader )); + jasmine.addCustomEqualityTester(policyTester); }); it("should contain oran logo and create title and no instance info", async () => { @@ -120,20 +146,21 @@ describe("PolicyInstanceDialogComponent", () => { expect(ele).toBeFalsy(); }); - it("should contain ric select with no policy type", async () => { + it("should contain ric select with no policy type and no ric selected", async () => { const ricSelector: RicSelectorComponent = fixture.debugElement.query( By.directive(RicSelectorComponent) ).componentInstance; expect(ricSelector).toBeTruthy(); expect(ricSelector.policyTypeName).toBeFalsy(); + expect(component.policyInstance.ric_id).toBeFalsy(); }); - it("should contain json editor with empty JSON", async () => { + it("should contain json editor with no JSON", async () => { const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query( By.directive(NoTypePolicyEditorComponent) ).componentInstance; expect(noTypePolicyEditor).toBeTruthy(); - expect(noTypePolicyEditor.policyJson).toEqual("{}"); + expect(noTypePolicyEditor.policyJson).toBeFalsy(); }); it("should contain enabled Close button and Submit button", async () => { @@ -150,6 +177,51 @@ describe("PolicyInstanceDialogComponent", () => { ); expect(await submitButton.getText()).toEqual("Submit"); }); + + it("should enable Submit button when ric is selected and json is valid", async () => { + const ricSelector: RicSelectorComponent = fixture.debugElement.query( + By.directive(RicSelectorComponent) + ).componentInstance; + const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query( + By.directive(NoTypePolicyEditorComponent) + ).componentInstance; + let submitButton: MatButtonHarness = await loader.getHarness( + MatButtonHarness.with({ selector: "#submitButton" }) + ); + + noTypePolicyEditor.validJson.emit(null); + expect(await submitButton.isDisabled()).toBeTruthy(); + + ricSelector.selectedRic.emit("ric1"); + expect(await submitButton.isDisabled()).toBeTruthy(); + + noTypePolicyEditor.validJson.emit("{}"); + expect(await submitButton.isDisabled()).toBeFalsy(); + }); + + it("should generate policy ID when submitting new policy", async () => { + const ricSelector: RicSelectorComponent = fixture.debugElement.query( + By.directive(RicSelectorComponent) + ).componentInstance; + const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query( + By.directive(NoTypePolicyEditorComponent) + ).componentInstance; + let submitButton: MatButtonHarness = await loader.getHarness( + MatButtonHarness.with({ selector: "#submitButton" }) + ); + + spyOn(uuid, "v4").and.returnValue(1234567890); + ricSelector.selectedRic.emit("ric1"); + noTypePolicyEditor.validJson.emit("{}"); + await submitButton.click(); + + const policyInstance = {} as CreatePolicyInstance; + policyInstance.policy_data = "{}"; + policyInstance.policy_id = "1234567890"; + policyInstance.ric_id = "ric1"; + policyInstance.service_id = "controlpanel"; + expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance); + }); }); describe("content when creating policy with type", () => { @@ -211,6 +283,27 @@ describe("PolicyInstanceDialogComponent", () => { ); expect(await submitButton.getText()).toEqual("Submit"); }); + + it("should enable Submit button when ric is selected and json is valid", async () => { + const ricSelector: RicSelectorComponent = fixture.debugElement.query( + By.directive(RicSelectorComponent) + ).componentInstance; + const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query( + By.directive(TypedPolicyEditorComponent) + ).componentInstance; + let submitButton: MatButtonHarness = await loader.getHarness( + MatButtonHarness.with({ selector: "#submitButton" }) + ); + + typedPolicyEditor.validJson.emit(null); + expect(await submitButton.isDisabled()).toBeTruthy(); + + ricSelector.selectedRic.emit("ric1"); + expect(await submitButton.isDisabled()).toBeTruthy(); + + typedPolicyEditor.validJson.emit("{}"); + expect(await submitButton.isDisabled()).toBeFalsy(); + }); }); describe("content when editing policy without type", () => { @@ -229,6 +322,7 @@ describe("PolicyInstanceDialogComponent", () => { component, loader )); + jasmine.addCustomEqualityTester(policyTester); }); it("should contain oran logo and instance info", async () => { @@ -256,7 +350,7 @@ describe("PolicyInstanceDialogComponent", () => { ).componentInstance; expect(noTypePolicyEditor).toBeTruthy(); expect(unescapeQuotes(noTypePolicyEditor.policyJson)).toEqual( - '"' + instanceJson + '"' + instanceJson ); }); @@ -273,6 +367,27 @@ describe("PolicyInstanceDialogComponent", () => { expect(await submitButton.isDisabled()).toBeFalsy(); expect(await submitButton.getText()).toEqual("Submit"); }); + + it("should submit policy with correct data, close dialog and notify user about success", async () => { + policyServiceSpy.putPolicy.and.returnValue(of("ok")); + let submitButton: MatButtonHarness = await loader.getHarness( + MatButtonHarness.with({ selector: "#submitButton" }) + ); + + await submitButton.click(); + + const policyInstance = {} as CreatePolicyInstance; + policyInstance.policy_data = instanceJson; + policyInstance.policy_id = "instanceId"; + policyInstance.ric_id = "ric1"; + policyInstance.service_id = "controlpanel"; + expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance); + + expect(dialogRefSpy.close).toHaveBeenCalled(); + expect(notificationServiceSpy.success).toHaveBeenCalledWith( + "Policy instanceId submitted" + ); + }); }); describe("content when editing policy with type", () => { @@ -358,60 +473,16 @@ function unescapeQuotes(string: string): string { return string.replace(/\\"/g, '"'); } -@Component({ - selector: "nrcp-ric-selector", - template: "", - providers: [ - { - provide: RicSelectorComponent, - useClass: RicSelectorStubComponent, - }, - ], -}) -class RicSelectorStubComponent { - @Input() policyTypeName: string = ""; - - get selectedRic(): string { - return "ric1"; - } -} - -@Component({ - selector: "nrcp-no-type-policy-editor", - template: "", - providers: [ - { - provide: NoTypePolicyEditorComponent, - useClass: NoTypePolicyEditorStubComponent, - }, - ], -}) -class NoTypePolicyEditorStubComponent { - @Input() policyJson: string; - - get policyJsonTextArea(): AbstractControl { - const textArea = { value: "{}" } as AbstractControl; - return textArea; - } -} - -@Component({ - selector: "nrcp-typed-policy-editor", - template: "", - providers: [ - { - provide: TypedPolicyEditorComponent, - useClass: TypedPolicyEditorStubComponent, - }, - ], -}) -class TypedPolicyEditorStubComponent { - @Input() jsonSchemaObject: any = {}; - @Input() jsonObject: any = {}; - @Input() darkMode: boolean; - - prettyLiveFormData = '"A": "string"'; - get formIsValid(): boolean { - return true; +function policyTester(first, second) { + if (typeof first === "object" && typeof second === "object") { + const policy1 = first as CreatePolicyInstance; + const policy2 = second as CreatePolicyInstance; + return ( + policy1.policy_data === policy2.policy_data && + policy1.policy_id === policy2.policy_id && + policy1.policytype_id === policy2.policytype_id && + policy1.ric_id === policy2.ric_id && + policy1.service_id === policy2.service_id + ); } } diff --git a/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.ts b/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.ts index f649911..f1ff68f 100644 --- a/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.ts +++ b/webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.ts @@ -40,7 +40,6 @@ import { PolicyInstance, PolicyTypeSchema, } from "../../interfaces/policy.types"; -import { formatJsonString } from "../no-type-policy-editor/no-type-policy-editor.component"; @Component({ selector: "nrcp-policy-instance-dialog", @@ -69,13 +68,13 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit { this.policyJson = data.instanceJson; this.jsonSchemaObject = data.createSchema; this.policyInstance.ric_id = data.ric; + this.policyInstance.service_id = "controlpanel"; } ngOnInit() { this.ui.darkModeState.subscribe((isDark) => { this.darkMode = isDark; }); - this.formatNoTypePolicyJson(); } // Do not remove! Needed to avoid "Expression has changed after it was checked" warning @@ -83,16 +82,6 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit { this.cdr.detectChanges(); } - private formatNoTypePolicyJson() { - if (!this.typeHasSchema()) { - if (this.policyInstance.policy_data) { - this.policyJson = formatJsonString(this.policyInstance.policy_data); - } else { - this.policyJson = "{}"; - } - } - } - onSelectedRicChanged(newRic: string): void { this.policyInstance.ric_id = newRic; } -- 2.16.6