Fix PolicyInstanceDialogComponent 69/5769/2
authorelinuxhenrik <henrik.b.andersson@est.tech>
Tue, 16 Mar 2021 12:55:28 +0000 (13:55 +0100)
committerelinuxhenrik <henrik.b.andersson@est.tech>
Tue, 16 Mar 2021 15:53:54 +0000 (16:53 +0100)
Also change the syubs to provide policy without type.

Change-Id: I33d4088533e2c5087a20dd868bf88d6487297a71
Signed-off-by: elinuxhenrik <henrik.b.andersson@est.tech>
Issue-ID: NONRTRIC-463

webapp-frontend/src/app/interceptor.mock.ts
webapp-frontend/src/app/mock/no-type-policies.json [new file with mode: 0644]
webapp-frontend/src/app/mock/policy-instance-notype.json
webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.spec.ts
webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.html
webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.spec.ts
webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.ts
webapp-frontend/src/app/policy/typed-policy-editor/typed-policy-editor.component.spec.ts
webapp-frontend/src/app/policy/typed-policy-editor/typed-policy-editor.component.ts

index 29bcf6a..749d762 100644 (file)
 import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
 import { Injectable, Injector } from '@angular/core';
 import { Observable, of } from 'rxjs';
-import * as policyinstances1 from './mock/policy-instance-1.json';
-import * as policies from './mock/policies.json';
-import * as policyinstances2 from './mock/policy-instance-2.json';
-import * as policyinstances1Status from './mock/policy-instance-1-status.json';
-import * as policyinstances2Status from './mock/policy-instance-2-status.json';
+import * as policyinstance1 from './mock/policy-instance-1.json';
+import * as noTypePolicies from './mock/no-type-policies.json';
+import * as typedPolicies from './mock/policies.json';
+import * as policyinstance2 from './mock/policy-instance-2.json';
+import * as noTypePolicyinstance from './mock/policy-instance-notype.json';
+import * as policyinstance1Status from './mock/policy-instance-1-status.json';
+import * as policyinstance2Status from './mock/policy-instance-2-status.json';
 import * as eijobsProd1 from './mock/ei-jobs-producer1.json';
 import * as eijobsProd2 from './mock/ei-jobs-producer2.json';
 import * as eiProducerIds from './mock/ei-producerids.json';
