X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=webapp-frontend%2Fsrc%2Fapp%2Fpolicy%2Fpolicy-instance-dialog%2Fpolicy-instance-dialog.component.spec.ts;h=438a29528520fe74911748aace835b55aaa44ebb;hb=refs%2Fchanges%2F18%2F5818%2F1;hp=e8038edb14601e7d74266c1da2efd96c005f6801;hpb=ffb56b1ee4e3c4d95cd574c29159181b726db38b;p=portal%2Fnonrtric-controlpanel.git 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 e8038ed..438a295 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 @@ -19,6 +19,8 @@ */ import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { By } from "@angular/platform-browser"; +import { ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { HarnessLoader } from "@angular/cdk/testing"; import { MatButtonModule } from "@angular/material/button"; @@ -30,50 +32,45 @@ import { } from "@angular/material/dialog"; import { MatSelectModule } from "@angular/material/select"; import { MatInputModule } from "@angular/material/input"; -import { AbstractControl, ReactiveFormsModule } from "@angular/forms"; +import { of } from "rxjs"; +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 { 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, -} 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 { PolicyTypeSchema } from "../../interfaces/policy.types"; +import { TypedPolicyEditorComponent } from "@policy/typed-policy-editor/typed-policy-editor.component"; +import { RicSelectorComponent } from "@policy/ric-selector/ric-selector.component"; +import { NoTypePolicyEditorComponent } from "@policy/no-type-policy-editor/no-type-policy-editor.component"; +import { CreatePolicyInstance } from "@interfaces/policy.types"; +import { NotificationService } from "@services/ui/notification.service"; +import * as uuid from "uuid"; describe("PolicyInstanceDialogComponent", () => { const untypedSchema = "{}"; - const untypedSchemaObject = { - id: "", - name: "", - schemaObject: untypedSchema, - } as PolicyTypeSchema; const typedSchema = - '{ "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "priorityLevel": "number" }, "required": [ "priorityLevel" ]}'; - const typedSchemaObject = { - id: "Type 1", - name: "Type 1", - schemaObject: typedSchema, - } as PolicyTypeSchema; + '{ "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "priorityLevel": "number" }}'; 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: [ @@ -88,25 +85,44 @@ 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: untypedSchemaObject, + createSchema: untypedSchema, }; TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy ({ fixture, component, loader } = compileAndGetComponents( @@ -114,6 +130,7 @@ describe("PolicyInstanceDialogComponent", () => { component, loader )); + jasmine.addCustomEqualityTester(policyTester); }); it("should contain oran logo and create title and no instance info", async () => { @@ -129,21 +146,24 @@ describe("PolicyInstanceDialogComponent", () => { expect(ele).toBeFalsy(); }); - it("should contain ric select", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-ric-selector" - ); - expect(ele).toBeTruthy(); + 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", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-no-type-policy-editor" - ); - expect(ele).toBeTruthy(); + 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).toBeFalsy(); }); - it("should contain enabled Close button and disabled Submit button", async () => { + it("should contain enabled Close button and Submit button", async () => { component.ngOnInit(); let closeButton: MatButtonHarness = await loader.getHarness( @@ -155,16 +175,60 @@ describe("PolicyInstanceDialogComponent", () => { let submitButton: MatButtonHarness = await loader.getHarness( MatButtonHarness.with({ selector: "#submitButton" }) ); - // expect(await submitButton.isDisabled()).toBeTruthy(); 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 = JSON.parse("{}"); + policyInstance.policy_id = "1234567890"; + policyInstance.ric_id = "ric1"; + policyInstance.service_id = "controlpanel"; + expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance); + }); }); describe("content when creating policy with type", () => { beforeEach(async () => { const policyData = { name: "Type 1", - createSchema: typedSchemaObject, + createSchema: typedSchema, }; TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy ({ fixture, component, loader } = compileAndGetComponents( @@ -187,21 +251,25 @@ describe("PolicyInstanceDialogComponent", () => { expect(ele).toBeFalsy(); }); - it("should contain ric select", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-ric-selector" - ); - expect(ele).toBeTruthy(); + it("should contain ric select with provided policy type", async () => { + const ricSelector: RicSelectorComponent = fixture.debugElement.query( + By.directive(RicSelectorComponent) + ).componentInstance; + expect(ricSelector).toBeTruthy(); + expect(ricSelector.policyTypeName).toEqual("Type 1"); }); - it("should contain typed json editor", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-typed-policy-editor" - ); - expect(ele).toBeTruthy(); + it("should contain typed json editor with empty JSON, schema and dark mode true", async () => { + const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query( + By.directive(TypedPolicyEditorComponent) + ).componentInstance; + expect(typedPolicyEditor).toBeTruthy(); + expect(typedPolicyEditor.jsonObject).toBeFalsy(); + expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema); + expect(typedPolicyEditor.darkMode).toBeTruthy(); }); - it("should contain enabled Close button and disabled Submit button", async () => { + it("should contain enabled Close button and Submit button", async () => { component.ngOnInit(); let closeButton: MatButtonHarness = await loader.getHarness( @@ -213,18 +281,38 @@ describe("PolicyInstanceDialogComponent", () => { let submitButton: MatButtonHarness = await loader.getHarness( MatButtonHarness.with({ selector: "#submitButton" }) ); - // expect(await submitButton.isDisabled()).toBeTruthy(); 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", () => { + const instanceJson = JSON.parse('{"qosObjectives": {"priorityLevel": 3100}}'); beforeEach(async () => { const policyData = { - createSchema: untypedSchemaObject, + createSchema: untypedSchema, instanceId: "instanceId", - instanceJson: '{"qosObjectives": {"priorityLevel": 3100}}', - name: "Type 1", + instanceJson: instanceJson, ric: "ric1", }; TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy @@ -233,6 +321,7 @@ describe("PolicyInstanceDialogComponent", () => { component, loader )); + jasmine.addCustomEqualityTester(policyTester); }); it("should contain oran logo and instance info", async () => { @@ -248,20 +337,23 @@ describe("PolicyInstanceDialogComponent", () => { }); it("should not contain ric select", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-ric-selector" + const ricSelector = fixture.debugElement.query( + By.directive(RicSelectorComponent) ); - expect(ele).toBeFalsy(); + expect(ricSelector).toBeFalsy(); }); - it("should contain json editor", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-no-type-policy-editor" + it("should contain json editor with json data", async () => { + const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query( + By.directive(NoTypePolicyEditorComponent) + ).componentInstance; + expect(noTypePolicyEditor).toBeTruthy(); + expect(noTypePolicyEditor.policyJson).toEqual( + instanceJson ); - expect(ele).toBeTruthy(); }); - it("should contain enabled Close and Submit buttons", async () => { + it("should contain enabled Close and Submit buttons when all inputs are valid", async () => { let closeButton: MatButtonHarness = await loader.getHarness( MatButtonHarness.with({ selector: "#closeButton" }) ); @@ -274,14 +366,36 @@ 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", () => { + const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}'; beforeEach(async () => { const policyData = { - createSchema: typedSchemaObject, + createSchema: typedSchema, instanceId: "instanceId", - instanceJson: '{"qosObjectives": {"priorityLevel": 3100}}', + instanceJson: instanceJson, name: "name", ric: "ric1", }; @@ -306,20 +420,25 @@ describe("PolicyInstanceDialogComponent", () => { }); it("should not contain ric select", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-ric-selector" + const ricSelector = fixture.debugElement.query( + By.directive(RicSelectorComponent) ); - expect(ele).toBeFalsy(); + expect(ricSelector).toBeFalsy(); }); - it("should contain typed json editor", async () => { - const ele = fixture.debugElement.nativeElement.querySelector( - "nrcp-typed-policy-editor" + it("should contain typed json editor with instance JSON, schema and dark mode true", async () => { + const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query( + By.directive(TypedPolicyEditorComponent) + ).componentInstance; + expect(typedPolicyEditor).toBeTruthy(); + expect(unescapeQuotes(typedPolicyEditor.jsonObject)).toEqual( + instanceJson ); - expect(ele).toBeTruthy(); + expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema); + expect(typedPolicyEditor.darkMode).toBeTruthy(); }); - it("should contain enabled Close and Submit buttons", async () => { + it("should contain enabled Close and Submit buttons when all inputs are valid", async () => { let closeButton: MatButtonHarness = await loader.getHarness( MatButtonHarness.with({ selector: "#closeButton" }) ); @@ -349,48 +468,22 @@ function compileAndGetComponents( return { fixture, component, loader }; } -@Component({ - selector: "nrcp-ric-selecor", - template: "", - providers: [ - { provide: RicSelectorComponent, useClass: RicSelectorStubComponent }, - ], -}) -class RicSelectorStubComponent { - get selectedRic(): string { - return "ric1"; - } -} - -@Component({ - selector: "nrcp-no-type-policy-editor", - template: "", - providers: [ - { - provide: NoTypePolicyEditorComponent, - useClass: NoTypePolicyEditorStubComponent, - }, - ], -}) -class NoTypePolicyEditorStubComponent { - get policyJsonTextArea(): AbstractControl { - const textArea = { value: "{}" } as AbstractControl; - return textArea; - } +function unescapeQuotes(string: string): string { + return string.replace(/\\"/g, '"'); } -@Component({ - selector: "nrcp-typed-policy-editor", - template: "", - providers: [ - { - provide: TypedPolicyEditorComponent, - useClass: TypedPolicyEditorStubComponent, - }, - ], -}) -class TypedPolicyEditorStubComponent { - get formIsValid(): boolean { - return true; +function policyTester(first, second) { + if (typeof first[0] === "object" && typeof second[0] === "object") { + const policy1 = first[0] as CreatePolicyInstance; + const policy2 = second[0] as CreatePolicyInstance; + return ( + typeof policy1.policy_data === "object" && + typeof policy2.policy_data === "object" && + JSON.stringify(policy1.policy_data) === JSON.stringify(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 + ); } }