Clean up and format
[portal/nonrtric-controlpanel.git] / webapp-frontend / src / app / policy / policy-instance-dialog / policy-instance-dialog.component.spec.ts
1 /*-
2  * ========================LICENSE_START=================================
3  * O-RAN-SC
4  * %%
5  * Copyright (C) 2019 Nordix Foundation
6  * %%
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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===================================
19  */
20
21 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
22 import { ComponentFixture, TestBed } from "@angular/core/testing";
23 import { HarnessLoader } from "@angular/cdk/testing";
24 import { MatButtonModule } from "@angular/material/button";
25 import { MatButtonHarness } from "@angular/material/button/testing";
26 import {
27   MatDialogModule,
28   MatDialogRef,
29   MAT_DIALOG_DATA,
30 } from "@angular/material/dialog";
31 import { MatSelectModule } from "@angular/material/select";
32 import { MatInputModule } from "@angular/material/input";
33 import { AbstractControl, ReactiveFormsModule } from "@angular/forms";
34 import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed";
35 import { ToastrModule } from "ngx-toastr";
36
37 import { PolicyService } from "../../services/policy/policy.service";
38 import { ErrorDialogService } from "../../services/ui/error-dialog.service";
39 import { UiService } from "../../services/ui/ui.service";
40 import { PolicyInstanceDialogComponent } from "./policy-instance-dialog.component";
41 import {
42   ChangeDetectorRef,
43   Component,
44   CUSTOM_ELEMENTS_SCHEMA,
45   Input,
46 } from "@angular/core";
47 import { TypedPolicyEditorComponent } from "../typed-policy-editor/typed-policy-editor.component";
48 import { RicSelectorComponent } from "../ric-selector/ric-selector.component";
49 import { NoTypePolicyEditorComponent } from "../no-type-policy-editor/no-type-policy-editor.component";
50 import { By } from "@angular/platform-browser";
51
52 describe("PolicyInstanceDialogComponent", () => {
53   const untypedSchema = "{}";
54   const typedSchema =
55     '{ "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "priorityLevel": "number" }}';
56
57   let component: PolicyInstanceDialogComponent;
58   let fixture: ComponentFixture<PolicyInstanceDialogComponent>;
59   let loader: HarnessLoader;
60   let policyServiceSpy: jasmine.SpyObj<PolicyService>;
61   let errDialogServiceSpy: jasmine.SpyObj<ErrorDialogService>;
62
63   beforeEach(async () => {
64     policyServiceSpy = jasmine.createSpyObj("PolicyService", ["putPolicy"]);
65     errDialogServiceSpy = jasmine.createSpyObj("ErrorDialogService", [
66       "displayError",
67     ]);
68
69     TestBed.configureTestingModule({
70       imports: [
71         BrowserAnimationsModule,
72         MatButtonModule,
73         MatDialogModule,
74         MatInputModule,
75         MatSelectModule,
76         ReactiveFormsModule,
77         ToastrModule.forRoot(),
78       ],
79       schemas: [CUSTOM_ELEMENTS_SCHEMA],
80       declarations: [
81         PolicyInstanceDialogComponent,
82         RicSelectorStubComponent,
83         NoTypePolicyEditorStubComponent,
84         TypedPolicyEditorStubComponent,
85       ],
86       providers: [
87         ChangeDetectorRef,
88         { provide: MatDialogRef, useValue: component },
89         { provide: PolicyService, useValue: policyServiceSpy },
90         { provide: ErrorDialogService, useValue: errDialogServiceSpy },
91         { provide: MAT_DIALOG_DATA, useValue: true },
92         UiService,
93       ],
94     });
95   });
96
97   describe("content when creating policy without type", () => {
98     beforeEach(async () => {
99       const policyData = {
100         createSchema: untypedSchema,
101       };
102       TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
103       ({ fixture, component, loader } = compileAndGetComponents(
104         fixture,
105         component,
106         loader
107       ));
108     });
109
110     it("should contain oran logo and create title and no instance info", async () => {
111       let ele = fixture.debugElement.nativeElement.querySelector("img");
112       expect(ele.src).toContain("assets/oran-logo.png");
113
114       ele = fixture.debugElement.nativeElement.querySelector("text");
115       expect(ele.textContent).toEqual(
116         "Create new policy instance of type < No Type >"
117       );
118
119       ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
120       expect(ele).toBeFalsy();
121     });
122
123     it("should contain ric select with no policy type", async () => {
124       const ricSelector: RicSelectorComponent = fixture.debugElement.query(
125         By.directive(RicSelectorComponent)
126       ).componentInstance;
127       expect(ricSelector).toBeTruthy();
128       expect(ricSelector.policyTypeName).toBeFalsy();
129     });
130
131     it("should contain json editor with empty JSON", async () => {
132       const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
133         By.directive(NoTypePolicyEditorComponent)
134       ).componentInstance;
135       expect(noTypePolicyEditor).toBeTruthy();
136       expect(noTypePolicyEditor.policyJson).toEqual("{}");
137     });
138
139     it("should contain enabled Close button and Submit button", async () => {
140       component.ngOnInit();
141
142       let closeButton: MatButtonHarness = await loader.getHarness(
143         MatButtonHarness.with({ selector: "#closeButton" })
144       );
145       expect(await closeButton.isDisabled()).toBeFalsy();
146       expect(await closeButton.getText()).toEqual("Close");
147
148       let submitButton: MatButtonHarness = await loader.getHarness(
149         MatButtonHarness.with({ selector: "#submitButton" })
150       );
151       expect(await submitButton.getText()).toEqual("Submit");
152     });
153   });
154
155   describe("content when creating policy with type", () => {
156     beforeEach(async () => {
157       const policyData = {
158         name: "Type 1",
159         createSchema: typedSchema,
160       };
161       TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
162       ({ fixture, component, loader } = compileAndGetComponents(
163         fixture,
164         component,
165         loader
166       ));
167     });
168
169     it("should contain oran logo and create title and no instance info", async () => {
170       let ele = fixture.debugElement.nativeElement.querySelector("img");
171       expect(ele.src).toContain("assets/oran-logo.png");
172
173       ele = fixture.debugElement.nativeElement.querySelector("text");
174       expect(ele.textContent).toEqual(
175         "Create new policy instance of type Type 1"
176       );
177
178       ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
179       expect(ele).toBeFalsy();
180     });
181
182     it("should contain ric select with provided policy type", async () => {
183       const ricSelector: RicSelectorComponent = fixture.debugElement.query(
184         By.directive(RicSelectorComponent)
185       ).componentInstance;
186       expect(ricSelector).toBeTruthy();
187       expect(ricSelector.policyTypeName).toEqual("Type 1");
188     });
189
190     it("should contain typed json editor with empty JSON, schema and dark mode true", async () => {
191       const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
192         By.directive(TypedPolicyEditorComponent)
193       ).componentInstance;
194       expect(typedPolicyEditor).toBeTruthy();
195       expect(typedPolicyEditor.jsonObject).toBeFalsy();
196       expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema);
197       expect(typedPolicyEditor.darkMode).toBeTruthy();
198     });
199
200     it("should contain enabled Close button and Submit button", async () => {
201       component.ngOnInit();
202
203       let closeButton: MatButtonHarness = await loader.getHarness(
204         MatButtonHarness.with({ selector: "#closeButton" })
205       );
206       expect(await closeButton.isDisabled()).toBeFalsy();
207       expect(await closeButton.getText()).toEqual("Close");
208
209       let submitButton: MatButtonHarness = await loader.getHarness(
210         MatButtonHarness.with({ selector: "#submitButton" })
211       );
212       expect(await submitButton.getText()).toEqual("Submit");
213     });
214   });
215
216   describe("content when editing policy without type", () => {
217     const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}';
218     beforeEach(async () => {
219       const policyData = {
220         createSchema: untypedSchema,
221         instanceId: "instanceId",
222         instanceJson: instanceJson,
223         name: "Type 1",
224         ric: "ric1",
225       };
226       TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
227       ({ fixture, component, loader } = compileAndGetComponents(
228         fixture,
229         component,
230         loader
231       ));
232     });
233
234     it("should contain oran logo and instance info", async () => {
235       let ele = fixture.debugElement.nativeElement.querySelector("img");
236       expect(ele.src).toContain("assets/oran-logo.png");
237
238       ele = fixture.debugElement.nativeElement.querySelector("text");
239       expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
240
241       ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
242       expect(ele).toBeTruthy();
243       expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
244     });
245
246     it("should not contain ric select", async () => {
247       const ricSelector = fixture.debugElement.query(
248         By.directive(RicSelectorComponent)
249       );
250       expect(ricSelector).toBeFalsy();
251     });
252
253     it("should contain json editor with json data", async () => {
254       const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(
255         By.directive(NoTypePolicyEditorComponent)
256       ).componentInstance;
257       expect(noTypePolicyEditor).toBeTruthy();
258       expect(unescapeQuotes(noTypePolicyEditor.policyJson)).toEqual(
259         '"' + instanceJson + '"'
260       );
261     });
262
263     it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
264       let closeButton: MatButtonHarness = await loader.getHarness(
265         MatButtonHarness.with({ selector: "#closeButton" })
266       );
267       expect(await closeButton.isDisabled()).toBeFalsy();
268       expect(await closeButton.getText()).toEqual("Close");
269
270       let submitButton: MatButtonHarness = await loader.getHarness(
271         MatButtonHarness.with({ selector: "#submitButton" })
272       );
273       expect(await submitButton.isDisabled()).toBeFalsy();
274       expect(await submitButton.getText()).toEqual("Submit");
275     });
276   });
277
278   describe("content when editing policy with type", () => {
279     const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}';
280     beforeEach(async () => {
281       const policyData = {
282         createSchema: typedSchema,
283         instanceId: "instanceId",
284         instanceJson: instanceJson,
285         name: "name",
286         ric: "ric1",
287       };
288       TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
289       ({ fixture, component, loader } = compileAndGetComponents(
290         fixture,
291         component,
292         loader
293       ));
294     });
295
296     it("should contain oran logo and instance info", async () => {
297       let ele = fixture.debugElement.nativeElement.querySelector("img");
298       expect(ele.src).toContain("assets/oran-logo.png");
299
300       ele = fixture.debugElement.nativeElement.querySelector("text");
301       expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
302
303       ele = fixture.debugElement.nativeElement.querySelector("#instanceInfo");
304       expect(ele).toBeTruthy();
305       expect(ele.innerText).toEqual("[ric1] Instance ID: instanceId");
306     });
307
308     it("should not contain ric select", async () => {
309       const ricSelector = fixture.debugElement.query(
310         By.directive(RicSelectorComponent)
311       );
312       expect(ricSelector).toBeFalsy();
313     });
314
315     it("should contain typed json editor with instance JSON, schema and dark mode true", async () => {
316       const typedPolicyEditor: TypedPolicyEditorComponent = fixture.debugElement.query(
317         By.directive(TypedPolicyEditorComponent)
318       ).componentInstance;
319       expect(typedPolicyEditor).toBeTruthy();
320       expect(unescapeQuotes(typedPolicyEditor.jsonObject)).toEqual(
321         instanceJson
322       );
323       expect(typedPolicyEditor.jsonSchemaObject).toEqual(typedSchema);
324       expect(typedPolicyEditor.darkMode).toBeTruthy();
325     });
326
327     it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
328       let closeButton: MatButtonHarness = await loader.getHarness(
329         MatButtonHarness.with({ selector: "#closeButton" })
330       );
331       expect(await closeButton.isDisabled()).toBeFalsy();
332       expect(await closeButton.getText()).toEqual("Close");
333
334       let submitButton: MatButtonHarness = await loader.getHarness(
335         MatButtonHarness.with({ selector: "#submitButton" })
336       );
337       expect(await submitButton.isDisabled()).toBeFalsy();
338       expect(await submitButton.getText()).toEqual("Submit");
339     });
340   });
341 });
342
343 function compileAndGetComponents(
344   fixture: ComponentFixture<PolicyInstanceDialogComponent>,
345   component: PolicyInstanceDialogComponent,
346   loader: HarnessLoader
347 ) {
348   TestBed.compileComponents();
349
350   fixture = TestBed.createComponent(PolicyInstanceDialogComponent);
351   component = fixture.componentInstance;
352   fixture.detectChanges();
353   loader = TestbedHarnessEnvironment.loader(fixture);
354   return { fixture, component, loader };
355 }
356
357 function unescapeQuotes(string: string): string {
358   return string.replace(/\\"/g, '"');
359 }
360
361 @Component({
362   selector: "nrcp-ric-selector",
363   template: "",
364   providers: [
365     {
366       provide: RicSelectorComponent,
367       useClass: RicSelectorStubComponent,
368     },
369   ],
370 })
371 class RicSelectorStubComponent {
372   @Input() policyTypeName: string = "";
373
374   get selectedRic(): string {
375     return "ric1";
376   }
377 }
378
379 @Component({
380   selector: "nrcp-no-type-policy-editor",
381   template: "",
382   providers: [
383     {
384       provide: NoTypePolicyEditorComponent,
385       useClass: NoTypePolicyEditorStubComponent,
386     },
387   ],
388 })
389 class NoTypePolicyEditorStubComponent {
390   @Input() policyJson: string;
391
392   get policyJsonTextArea(): AbstractControl {
393     const textArea = { value: "{}" } as AbstractControl;
394     return textArea;
395   }
396 }
397
398 @Component({
399   selector: "nrcp-typed-policy-editor",
400   template: "",
401   providers: [
402     {
403       provide: TypedPolicyEditorComponent,
404       useClass: TypedPolicyEditorStubComponent,
405     },
406   ],
407 })
408 class TypedPolicyEditorStubComponent {
409   @Input() jsonSchemaObject: any = {};
410   @Input() jsonObject: any = {};
411   @Input() darkMode: boolean;
412
413   prettyLiveFormData = '"A": "string"';
414   get formIsValid(): boolean {
415     return true;
416   }
417 }