@@ -54,27 +56,35 @@ const urls = [
     },
     {
         url: '/a1-policy/v2/policies?policytype_id=',
-        json: policies
+        json: noTypePolicies
     },
     {
         url: '/a1-policy/v2/policies?policytype_id=1',
-        json: policies
+        json: typedPolicies
+    },
+    {
+        url: '/a1-policy/v2/policies/2001',
+        json: noTypePolicyinstance
     },
     {
         url: '/a1-policy/v2/policies/2000',
-        json: policyinstances1
+        json: policyinstance1
     },
     {
         url: '/a1-policy/v2/policies/2100',
-        json: policyinstances2
+        json: policyinstance2
+    },
+    {
+        url: '/a1-policy/v2/policies/2001/status',
+        json: policyinstance1Status
     },
     {
         url: '/a1-policy/v2/policies/2000/status',
-        json: policyinstances1Status
+        json: policyinstance1Status
     },
     {
         url: '/a1-policy/v2/policies/2100/status',
-        json: policyinstances2Status
+        json: policyinstance2Status
     },
     {
         url: '/a1-policy/v2/policies/2000?type=',
diff --git a/webapp-frontend/src/app/mock/no-type-policies.json b/webapp-frontend/src/app/mock/no-type-policies.json
new file mode 100644 (file)
index 0000000..6f00441
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "policy_ids": [
+    "2001"
+  ]
+}
\ No newline at end of file
index 7c91060..a3d95e7 100644 (file)
@@ -1,18 +1,17 @@
-[
-    {
-      "id": "2001",
-      "type": "",
-      "ric": "ric1",
-      "json": {
-        "scope": {
-          "ueId": "ue3100",
-          "qosId": "qos3100"
-        },
-        "qosObjectives": {
-          "priorityLevel": 3100
-        }
-      },
-      "service": "service1",
-      "lastModified": "2020-12-08T21:12:43.719084Z"
+{
+  "policy_id": "2001",
+  "policytype_id": "",
+  "ric_id": "ric1",
+  "policy_data": {
+    "scope": {
+      "ueId": "ue3200",
+      "qosId": "qos3200"
+    },
+    "qosObjectives": {
+      "priorityLevel": 3100
     }
-  ]
\ No newline at end of file
+  },
+  "service_id": "service1",
+  "transient": false,
+  "status_notification_uri": ""
+}
\ No newline at end of file
index 529caee..fb3a6a6 100644 (file)
 //   ========================LICENSE_END===================================
 //
 
-import { HarnessLoader } from '@angular/cdk/testing';
-import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
-import { Component, ViewChild, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { FormBuilder, FormGroup } from '@angular/forms';
-import { MatButtonModule } from '@angular/material/button';
-import { MatButtonHarness } from '@angular/material/button/testing';
-import { MatFormFieldModule } from '@angular/material/form-field';
-import { MatInputModule } from '@angular/material/input';
-import { MatInputHarness } from '@angular/material/input/testing';
-import { BrowserModule } from '@angular/platform-browser';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { HarnessLoader } from "@angular/cdk/testing";
+import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed";
+import { Component, ViewChild, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { FormBuilder, FormGroup } from "@angular/forms";
+import { MatButtonModule } from "@angular/material/button";
+import { MatButtonHarness } from "@angular/material/button/testing";
+import { MatFormFieldModule } from "@angular/material/form-field";
+import { MatInputModule } from "@angular/material/input";
+import { MatInputHarness } from "@angular/material/input/testing";
+import { BrowserModule } from "@angular/platform-browser";
+import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 
-import { NoTypePolicyEditorComponent } from './no-type-policy-editor.component';
+import { NoTypePolicyEditorComponent } from "./no-type-policy-editor.component";
 
-describe('NoTypePolicyEditorComponent', () => {
+describe("NoTypePolicyEditorComponent", () => {
   let formGroup: FormGroup = new FormGroup({});
 
   let component: TestNoTypePolicyEditorComponentHostComponent;
@@ -47,65 +47,74 @@ describe('NoTypePolicyEditorComponent', () => {
         BrowserAnimationsModule,
         MatButtonModule,
         MatFormFieldModule,
-        MatInputModule
-      ],
-      schemas: [
-        CUSTOM_ELEMENTS_SCHEMA
+        MatInputModule,
       ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
       declarations: [
         NoTypePolicyEditorComponent,
-        TestNoTypePolicyEditorComponentHostComponent
+        TestNoTypePolicyEditorComponentHostComponent,
       ],
-      providers: [
-        FormBuilder
-      ]
-    })
-    .compileComponents();
+      providers: [FormBuilder],
+    }).compileComponents();
 
-    fixture = TestBed.createComponent(TestNoTypePolicyEditorComponentHostComponent);
+    fixture = TestBed.createComponent(
+      TestNoTypePolicyEditorComponentHostComponent
+    );
     component = fixture.componentInstance;
     fixture.detectChanges();
     loader = TestbedHarnessEnvironment.loader(fixture);
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 
-  it('should be added to form group with required validator', async () => {
-    let textArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({ selector: '#policyJsonTextArea' }));
+  it("should be added to form group with required validator", async () => {
+    let textArea: MatInputHarness = await loader.getHarness(
+      MatInputHarness.with({ selector: "#policyJsonTextArea" })
+    );
 
-    expect(formGroup.get('policyJsonTextArea')).toBeTruthy();
+    expect(formGroup.get("policyJsonTextArea")).toBeTruthy();
     expect(await textArea.isRequired()).toBeTruthy();
   });
 
-  it('should contain provided policy json and enabled Format button', async () => {
-    let textArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({ selector: '#policyJsonTextArea' }));
+  it("should contain provided policy json and enabled Format button", async () => {
+    let textArea: MatInputHarness = await loader.getHarness(
+      MatInputHarness.with({ selector: "#policyJsonTextArea" })
+    );
     expect(await textArea.getValue()).toEqual('{"A":"A"}');
 
-    console.log('Validity:',formGroup.valid);
-    let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({ selector: '#formatButton' }));
+    let formatButton: MatButtonHarness = await loader.getHarness(
+      MatButtonHarness.with({ selector: "#formatButton" })
+    );
     expect(await formatButton.isDisabled()).toBeFalsy();
   });
 
-  it('Format button should be disabled when json not valid', async () => {
-    const ele = formGroup.get('policyJsonTextArea');
-    ele.setValue('{');
+  it("Format button should be disabled when json not valid", async () => {
+    const ele = formGroup.get("policyJsonTextArea");
+    ele.setValue("{");
 
-    let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({ selector: '#formatButton' }));
+    let formatButton: MatButtonHarness = await loader.getHarness(
+      MatButtonHarness.with({ selector: "#formatButton" })
+    );
     expect(await formatButton.isDisabled()).toBeTruthy();
   });
 
-  it('should format unformatted json', async () => {
-    const textArea = formGroup.get('policyJsonTextArea');
+  it("should format unformatted json", async () => {
+    const textArea = formGroup.get("policyJsonTextArea");
     textArea.setValue('{"A":"A"}');
     component.noTypePolicyEditorComponent.formatJsonInput();
-    expect(component.noTypePolicyEditorComponent.policyJson).toEqual('{\n  "A": "A"\n}');
+    expect(component.noTypePolicyEditorComponent.policyJson).toEqual(
+      '{\n  "A": "A"\n}'
+    );
   });
 
   @Component({
     selector: `no-type-policy-editor-host-component`,
-    template: `<nrcp-no-type-policy-editor [policyJson]="this.policyJson" [instanceForm]="instanceForm"></nrcp-no-type-policy-editor>`
+    template: `<nrcp-no-type-policy-editor
+      [policyJson]="this.policyJson"
+      [instanceForm]="instanceForm"
+    ></nrcp-no-type-policy-editor>`,
   })
   class TestNoTypePolicyEditorComponentHostComponent {
     @ViewChild(NoTypePolicyEditorComponent)
index df4c1cf..6e79e78 100644 (file)
@@ -27,7 +27,9 @@
         <svg class="logo__icon" viewBox="150.3 22.2 1000 50">
             <text class="logo__text" [ngClass]="{'logo__text-dark': darkMode}" font-size="30" font-weight="600"
                 letter-spacing=".1em" transform="translate(149 56)">
-                <tspan *ngIf="!this.policyInstanceId">Create new policy instance of type {{policyTypeName}}</tspan>
+                <tspan *ngIf="!this.policyInstanceId">Create new policy instance of type </tspan>
+                <tspan *ngIf="policyTypeName">{{policyTypeName}}</tspan>
+                <tspan *ngIf="!policyTypeName">&lt; No Type &gt;</tspan>
             </text>
         </svg>
     </div>
     fxLayoutAlign.lt-sm="flex-start center">
 
     <mat-card class="card" [ngClass]="{'card-dark': darkMode}">
-        <nrcp-ric-selector *ngIf="!policyInstanceId" [instanceForm]="instanceForm"></nrcp-ric-selector>
+        <nrcp-ric-selector *ngIf="!policyInstanceId" [instanceForm]="instanceForm" [policyTypeName]="policyTypeName"></nrcp-ric-selector>
         <h4 *ngIf="!typeHasSchema()">
             Properties
         </h4>
-        <nrcp-no-type-policy-editor *ngIf="!typeHasSchema()" [policyJson]="policyJson" [instanceForm]="instanceForm"></nrcp-no-type-policy-editor>
+        <nrcp-no-type-policy-editor *ngIf="!typeHasSchema()" [instanceForm]="instanceForm" [policyJson]="policyJson"></nrcp-no-type-policy-editor>
         <nrcp-typed-policy-editor *ngIf="typeHasSchema()" [jsonSchemaObject]="jsonSchemaObject" [jsonObject]="policyJson" [darkMode]="darkMode"></nrcp-typed-policy-editor>
         <div mat-dialog-actions>
             <button id="closeButton"  mat-raised-button [mat-dialog-close]="false">Close</button>
index e8038ed..b4c2732 100644 (file)
@@ -30,7 +30,13 @@ import {
 } from "@angular/material/dialog";
 import { MatSelectModule } from "@angular/material/select";
 import { MatInputModule } from "@angular/material/input";
-import { AbstractControl, ReactiveFormsModule } from "@angular/forms";
+import {
+  AbstractControl,
+  FormControl,
+  FormGroup,
+  ReactiveFormsModule,
+  Validators,
+} from "@angular/forms";
 import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed";
 import { ToastrModule } from "ngx-toastr";
 
@@ -42,26 +48,17 @@ import {
   ChangeDetectorRef,
   Component,
   CUSTOM_ELEMENTS_SCHEMA,
+  Input,
 } 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 { By } from "@angular/platform-browser";
 
 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<PolicyInstanceDialogComponent>;
@@ -106,7 +103,7 @@ describe("PolicyInstanceDialogComponent", () => {
   describe("content when 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(
@@ -129,22 +126,29 @@ 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 instance form and no policy type", async () => {
+      const ricSelector: RicSelectorComponent = fixture.debugElement.query(By.directive(RicSelectorComponent)).componentInstance;
+      expect(ricSelector).toBeTruthy();
+      expect(ricSelector.instanceForm).toBeTruthy();
+      expect(ricSelector.policyTypeName).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 instance form and empty JSON", async () => {
+      const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(By.directive(NoTypePolicyEditorComponent)).componentInstance;
+      expect(noTypePolicyEditor).toBeTruthy();
+      expect(noTypePolicyEditor.instanceForm).toBeTruthy();
+      expect(noTypePolicyEditor.policyJson).toEqual("{}");
     });
 
     it("should contain enabled Close button and disabled Submit button", async () => {
       component.ngOnInit();
+      // Add an empty value with required validator to set the dialog's instance form to be invalid.
+      const value: any = null;
+      component.instanceForm.addControl(
+        "dummy",
+        new FormControl(value, [Validators.required])
+      );
+      expect(component.instanceForm.valid).toBeFalsy();
 
       let closeButton: MatButtonHarness = await loader.getHarness(
         MatButtonHarness.with({ selector: "#closeButton" })
@@ -155,7 +159,7 @@ describe("PolicyInstanceDialogComponent", () => {
       let submitButton: MatButtonHarness = await loader.getHarness(
         MatButtonHarness.with({ selector: "#submitButton" })
       );
-      // expect(await submitButton.isDisabled()).toBeTruthy();
+      expect(await submitButton.isDisabled()).toBeTruthy();
       expect(await submitButton.getText()).toEqual("Submit");
     });
   });
@@ -164,7 +168,7 @@ describe("PolicyInstanceDialogComponent", () => {
     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,22 +191,30 @@ 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 instance form and provided policy type", async () => {
+      const ricSelector: RicSelectorComponent = fixture.debugElement.query(By.directive(RicSelectorComponent)).componentInstance;
+      expect(ricSelector).toBeTruthy();
+      expect(ricSelector.instanceForm).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 () => {
       component.ngOnInit();
+      // Add an empty value with required validator to set the dialog's instance form to be invalid.
+      const value: any = null;
+      component.instanceForm.addControl(
+        "dummy",
+        new FormControl(value, [Validators.required])
+      );
+      expect(component.instanceForm.valid).toBeFalsy();
 
       let closeButton: MatButtonHarness = await loader.getHarness(
         MatButtonHarness.with({ selector: "#closeButton" })
@@ -213,17 +225,18 @@ describe("PolicyInstanceDialogComponent", () => {
       let submitButton: MatButtonHarness = await loader.getHarness(
         MatButtonHarness.with({ selector: "#submitButton" })
       );
-      // expect(await submitButton.isDisabled()).toBeTruthy();
+      expect(await submitButton.isDisabled()).toBeTruthy();
       expect(await submitButton.getText()).toEqual("Submit");
     });
   });
 
   describe("content when editing policy without type", () => {
+    const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}';
     beforeEach(async () => {
       const policyData = {
-        createSchema: untypedSchemaObject,
+        createSchema: untypedSchema,
         instanceId: "instanceId",
-        instanceJson: '{"qosObjectives": {"priorityLevel": 3100}}',
+        instanceJson: instanceJson,
         name: "Type 1",
         ric: "ric1",
       };
@@ -248,20 +261,20 @@ describe("PolicyInstanceDialogComponent", () => {
     });
 
     it("should not contain ric select", async () => {
-      const ele = fixture.debugElement.nativeElement.querySelector(
-        "nrcp-ric-selector"
-      );
-      expect(ele).toBeFalsy();
+      const ricSelector = fixture.debugElement.query(By.directive(RicSelectorComponent));
+      expect(ricSelector).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 form and json data", async () => {
+      const noTypePolicyEditor: NoTypePolicyEditorComponent = fixture.debugElement.query(By.directive(NoTypePolicyEditorComponent)).componentInstance;
+      expect(noTypePolicyEditor).toBeTruthy();
+      expect(noTypePolicyEditor.instanceForm).toBeTruthy();
+      expect(unescapeQuotes(noTypePolicyEditor.policyJson)).toEqual('"' + instanceJson + '"');
     });
 
-    it("should contain enabled Close and Submit buttons", async () => {
+    it("should contain enabled Close and Submit buttons when all inputs are valid", async () => {
+      expect(component.instanceForm.valid).toBeTruthy();
+
       let closeButton: MatButtonHarness = await loader.getHarness(
         MatButtonHarness.with({ selector: "#closeButton" })
       );
@@ -277,11 +290,12 @@ describe("PolicyInstanceDialogComponent", () => {
   });
 
   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 +320,21 @@ describe("PolicyInstanceDialogComponent", () => {
     });
 
     it("should not contain ric select", async () => {
-      const ele = fixture.debugElement.nativeElement.querySelector(
-        "nrcp-ric-selector"
-      );
-      expect(ele).toBeFalsy();
+      const ricSelector = fixture.debugElement.query(By.directive(RicSelectorComponent));
+      expect(ricSelector).toBeFalsy();
     });
 
-    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 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(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 () => {
+      expect(component.instanceForm.valid).toBeTruthy();
+
       let closeButton: MatButtonHarness = await loader.getHarness(
         MatButtonHarness.with({ selector: "#closeButton" })
       );
@@ -349,14 +364,24 @@ function compileAndGetComponents(
   return { fixture, component, loader };
 }
 
+function unescapeQuotes(string: string): string {
+  return string.replace(/\\"/g, '"');
+}
+
 @Component({
-  selector: "nrcp-ric-selecor",
+  selector: "nrcp-ric-selector",
   template: "",
   providers: [
-    { provide: RicSelectorComponent, useClass: RicSelectorStubComponent },
+    {
+      provide: RicSelectorComponent,
+      useClass: RicSelectorStubComponent,
+    },
   ],
 })
 class RicSelectorStubComponent {
+  @Input() instanceForm: FormGroup;
+  @Input() policyTypeName: string = "";
+
   get selectedRic(): string {
     return "ric1";
   }
@@ -373,6 +398,9 @@ class RicSelectorStubComponent {
   ],
 })
 class NoTypePolicyEditorStubComponent {
+  @Input() instanceForm: FormGroup;
+  @Input() policyJson: string;
+
   get policyJsonTextArea(): AbstractControl {
     const textArea = { value: "{}" } as AbstractControl;
     return textArea;
@@ -390,6 +418,11 @@ class NoTypePolicyEditorStubComponent {
   ],
 })
 class TypedPolicyEditorStubComponent {
+  @Input() jsonSchemaObject: any = {};
+  @Input() jsonObject: any = {};
+  @Input() darkMode: boolean;
+
+  prettyLiveFormData = '"A": "string"';
   get formIsValid(): boolean {
     return true;
   }
index 3ec5522..096346e 100644 (file)
@@ -80,7 +80,7 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit {
     private ui: UiService
   ) {
     this.policyInstanceId = data.instanceId;
-    this.policyTypeName = data.name ? data.name : "< No Type >";
+    this.policyTypeName = data.name;
     this.policyJson = data.instanceJson;
     this.jsonSchemaObject = data.createSchema;
     this.ric = data.ric;
@@ -138,7 +138,7 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit {
   }
 
   typeHasSchema(): boolean {
-    return this.jsonSchemaObject.schemaObject !== "{}";
+    return this.jsonSchemaObject !== "{}";
   }
 
   isFormValid(): boolean {
index 6c745e3..fc4a166 100644 (file)
 //   ========================LICENSE_END===================================
 //
 
-import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/compiler';
-import { Component } from '@angular/core';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatIconModule } from '@angular/material/icon';
-import { BrowserModule } from '@angular/platform-browser';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/compiler";
+import { Component } from "@angular/core";
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { MatIconModule } from "@angular/material/icon";
+import { BrowserModule } from "@angular/platform-browser";
+import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 
-import { TypedPolicyEditorComponent } from './typed-policy-editor.component';
+import { TypedPolicyEditorComponent } from "./typed-policy-editor.component";
 
-describe('TypedPolicyEditorComponent', () => {
+describe("TypedPolicyEditorComponent", () => {
   let component: TestTypedPolicyEditorComponentHostComponent;
   let fixture: ComponentFixture<TestTypedPolicyEditorComponentHostComponent>;
 
   beforeEach(async () => {
     TestBed.configureTestingModule({
-      imports: [
-        BrowserModule,
-        BrowserAnimationsModule,
-        MatIconModule
-      ],
+      imports: [BrowserModule, BrowserAnimationsModule, MatIconModule],
       declarations: [
         TypedPolicyEditorComponent,
-        TestTypedPolicyEditorComponentHostComponent
+        TestTypedPolicyEditorComponentHostComponent,
       ],
-      schemas: [
-        CUSTOM_ELEMENTS_SCHEMA
-      ]
-    })
-    .compileComponents();
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    }).compileComponents();
   });
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(TestTypedPolicyEditorComponentHostComponent);
+    fixture = TestBed.createComponent(
+      TestTypedPolicyEditorComponentHostComponent
+    );
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 
-  it('should have JSON form visible and JSON and JSON Schema not visible', () => {
-    let propertiesHeading = fixture.debugElement.nativeElement.querySelector('#propertiesHeading');
+  it("should have JSON form visible and JSON and JSON Schema not visible", () => {
+    let propertiesHeading = fixture.debugElement.nativeElement.querySelector(
+      "#propertiesHeading"
+    );
     expect(propertiesHeading).toBeTruthy();
-    expect(propertiesHeading.innerText).toContain('Properties');
-    let propertiesIcon = fixture.debugElement.nativeElement.querySelector('#propertiesIcon');
+    expect(propertiesHeading.innerText).toContain("Properties");
+    let propertiesIcon = fixture.debugElement.nativeElement.querySelector(
+      "#propertiesIcon"
+    );
     expect(propertiesIcon).toBeTruthy();
-    expect(propertiesIcon.innerText).toEqual('expand_less');
-    let jsonForm = fixture.debugElement.nativeElement.querySelector('json-schema-form');
+    expect(propertiesIcon.innerText).toEqual("expand_less");
+    let jsonForm = fixture.debugElement.nativeElement.querySelector(
+      "json-schema-form"
+    );
     expect(jsonForm).toBeTruthy();
 
-    let jsonHeading = fixture.debugElement.nativeElement.querySelector('#jsonHeading');
+    let jsonHeading = fixture.debugElement.nativeElement.querySelector(
+      "#jsonHeading"
+    );
     expect(jsonHeading).toBeTruthy();
-    expect(jsonHeading.innerText).toContain('JSON')
-    let jsonIcon = fixture.debugElement.nativeElement.querySelector('#jsonIcon');
+    expect(jsonHeading.innerText).toContain("JSON");
+    let jsonIcon = fixture.debugElement.nativeElement.querySelector(
+      "#jsonIcon"
+    );
     expect(jsonIcon).toBeTruthy();
-    expect(jsonIcon.innerText).toEqual('expand_more');
-    let jsonDiv = fixture.debugElement.nativeElement.querySelector('#jsonDiv');
+    expect(jsonIcon.innerText).toEqual("expand_more");
+    let jsonDiv = fixture.debugElement.nativeElement.querySelector("#jsonDiv");
     expect(jsonDiv).toBeFalsy();
 
-    let schemaHeading = fixture.debugElement.nativeElement.querySelector('#schemaHeading');
+    let schemaHeading = fixture.debugElement.nativeElement.querySelector(
+      "#schemaHeading"
+    );
     expect(schemaHeading).toBeTruthy();
-    expect(schemaHeading.innerText).toContain('JSON Schema');
-    let schemaIcon = fixture.debugElement.nativeElement.querySelector('#schemaIcon');
+    expect(schemaHeading.innerText).toContain("JSON Schema");
+    let schemaIcon = fixture.debugElement.nativeElement.querySelector(
+      "#schemaIcon"
+    );
     expect(schemaIcon).toBeTruthy();
-    expect(schemaIcon.innerText).toEqual('expand_more');
-    let schemaDiv = fixture.debugElement.nativeElement.querySelector('#schemaDiv');
+    expect(schemaIcon.innerText).toEqual("expand_more");
+    let schemaDiv = fixture.debugElement.nativeElement.querySelector(
+      "#schemaDiv"
+    );
     expect(schemaDiv).toBeFalsy();
   });
 
-  it('should hide JSON form', () => {
-    let propertiesHeading = fixture.debugElement.nativeElement.querySelector('#propertiesHeading');
+  it("should hide JSON form", () => {
+    let propertiesHeading = fixture.debugElement.nativeElement.querySelector(
+      "#propertiesHeading"
+    );
     expect(propertiesHeading).toBeTruthy();
     propertiesHeading.click();
     fixture.detectChanges();
 
-    let propertiesIcon = fixture.debugElement.nativeElement.querySelector('#propertiesIcon');
+    let propertiesIcon = fixture.debugElement.nativeElement.querySelector(
+      "#propertiesIcon"
+    );
     expect(propertiesIcon).toBeTruthy();
-    expect(propertiesIcon.innerText).toEqual('expand_more');
-    let propertiesDiv = fixture.debugElement.nativeElement.querySelector('propertiesDiv');
+    expect(propertiesIcon.innerText).toEqual("expand_more");
+    let propertiesDiv = fixture.debugElement.nativeElement.querySelector(
+      "propertiesDiv"
+    );
     expect(propertiesDiv).toBeFalsy();
   });
 
-  it('should show JSON with text for dark mode', () => {
-    let jsonHeading = fixture.debugElement.nativeElement.querySelector('#jsonHeading');
+  it("should show JSON with text for dark mode", () => {
+    let jsonHeading = fixture.debugElement.nativeElement.querySelector(
+      "#jsonHeading"
+    );
     expect(jsonHeading).toBeTruthy();
     jsonHeading.click();
     fixture.detectChanges();
 
-    let jsonIcon = fixture.debugElement.nativeElement.querySelector('#jsonIcon');
+    let jsonIcon = fixture.debugElement.nativeElement.querySelector(
+      "#jsonIcon"
+    );
     expect(jsonIcon).toBeTruthy();
-    expect(jsonIcon.innerText).toEqual('expand_less');
-    let jsonDiv = fixture.debugElement.nativeElement.querySelector('#jsonDiv');
+    expect(jsonIcon.innerText).toEqual("expand_less");
+    let jsonDiv = fixture.debugElement.nativeElement.querySelector("#jsonDiv");
     expect(jsonDiv).toBeTruthy();
-    let jsonText = jsonDiv.querySelector('pre');
-    expect(jsonText.classList).toContain('text__dark');
+    let jsonText = jsonDiv.querySelector("pre");
+    expect(jsonText.classList).toContain("text__dark");
   });
 
-  it('should show JSON Schema with text for dark mode', () => {
-    let schemaHeading = fixture.debugElement.nativeElement.querySelector('#schemaHeading');
+  it("should show JSON Schema with text for dark mode", () => {
+    let schemaHeading = fixture.debugElement.nativeElement.querySelector(
+      "#schemaHeading"
+    );
     expect(schemaHeading).toBeTruthy();
     schemaHeading.click();
     fixture.detectChanges();
 
-    let schemaIcon = fixture.debugElement.nativeElement.querySelector('#schemaIcon');
+    let schemaIcon = fixture.debugElement.nativeElement.querySelector(
+      "#schemaIcon"
+    );
     expect(schemaIcon).toBeTruthy();
-    expect(schemaIcon.innerText).toEqual('expand_less');
-    let schemaDiv = fixture.debugElement.nativeElement.querySelector('#schemaDiv');
+    expect(schemaIcon.innerText).toEqual("expand_less");
+    let schemaDiv = fixture.debugElement.nativeElement.querySelector(
+      "#schemaDiv"
+    );
     expect(schemaDiv).toBeTruthy();
-    let jsonSchemaText = schemaDiv.querySelector('pre');
-    expect(jsonSchemaText.classList).toContain('text__dark');
+    let jsonSchemaText = schemaDiv.querySelector("pre");
+    expect(jsonSchemaText.classList).toContain("text__dark");
   });
 
   @Component({
     selector: `typed-policy-editor-host-component`,
-    template: `<nrcp-typed-policy-editor [jsonObject]="policyJson" [jsonSchemaObject]="jsonSchemaObject" [darkMode]="true"></nrcp-typed-policy-editor>`
+    template: `<nrcp-typed-policy-editor
+      [jsonObject]="policyJson"
+      [jsonSchemaObject]="jsonSchemaObject"
+      [darkMode]="true"
+    ></nrcp-typed-policy-editor>`,
   })
   class TestTypedPolicyEditorComponentHostComponent {
     policyJson: string = '{"A":"A"}';
-    jsonSchemaObject: string = 'policy_schema": { "$schema": "http://json-schema.org/draft-07/schema#", "description": "Type 1 policy type", "additionalProperties": false, "title": "1", "type": "object", "properties": { "A": "string" }, "required": [ "A" ]}';
+    jsonSchemaObject: string =
+      'policy_schema": { "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "A": "string" }, "required": [ "A" ]}';
   }
 });
index 46b51bf..f9651a4 100644 (file)
@@ -23,95 +23,94 @@ import { Component, Input, OnInit } from '@angular/core';
 import { JsonPointer } from 'angular6-json-schema-form';
 
 @Component({
-    selector: 'nrcp-typed-policy-editor',
-    templateUrl: './typed-policy-editor.component.html',
-    styleUrls: ['./typed-policy-editor.component.scss'],
-    animations: [
-        trigger('expandSection', [
-            state('in', style({ height: '*' })),
-            transition(':enter', [
-                style({ height: 0 }), animate(100),
-            ]),
-            transition(':leave', [
-                style({ height: '*' }),
-                animate(100, style({ height: 0 })),
-            ]),
-        ]),
-    ],
-
+  selector: "nrcp-typed-policy-editor",
+  templateUrl: "./typed-policy-editor.component.html",
+  styleUrls: ["./typed-policy-editor.component.scss"],
+  animations: [
+    trigger("expandSection", [
+      state("in", style({ height: "*" })),
+      transition(":enter", [style({ height: 0 }), animate(100)]),
+      transition(":leave", [
+        style({ height: "*" }),
+        animate(100, style({ height: 0 })),
+      ]),
+    ]),
+  ],
 })
 export class TypedPolicyEditorComponent implements OnInit {
-    jsonFormOptions: any = {
-        addSubmit: false, // Add a submit button if layout does not have one
-        debug: false, // Don't show inline debugging information
-        loadExternalAssets: false, // Load external css and JavaScript for frameworks
-        returnEmptyFields: false, // Don't return values for empty input fields
-        setSchemaDefaults: true, // Always use schema defaults for empty fields
-        defautWidgetOptions: { feedback: true }, // Show inline feedback icons
-    };
+  jsonFormOptions: any = {
+    addSubmit: false, // Add a submit button if layout does not have one
+    debug: false, // Don't show inline debugging information
+    loadExternalAssets: false, // Load external css and JavaScript for frameworks
+    returnEmptyFields: false, // Don't return values for empty input fields
+    setSchemaDefaults: true, // Always use schema defaults for empty fields
+    defautWidgetOptions: { feedback: true }, // Show inline feedback icons
+  };
 
-    @Input() jsonSchemaObject: any = {};
-    @Input() jsonObject: any = {};
-    @Input() darkMode: boolean;
+  @Input() jsonSchemaObject: any = {};
+  @Input() jsonObject: any = {};
+  @Input() darkMode: boolean;
 
-    isVisible = {
-        form: true,
-        json: false,
-        schema: false
-    };
-    liveFormData: any = {};
-    formIsValid: boolean = false;
-    formValidationErrors: any;
+  isVisible = {
+    form: true,
+    json: false,
+    schema: false,
+  };
+  liveFormData: any = {};
+  formIsValid: boolean = false;
+  formValidationErrors: any;
 
-    constructor() {}
+  constructor() {}
 
-    ngOnInit(): void {}
+  ngOnInit(): void {}
 
-    public onChanges(formData: any) {
-        this.liveFormData = formData;
-    }
+  public onChanges(formData: any) {
+    this.liveFormData = formData;
+  }
 
-    get prettyLiveFormData(): string {
-        return JSON.stringify(this.liveFormData, null, 2);
-    }
+  get prettyLiveFormData(): string {
+    return JSON.stringify(this.liveFormData, null, 2);
+  }
 
-    get schemaAsString(): string {
-        return JSON.stringify(this.jsonSchemaObject, null, 2);
-    }
+  get schemaAsString(): string {
+    return JSON.stringify(this.jsonSchemaObject, null, 2);
+  }
 
-    get jsonAsString(): string {
-        return JSON.stringify(this.jsonObject, null, 2);
-    }
+  get jsonAsString(): string {
+    return JSON.stringify(this.jsonObject, null, 2);
+  }
 
-    isValid(isValid: boolean): void {
-        this.formIsValid = isValid;
-    }
+  isValid(isValid: boolean): void {
+    this.formIsValid = isValid;
+  }
 
-    validationErrors(validationErrors: any): void {
-        this.formValidationErrors = validationErrors;
-    }
+  validationErrors(validationErrors: any): void {
+    this.formValidationErrors = validationErrors;
+  }
 
-    get prettyValidationErrors() {
-        if (!this.formValidationErrors) { return null; }
-        const errorArray = [];
-        for (const error of this.formValidationErrors) {
-            const message = error.message;
-            const dataPathArray = JsonPointer.parse(error.dataPath);
-            if (dataPathArray.length) {
-                let field = dataPathArray[0];
-                for (let i = 1; i < dataPathArray.length; i++) {
-                    const key = dataPathArray[i];
-                    field += /^\d+$/.test(key) ? `[${key}]` : `.${key}`;
-                }
-                errorArray.push(`${field}: ${message}`);
-            } else {
-                errorArray.push(message);
-            }
+  get prettyValidationErrors() {
+    if (!this.formValidationErrors) {
+      return null;
+    }
+    const errorArray = [];
+    for (const error of this.formValidationErrors) {
+      const message = error.message;
+      const dataPathArray = JsonPointer.parse(error.dataPath);
+      if (dataPathArray.length) {
+        let field = dataPathArray[0];
+        for (let i = 1; i < dataPathArray.length; i++) {
+          const key = dataPathArray[i];
+          field += /^\d+$/.test(key) ? `[${key}]` : `.${key}`;
         }
-        return errorArray.join('<br>');
+        errorArray.push(`${field}: ${message}`);
+      } else {
+        errorArray.push(message);
+      }
     }
+    return errorArray.join("<br>");
+  }
 
-    public toggleVisible(item: string) {
-        this.isVisible[item] = !this.isVisible[item];
-    }
+  public toggleVisible(item: string) {
+    this.isVisible[item] = !this.isVisible[item];
+  }
 }