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 = "{}";
55 '{ "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 = "{}";
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 = '{"qosObjectives": {"priorityLevel": 3100}}';
311 beforeEach(async () => {
313 createSchema: untypedSchema,
314 instanceId: "instanceId",
315 instanceJson: instanceJson,
319 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
320 ({ fixture, component, loader } = compileAndGetComponents(
325 jasmine.addCustomEqualityTester(policyTester);
328 it("should contain oran logo and instance info", async () => {
329 let ele = fixture.debugElement.nativeElement.querySelector("img");
330 expect(ele.src).toContain("assets/oran-logo.png");
332 ele = fixture.debugElement.nativeElement.querySelector("text");
333 expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
335 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
336 expect(ele).toBeTruthy();
337 expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
340 it("should not contain ric select", async () => {
341 const ricSelector = fixture.debugElement.query(
342 By.directive(RicSelectorComponent)
344 expect(ricSelector).toBeFalsy();
347 it("should contain json editor with json data", async () => {
348 const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
349 By.directive(NoTypePolicyEditorComponent)
351 expect(noTypePolicyEditor).toBeTruthy();
352 expect(unescapeQuotes(noTypePolicyEditor.policyJson)).toEqual(
357 it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
358 let closeButton: MatButtonHarness = await loader.getHarness(
359 MatButtonHarness.with({ selector: "#closeButton" })
361 expect(await closeButton.isDisabled()).toBeFalsy();
362 expect(await closeButton.getText()).toEqual("Close");
364 let submitButton: MatButtonHarness = await loader.getHarness(
365 MatButtonHarness.with({ selector: "#submitButton" })
367 expect(await submitButton.isDisabled()).toBeFalsy();
368 expect(await submitButton.getText()).toEqual("Submit");
371 it("should submit policy with correct data, close dialog and notify user about success", async () => {
372 policyServiceSpy.putPolicy.and.returnValue(of("ok"));
373 let submitButton: MatButtonHarness = await loader.getHarness(
374 MatButtonHarness.with({ selector: "#submitButton" })
377 await submitButton.click();
379 const policyInstance = {} as CreatePolicyInstance;
380 policyInstance.policy_data = instanceJson;
381 policyInstance.policy_id = "instanceId";
382 policyInstance.ric_id = "ric1";
383 policyInstance.service_id = "controlpanel";
384 expect(policyServiceSpy.putPolicy).toHaveBeenCalledWith(policyInstance);
386 expect(dialogRefSpy.close).toHaveBeenCalled();
387 expect(notificationServiceSpy.success).toHaveBeenCalledWith(
388 "Policy instanceId submitted"
393 describe("content when editing policy with type", () => {
394 const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}';
395 beforeEach(async () => {
397 createSchema: typedSchema,
398 instanceId: "instanceId",
399 instanceJson: instanceJson,
403 TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
404 ({ fixture, component, loader } = compileAndGetComponents(
411 it("should contain oran logo and instance info", async () => {
412 let ele = fixture.debugElement.nativeElement.querySelector("img");
413 expect(ele.src).toContain("assets/oran-logo.png");
415 ele = fixture.debugElement.nativeElement.querySelector("text");
416 expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
418 ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
419 expect(ele).toBeTruthy();
420 expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
423 it("should not contain ric select", async () => {
424 const ricSelector = fixture.debugElement.query(
425 By.directive(RicSelectorComponent)
427 expect(ricSelector).toBeFalsy();
430 it("should contain typed json editor with instance JSON, schema and dark mode true", async () => {
431 const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
432 By.directive(TypedPolicyEditorComponent)
434 expect(typedPolicyEditor).toBeTruthy();
435 expect(unescapeQuotes(typedPolicyEditor.jsonObject)).toEqual(
438 expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema);
439 expect(typedPolicyEditor.darkMode).toBeTruthy();
442 it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
443 let closeButton: MatButtonHarness = await loader.getHarness(
444 MatButtonHarness.with({ selector: "#closeButton" })
446 expect(await closeButton.isDisabled()).toBeFalsy();
447 expect(await closeButton.getText()).toEqual("Close");
449 let submitButton: MatButtonHarness = await loader.getHarness(
450 MatButtonHarness.with({ selector: "#submitButton" })
452 expect(await submitButton.isDisabled()).toBeFalsy();
453 expect(await submitButton.getText()).toEqual("Submit");
458 function compileAndGetComponents(
459 fixture: ComponentFixture<PolicyInstanceDialogComponent>,
460 component: PolicyInstanceDialogComponent,
461 loader: HarnessLoader
463 TestBed.compileComponents();
465 fixture = TestBed.createComponent(PolicyInstanceDialogComponent);
466 component = fixture.componentInstance;
467 fixture.detectChanges();
468 loader = TestbedHarnessEnvironment.loader(fixture);
469 return { fixture, component, loader };
472 function unescapeQuotes(string: string): string {
473 return string.replace(/\\"/g, '"');
476 function policyTester(first, second) {
477 if (typeof first === "object" && typeof second === "object") {
478 const policy1 = first as CreatePolicyInstance;
479 const policy2 = second as CreatePolicyInstance;
481 policy1.policy_data === policy2.policy_data &&
482 policy1.policy_id === policy2.policy_id &&
483 policy1.policytype_id === policy2.policytype_id &&
484 policy1.ric_id === policy2.ric_id &&
485 policy1.service_id === policy2.service_id