2 * ========================LICENSE_START=================================
5 * Copyright (C) 2019 Nordix Foundation
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ========================LICENSE_END===================================
21 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
22 import { By } from "@angular/platform-browser";
23 import { ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
24 import { ComponentFixture, TestBed } from "@angular/core/testing";
25 import { HarnessLoader } from "@angular/cdk/testing";
26 import { MatButtonModule } from "@angular/material/button";
27 import { MatButtonHarness } from "@angular/material/button/testing";
32 } from "@angular/material/dialog";
33 import { MatSelectModule } from "@angular/material/select";
34 import { MatInputModule } from "@angular/material/input";
35 import { of } from "rxjs";
36 import { ReactiveFormsModule } from "@angular/forms";
37 import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed";
38 import { ToastrModule } from "ngx-toastr";
39 import { MockComponent } from "ng-mocks";
41 import { PolicyService } from "@services/policy/policy.service";
42 import { UiService } from "@services/ui/ui.service";
43 import { PolicyInstanceDialogComponent } from "./policy-instance-dialog.component";
44 import { TypedPolicyEditorComponent } from "@policy/typed-policy-editor/typed-policy-editor.component";
45 import { RicSelectorComponent } from "@policy/ric-selector/ric-selector.component";
46 import { NoTypePolicyEditorComponent } from "@policy/no-type-policy-editor/no-type-policy-editor.component";
47 import { CreatePolicyInstance } from "@interfaces/policy.types";
48 import { NotificationService } from "@services/ui/notification.service";
49 import * as uuid from "uuid";
50 import { HttpErrorResponse } from "@angular/common/http";
52 describe("PolicyInstanceDialogComponent", () => {
53 const untypedSchema = JSON.parse("{}");
54 const typedSchema = JSON.parse(
55 '{ "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "priorityLevel": "number" }}'
58 let component: PolicyInstanceDialogComponent;
59 let fixture: ComponentFixture<PolicyInstanceDialogComponent>;
60 let loader: HarnessLoader;
61 let dialogRefSpy: MatDialogRef<PolicyInstanceDialogComponent>;
62 let policyServiceSpy: jasmine.SpyObj<PolicyService>;
63 let notificationServiceSpy: NotificationService;
65 beforeEach(async () => {
66 dialogRefSpy = jasmine.createSpyObj("MatDialogRef", ["close"]);
67 policyServiceSpy = jasmine.createSpyObj("PolicyService", ["putPolicy"]);
68 notificationServiceSpy = jasmine.createSpyObj("NotificationService", [
72 TestBed.configureTestingModule({
74 BrowserAnimationsModule,
80 ToastrModule.forRoot(),
82 schemas: [CUSTOM_ELEMENTS_SCHEMA],
84 PolicyInstanceDialogComponent,
85 MockComponent(RicSelectorComponent),
86 MockComponent(NoTypePolicyEditorComponent),
87 MockComponent(TypedPolicyEditorComponent),
91 { provide: MatDialogRef, useValue: dialogRefSpy },
92 { provide: PolicyService, useValue: policyServiceSpy },
93 { provide: NotificationService, useValue: notificationServiceSpy },
94 { provide: MAT_DIALOG_DATA, useValue: true },
100 it("should set correct dark mode from UIService", () => {
102 createSchema: untypedSchema,
104 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
105 ({ fixture, component, loader } = compileAndGetComponents(
110 const uiService: UiService = TestBed.inject(UiService);
111 expect(component.darkMode).toBeTruthy();
113 uiService.darkModeState.next(false);
114 fixture.detectChanges();
115 expect(component.darkMode).toBeFalsy();
118 describe("creating policy without type", () => {
119 beforeEach(async () => {
121 createSchema: untypedSchema,
123 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
124 ({ fixture, component, loader } = compileAndGetComponents(
129 jasmine.addCustomEqualityTester(policyTester);
132 it("should contain oran logo and create title and no instance info", async () => {
133 let ele = fixture.debugElement.nativeElement.querySelector("img");
134 expect(ele.src).toContain("assets/oran-logo.png");
136 ele = fixture.debugElement.nativeElement.querySelector("text");
137 expect(ele.textContent).toEqual(
138 "Create new policy instance of type < No Type >"
141 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
142 expect(ele).toBeFalsy();
145 it("should contain ric select with no policy type and no ric selected", async () => {
146 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
147 By.directive(RicSelectorComponent)
149 expect(ricSelector).toBeTruthy();
150 expect(ricSelector.policyTypeName).toBeFalsy();
151 expect(component.policyInstance.ric_id).toBeFalsy();
154 it("should contain json editor with no JSON", async () => {
155 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
156 By.directive(NoTypePolicyEditorComponent)
158 expect(noTypePolicyEditor).toBeTruthy();
159 expect(noTypePolicyEditor.policyJson).toBeFalsy();
162 it("should contain enabled Close button and Submit button", async () => {
163 component.ngOnInit();
165 let closeButton: MatButtonHarness = await loader.getHarness(
166 MatButtonHarness.with({ selector: "#closeButton" })
168 expect(await closeButton.isDisabled()).toBeFalsy();
169 expect(await closeButton.getText()).toEqual("Close");
171 let submitButton: MatButtonHarness = await loader.getHarness(
172 MatButtonHarness.with({ selector: "#submitButton" })
174 expect(await submitButton.getText()).toEqual("Submit");
177 it("should enable Submit button when ric is selected and json is valid", async () => {
178 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
179 By.directive(RicSelectorComponent)
181 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
182 By.directive(NoTypePolicyEditorComponent)
184 let submitButton: MatButtonHarness = await loader.getHarness(
185 MatButtonHarness.with({ selector: "#submitButton" })
188 noTypePolicyEditor.validJson.emit(null);
189 expect(await submitButton.isDisabled()).toBeTruthy();
191 ricSelector.selectedRic.emit("ric1");
192 expect(await submitButton.isDisabled()).toBeTruthy();
194 noTypePolicyEditor.validJson.emit("{}");
195 expect(await submitButton.isDisabled()).toBeFalsy();
198 it("should generate policy ID when submitting new policy and close dialog", async () => {
199 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
200 By.directive(RicSelectorComponent)
202 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
203 By.directive(NoTypePolicyEditorComponent)
205 let submitButton: MatButtonHarness = await loader.getHarness(
206 MatButtonHarness.with({ selector: "#submitButton" })
209 spyOn(uuid, "v4").and.returnValue("1234567890");
210 ricSelector.selectedRic.emit("ric1");
211 noTypePolicyEditor.validJson.emit("{}");
213 policyServiceSpy.putPolicy.and.returnValue(of("Success"));
215 await submitButton.click();
217 const policyInstance = {} as CreatePolicyInstance;
218 policyInstance.policy_data = JSON.parse("{}");
219 policyInstance.policy_id = "1234567890";
220 policyInstance.policytype_id = "";
221 policyInstance.ric_id = "ric1";
222 policyInstance.service_id = "controlpanel";
223 expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance);
225 expect(dialogRefSpy.close).toHaveBeenCalledWith("ok");
228 it("should not close dialog when error from server", async () => {
229 let submitButton: MatButtonHarness = await loader.getHarness(
230 MatButtonHarness.with({ selector: "#submitButton" })
233 const errorResponse = {
235 statusText: "Bad Request",
236 } as HttpErrorResponse;
237 policyServiceSpy.putPolicy.and.returnValue(errorResponse);
239 await submitButton.click();
241 expect(policyServiceSpy.putPolicy).toHaveBeenCalled();
243 expect(dialogRefSpy.close).not.toHaveBeenCalled();
247 describe("content when creating policy with type", () => {
248 beforeEach(async () => {
251 createSchema: typedSchema,
253 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
254 ({ fixture, component, loader } = compileAndGetComponents(
261 it("should contain oran logo and create title and no instance info", async () => {
262 let ele = fixture.debugElement.nativeElement.querySelector("img");
263 expect(ele.src).toContain("assets/oran-logo.png");
265 ele = fixture.debugElement.nativeElement.querySelector("text");
266 expect(ele.textContent).toEqual(
267 "Create new policy instance of type Type 1"
270 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
271 expect(ele).toBeFalsy();
274 it("should contain ric select with provided policy type", async () => {
275 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
276 By.directive(RicSelectorComponent)
278 expect(ricSelector).toBeTruthy();
279 expect(ricSelector.policyTypeName).toEqual("Type 1");
282 it("should contain typed json editor with empty JSON, schema and dark mode true", async () => {
283 const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
284 By.directive(TypedPolicyEditorComponent)
286 expect(typedPolicyEditor).toBeTruthy();
287 expect(typedPolicyEditor.jsonObject).toBeFalsy();
288 expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema);
289 expect(typedPolicyEditor.darkMode).toBeTruthy();
292 it("should contain enabled Close button and Submit button", async () => {
293 component.ngOnInit();
295 let closeButton: MatButtonHarness = await loader.getHarness(
296 MatButtonHarness.with({ selector: "#closeButton" })
298 expect(await closeButton.isDisabled()).toBeFalsy();
299 expect(await closeButton.getText()).toEqual("Close");
301 let submitButton: MatButtonHarness = await loader.getHarness(
302 MatButtonHarness.with({ selector: "#submitButton" })
304 expect(await submitButton.getText()).toEqual("Submit");
307 it("should enable Submit button when ric is selected and json is valid", async () => {
308 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
309 By.directive(RicSelectorComponent)
311 const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
312 By.directive(TypedPolicyEditorComponent)
314 let submitButton: MatButtonHarness = await loader.getHarness(
315 MatButtonHarness.with({ selector: "#submitButton" })
318 typedPolicyEditor.validJson.emit(null);
319 expect(await submitButton.isDisabled()).toBeTruthy();
321 ricSelector.selectedRic.emit("ric1");
322 expect(await submitButton.isDisabled()).toBeTruthy();
324 typedPolicyEditor.validJson.emit("{}");
325 expect(await submitButton.isDisabled()).toBeFalsy();
329 describe("content when editing policy without type", () => {
330 const instanceJson = JSON.parse(
331 '{"qosObjectives": {"priorityLevel": 3100}}'
333 beforeEach(async () => {
335 createSchema: untypedSchema,
336 instanceId: "instanceId",
337 instanceJson: instanceJson,
340 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
341 ({ fixture, component, loader } = compileAndGetComponents(
346 jasmine.addCustomEqualityTester(policyTester);
349 it("should contain oran logo and instance info", async () => {
350 let ele = fixture.debugElement.nativeElement.querySelector("img");
351 expect(ele.src).toContain("assets/oran-logo.png");
353 ele = fixture.debugElement.nativeElement.querySelector("text");
354 expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
356 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
357 expect(ele).toBeTruthy();
358 expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
361 it("should not contain ric select", async () => {
362 const ricSelector = fixture.debugElement.query(
363 By.directive(RicSelectorComponent)
365 expect(ricSelector).toBeFalsy();
368 it("should contain json editor with json data", async () => {
369 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
370 By.directive(NoTypePolicyEditorComponent)
372 expect(noTypePolicyEditor).toBeTruthy();
373 expect(noTypePolicyEditor.policyJson).toEqual(instanceJson);
376 it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
377 let closeButton: MatButtonHarness = await loader.getHarness(
378 MatButtonHarness.with({ selector: "#closeButton" })
380 expect(await closeButton.isDisabled()).toBeFalsy();
381 expect(await closeButton.getText()).toEqual("Close");
383 let submitButton: MatButtonHarness = await loader.getHarness(
384 MatButtonHarness.with({ selector: "#submitButton" })
386 expect(await submitButton.isDisabled()).toBeFalsy();
387 expect(await submitButton.getText()).toEqual("Submit");
390 it("should submit policy with correct data, close dialog and notify user about success", async () => {
391 policyServiceSpy.putPolicy.and.returnValue(of("ok"));
392 let submitButton: MatButtonHarness = await loader.getHarness(
393 MatButtonHarness.with({ selector: "#submitButton" })
396 await submitButton.click();
398 const policyInstance = {} as CreatePolicyInstance;
399 policyInstance.policy_data = instanceJson;
400 policyInstance.policy_id = "instanceId";
401 policyInstance.policytype_id = "";
402 policyInstance.ric_id = "ric1";
403 policyInstance.service_id = "controlpanel";
404 expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance);
406 expect(dialogRefSpy.close).toHaveBeenCalled();
407 expect(notificationServiceSpy.success).toHaveBeenCalledWith(
408 "Policy instanceId submitted"
413 describe("content when editing policy with type", () => {
414 const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}';
415 beforeEach(async () => {
417 createSchema: typedSchema,
418 instanceId: "instanceId",
419 instanceJson: instanceJson,
423 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
424 ({ fixture, component, loader } = compileAndGetComponents(
431 it("should contain oran logo and instance info", async () => {
432 let ele = fixture.debugElement.nativeElement.querySelector("img");
433 expect(ele.src).toContain("assets/oran-logo.png");
435 ele = fixture.debugElement.nativeElement.querySelector("text");
436 expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
438 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
439 expect(ele).toBeTruthy();
440 expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
443 it("should not contain ric select", async () => {
444 const ricSelector = fixture.debugElement.query(
445 By.directive(RicSelectorComponent)
447 expect(ricSelector).toBeFalsy();
450 it("should contain typed json editor with instance JSON, schema and dark mode true", async () => {
451 const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
452 By.directive(TypedPolicyEditorComponent)
454 expect(typedPolicyEditor).toBeTruthy();
455 expect(unescapeQuotes(typedPolicyEditor.jsonObject)).toEqual(
458 expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema);
459 expect(typedPolicyEditor.darkMode).toBeTruthy();
462 it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
463 let closeButton: MatButtonHarness = await loader.getHarness(
464 MatButtonHarness.with({ selector: "#closeButton" })
466 expect(await closeButton.isDisabled()).toBeFalsy();
467 expect(await closeButton.getText()).toEqual("Close");
469 let submitButton: MatButtonHarness = await loader.getHarness(
470 MatButtonHarness.with({ selector: "#submitButton" })
472 expect(await submitButton.isDisabled()).toBeFalsy();
473 expect(await submitButton.getText()).toEqual("Submit");
478 function compileAndGetComponents(
479 fixture: ComponentFixture<PolicyInstanceDialogComponent>,
480 component: PolicyInstanceDialogComponent,
481 loader: HarnessLoader
483 TestBed.compileComponents();
485 fixture = TestBed.createComponent(PolicyInstanceDialogComponent);
486 component = fixture.componentInstance;
487 fixture.detectChanges();
488 loader = TestbedHarnessEnvironment.loader(fixture);
489 return { fixture, component, loader };
492 function unescapeQuotes(string: string): string {
493 return string.replace(/\\"/g, '"');
496 function policyTester(first, second) {
497 if (typeof first[0] === "object" && typeof second[0] === "object") {
498 const policy1 = first[0] as CreatePolicyInstance;
499 const policy2 = second[0] as CreatePolicyInstance;
501 typeof policy1.policy_data === "object" &&
502 typeof policy2.policy_data === "object" &&
503 JSON.stringify(policy1.policy_data) ===
504 JSON.stringify(policy2.policy_data) &&
505 policy1.policy_id === policy2.policy_id &&
506 policy1.policytype_id === policy2.policytype_id &&
507 policy1.ric_id === policy2.ric_id &&
508 policy1.service_id === policy2.service_id