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 { ErrorDialogService } from "@services/ui/error-dialog.service";
43 import { UiService } from "@services/ui/ui.service";
44 import { PolicyInstanceDialogComponent } from "./policy-instance-dialog.component";
45 import { TypedPolicyEditorComponent } from "@policy/typed-policy-editor/typed-policy-editor.component";
46 import { RicSelectorComponent } from "@policy/ric-selector/ric-selector.component";
47 import { NoTypePolicyEditorComponent } from "@policy/no-type-policy-editor/no-type-policy-editor.component";
48 import { CreatePolicyInstance } from "@interfaces/policy.types";
49 import { NotificationService } from "@services/ui/notification.service";
50 import * as uuid from "uuid";
52 describe("PolicyInstanceDialogComponent", () => {
53 const untypedSchema = JSON.parse("{}");
55 JSON.parse('{ "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "priorityLevel": "number" }}');
57 let component: PolicyInstanceDialogComponent;
58 let fixture: ComponentFixture<PolicyInstanceDialogComponent>;
59 let loader: HarnessLoader;
60 let dialogRefSpy: MatDialogRef<PolicyInstanceDialogComponent>;
61 let policyServiceSpy: jasmine.SpyObj<PolicyService>;
62 let errDialogServiceSpy: jasmine.SpyObj<ErrorDialogService>;
63 let notificationServiceSpy: NotificationService;
65 beforeEach(async () => {
66 dialogRefSpy = jasmine.createSpyObj("MatDialogRef", ["close"]);
67 policyServiceSpy = jasmine.createSpyObj("PolicyService", ["putPolicy"]);
68 errDialogServiceSpy = jasmine.createSpyObj("ErrorDialogService", [
71 notificationServiceSpy = jasmine.createSpyObj("NotificationService", [
75 TestBed.configureTestingModule({
77 BrowserAnimationsModule,
83 ToastrModule.forRoot(),
85 schemas: [CUSTOM_ELEMENTS_SCHEMA],
87 PolicyInstanceDialogComponent,
88 MockComponent(RicSelectorComponent),
89 MockComponent(NoTypePolicyEditorComponent),
90 MockComponent(TypedPolicyEditorComponent),
94 { provide: MatDialogRef, useValue: dialogRefSpy },
95 { provide: PolicyService, useValue: policyServiceSpy },
96 { provide: ErrorDialogService, useValue: errDialogServiceSpy },
97 { provide: NotificationService, useValue: notificationServiceSpy },
98 { provide: MAT_DIALOG_DATA, useValue: true },
104 it("should set correct dark mode from UIService", () => {
106 createSchema: untypedSchema,
108 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
109 ({ fixture, component, loader } = compileAndGetComponents(
114 const uiService: UiService = TestBed.inject(UiService);
115 expect(component.darkMode).toBeTruthy();
117 uiService.darkModeState.next(false);
118 fixture.detectChanges();
119 expect(component.darkMode).toBeFalsy();
122 describe("creating policy without type", () => {
123 beforeEach(async () => {
125 createSchema: untypedSchema,
127 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
128 ({ fixture, component, loader } = compileAndGetComponents(
133 jasmine.addCustomEqualityTester(policyTester);
136 it("should contain oran logo and create title and no instance info", async () => {
137 let ele = fixture.debugElement.nativeElement.querySelector("img");
138 expect(ele.src).toContain("assets/oran-logo.png");
140 ele = fixture.debugElement.nativeElement.querySelector("text");
141 expect(ele.textContent).toEqual(
142 "Create new policy instance of type < No Type >"
145 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
146 expect(ele).toBeFalsy();
149 it("should contain ric select with no policy type and no ric selected", async () => {
150 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
151 By.directive(RicSelectorComponent)
153 expect(ricSelector).toBeTruthy();
154 expect(ricSelector.policyTypeName).toBeFalsy();
155 expect(component.policyInstance.ric_id).toBeFalsy();
158 it("should contain json editor with no JSON", async () => {
159 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
160 By.directive(NoTypePolicyEditorComponent)
162 expect(noTypePolicyEditor).toBeTruthy();
163 expect(noTypePolicyEditor.policyJson).toBeFalsy();
166 it("should contain enabled Close button and Submit button", async () => {
167 component.ngOnInit();
169 let closeButton: MatButtonHarness = await loader.getHarness(
170 MatButtonHarness.with({ selector: "#closeButton" })
172 expect(await closeButton.isDisabled()).toBeFalsy();
173 expect(await closeButton.getText()).toEqual("Close");
175 let submitButton: MatButtonHarness = await loader.getHarness(
176 MatButtonHarness.with({ selector: "#submitButton" })
178 expect(await submitButton.getText()).toEqual("Submit");
181 it("should enable Submit button when ric is selected and json is valid", async () => {
182 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
183 By.directive(RicSelectorComponent)
185 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
186 By.directive(NoTypePolicyEditorComponent)
188 let submitButton: MatButtonHarness = await loader.getHarness(
189 MatButtonHarness.with({ selector: "#submitButton" })
192 noTypePolicyEditor.validJson.emit(null);
193 expect(await submitButton.isDisabled()).toBeTruthy();
195 ricSelector.selectedRic.emit("ric1");
196 expect(await submitButton.isDisabled()).toBeTruthy();
198 noTypePolicyEditor.validJson.emit("{}");
199 expect(await submitButton.isDisabled()).toBeFalsy();
202 it("should generate policy ID when submitting new policy", async () => {
203 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
204 By.directive(RicSelectorComponent)
206 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
207 By.directive(NoTypePolicyEditorComponent)
209 let submitButton: MatButtonHarness = await loader.getHarness(
210 MatButtonHarness.with({ selector: "#submitButton" })
213 spyOn(uuid, "v4").and.returnValue("1234567890");
214 ricSelector.selectedRic.emit("ric1");
215 noTypePolicyEditor.validJson.emit("{}");
216 await submitButton.click();
218 const policyInstance = {} as CreatePolicyInstance;
219 policyInstance.policy_data = JSON.parse("{}");
220 policyInstance.policy_id = "1234567890";
221 policyInstance.ric_id = "ric1";
222 policyInstance.service_id = "controlpanel";
223 expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance);
227 describe("content when creating policy with type", () => {
228 beforeEach(async () => {
231 createSchema: typedSchema,
233 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
234 ({ fixture, component, loader } = compileAndGetComponents(
241 it("should contain oran logo and create title and no instance info", async () => {
242 let ele = fixture.debugElement.nativeElement.querySelector("img");
243 expect(ele.src).toContain("assets/oran-logo.png");
245 ele = fixture.debugElement.nativeElement.querySelector("text");
246 expect(ele.textContent).toEqual(
247 "Create new policy instance of type Type 1"
250 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
251 expect(ele).toBeFalsy();
254 it("should contain ric select with provided policy type", async () => {
255 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
256 By.directive(RicSelectorComponent)
258 expect(ricSelector).toBeTruthy();
259 expect(ricSelector.policyTypeName).toEqual("Type 1");
262 it("should contain typed json editor with empty JSON, schema and dark mode true", async () => {
263 const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
264 By.directive(TypedPolicyEditorComponent)
266 expect(typedPolicyEditor).toBeTruthy();
267 expect(typedPolicyEditor.jsonObject).toBeFalsy();
268 expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema);
269 expect(typedPolicyEditor.darkMode).toBeTruthy();
272 it("should contain enabled Close button and Submit button", async () => {
273 component.ngOnInit();
275 let closeButton: MatButtonHarness = await loader.getHarness(
276 MatButtonHarness.with({ selector: "#closeButton" })
278 expect(await closeButton.isDisabled()).toBeFalsy();
279 expect(await closeButton.getText()).toEqual("Close");
281 let submitButton: MatButtonHarness = await loader.getHarness(
282 MatButtonHarness.with({ selector: "#submitButton" })
284 expect(await submitButton.getText()).toEqual("Submit");
287 it("should enable Submit button when ric is selected and json is valid", async () => {
288 const ricSelector: RicSelectorComponent = fixture.debugElement.query(
289 By.directive(RicSelectorComponent)
291 const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
292 By.directive(TypedPolicyEditorComponent)
294 let submitButton: MatButtonHarness = await loader.getHarness(
295 MatButtonHarness.with({ selector: "#submitButton" })
298 typedPolicyEditor.validJson.emit(null);
299 expect(await submitButton.isDisabled()).toBeTruthy();
301 ricSelector.selectedRic.emit("ric1");
302 expect(await submitButton.isDisabled()).toBeTruthy();
304 typedPolicyEditor.validJson.emit("{}");
305 expect(await submitButton.isDisabled()).toBeFalsy();
309 describe("content when editing policy without type", () => {
310 const instanceJson = JSON.parse('{"qosObjectives": {"priorityLevel": 3100}}');
311 beforeEach(async () => {
313 createSchema: untypedSchema,
314 instanceId: "instanceId",
315 instanceJson: instanceJson,
318 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
319 ({ fixture, component, loader } = compileAndGetComponents(
324 jasmine.addCustomEqualityTester(policyTester);
327 it("should contain oran logo and instance info", async () => {
328 let ele = fixture.debugElement.nativeElement.querySelector("img");
329 expect(ele.src).toContain("assets/oran-logo.png");
331 ele = fixture.debugElement.nativeElement.querySelector("text");
332 expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
334 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
335 expect(ele).toBeTruthy();
336 expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
339 it("should not contain ric select", async () => {
340 const ricSelector = fixture.debugElement.query(
341 By.directive(RicSelectorComponent)
343 expect(ricSelector).toBeFalsy();
346 it("should contain json editor with json data", async () => {
347 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
348 By.directive(NoTypePolicyEditorComponent)
350 expect(noTypePolicyEditor).toBeTruthy();
351 expect(noTypePolicyEditor.policyJson).toEqual(
356 it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
357 let closeButton: MatButtonHarness = await loader.getHarness(
358 MatButtonHarness.with({ selector: "#closeButton" })
360 expect(await closeButton.isDisabled()).toBeFalsy();
361 expect(await closeButton.getText()).toEqual("Close");
363 let submitButton: MatButtonHarness = await loader.getHarness(
364 MatButtonHarness.with({ selector: "#submitButton" })
366 expect(await submitButton.isDisabled()).toBeFalsy();
367 expect(await submitButton.getText()).toEqual("Submit");
370 it("should submit policy with correct data, close dialog and notify user about success", async () => {
371 policyServiceSpy.putPolicy.and.returnValue(of("ok"));
372 let submitButton: MatButtonHarness = await loader.getHarness(
373 MatButtonHarness.with({ selector: "#submitButton" })
376 await submitButton.click();
378 const policyInstance = {} as CreatePolicyInstance;
379 policyInstance.policy_data = instanceJson;
380 policyInstance.policy_id = "instanceId";
381 policyInstance.ric_id = "ric1";
382 policyInstance.service_id = "controlpanel";
383 expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance);
385 expect(dialogRefSpy.close).toHaveBeenCalled();
386 expect(notificationServiceSpy.success).toHaveBeenCalledWith(
387 "Policy instanceId submitted"
392 describe("content when editing policy with type", () => {
393 const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}';
394 beforeEach(async () => {
396 createSchema: typedSchema,
397 instanceId: "instanceId",
398 instanceJson: instanceJson,
402 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
403 ({ fixture, component, loader } = compileAndGetComponents(
410 it("should contain oran logo and instance info", async () => {
411 let ele = fixture.debugElement.nativeElement.querySelector("img");
412 expect(ele.src).toContain("assets/oran-logo.png");
414 ele = fixture.debugElement.nativeElement.querySelector("text");
415 expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
417 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
418 expect(ele).toBeTruthy();
419 expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
422 it("should not contain ric select", async () => {
423 const ricSelector = fixture.debugElement.query(
424 By.directive(RicSelectorComponent)
426 expect(ricSelector).toBeFalsy();
429 it("should contain typed json editor with instance JSON, schema and dark mode true", async () => {
430 const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
431 By.directive(TypedPolicyEditorComponent)
433 expect(typedPolicyEditor).toBeTruthy();
434 expect(unescapeQuotes(typedPolicyEditor.jsonObject)).toEqual(
437 expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema);
438 expect(typedPolicyEditor.darkMode).toBeTruthy();
441 it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
442 let closeButton: MatButtonHarness = await loader.getHarness(
443 MatButtonHarness.with({ selector: "#closeButton" })
445 expect(await closeButton.isDisabled()).toBeFalsy();
446 expect(await closeButton.getText()).toEqual("Close");
448 let submitButton: MatButtonHarness = await loader.getHarness(
449 MatButtonHarness.with({ selector: "#submitButton" })
451 expect(await submitButton.isDisabled()).toBeFalsy();
452 expect(await submitButton.getText()).toEqual("Submit");
457 function compileAndGetComponents(
458 fixture: ComponentFixture<PolicyInstanceDialogComponent>,
459 component: PolicyInstanceDialogComponent,
460 loader: HarnessLoader
462 TestBed.compileComponents();
464 fixture = TestBed.createComponent(PolicyInstanceDialogComponent);
465 component = fixture.componentInstance;
466 fixture.detectChanges();
467 loader = TestbedHarnessEnvironment.loader(fixture);
468 return { fixture, component, loader };
471 function unescapeQuotes(string: string): string {
472 return string.replace(/\\"/g, '"');
475 function policyTester(first, second) {
476 if (typeof first[0] === "object" && typeof second[0] === "object") {
477 const policy1 = first[0] as CreatePolicyInstance;
478 const policy2 = second[0] as CreatePolicyInstance;
480 typeof policy1.policy_data === "object" &&
481 typeof policy2.policy_data === "object" &&
482 JSON.stringify(policy1.policy_data) === JSON.stringify(policy2.policy_data) &&
483 policy1.policy_id === policy2.policy_id &&
484 policy1.policytype_id === policy2.policytype_id &&
485 policy1.ric_id === policy2.ric_id &&
486 policy1.service_id === policy2.service_id