Merge "Use of ng-mocks instead of stub"
authorPatrik Buhr <patrik.buhr@est.tech>
Tue, 6 Apr 2021 06:59:53 +0000 (06:59 +0000)
committerGerrit Code Review <gerrit@o-ran-sc.org>
Tue, 6 Apr 2021 06:59:53 +0000 (06:59 +0000)
19 files changed:
webapp-frontend/.vscode/launch.json
webapp-frontend/src/app/interceptor.mock.ts
webapp-frontend/src/app/policy/policy-control.component.html
webapp-frontend/src/app/policy/policy-control.component.spec.ts
webapp-frontend/src/app/policy/policy-control.component.ts
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/policy-instance/policy-instance.component.html
webapp-frontend/src/app/policy/policy-instance/policy-instance.component.spec.ts [new file with mode: 0644]
webapp-frontend/src/app/policy/policy-instance/policy-instance.component.ts
webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts [deleted file]
webapp-frontend/src/app/policy/policy-type/policy-type.component.html
webapp-frontend/src/app/policy/policy-type/policy-type.component.spec.ts
webapp-frontend/src/app/policy/policy-type/policy-type.component.ts
webapp-frontend/src/app/policy/policy-type/policy-type.datasource.spec.ts [deleted file]
webapp-frontend/src/app/policy/policy-type/policy-type.datasource.ts [deleted file]
webapp-frontend/src/app/policy/ric-selector/ric-selector.component.ts
webapp-frontend/src/app/services/policy/policy.service.spec.ts
webapp-frontend/src/app/services/policy/policy.service.ts

index 9d1a541..e432bcb 100644 (file)
@@ -8,6 +8,13 @@
             "url": "http://localhost:4200",
             "webRoot": "${workspaceFolder}"
         },
+        {
+            "type": "chrome",
+            "request": "launch",
+            "name": "Launch Chrome against docker",
+            "url": "http://localhost:8080",
+            "webRoot": "${workspaceFolder}"
+        },
         {
             "type": "chrome",
             "request": "launch",
index 749d762..6fc5c14 100644 (file)
@@ -46,10 +46,6 @@ const urls = [
         url: '/a1-policy/v2/policy-types',
         json: policytypesList
     },
-    {
-        url: '/a1-policy/v2/policy-types/',
-        json: policytypes1
-    },
     {
         url: '/a1-policy/v2/policy-types/1',
         json: policytypes1
index 63f2dab..b9f4c34 100644 (file)
 
   <div fxLayout="row">
     <div class="nrcp-global-page-title">Policy Control</div>
-    <div class="refresh-button">
-        <button mat-icon-button color="primary" (click)="refreshTables()">
-            <mat-icon>refresh</mat-icon>
-        </button>
-    </div>
 </div>
 
 <nrcp-policy-type *ngFor="let policyTypeId of this.policyTypeIds" [policyTypeId]="policyTypeId"></nrcp-policy-type>
index 198305d..05f95db 100644 (file)
  */
 import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
-import { MatDialog } from "@angular/material/dialog";
+import { By } from "@angular/platform-browser";
 import { MatIconModule } from "@angular/material/icon";
 import { MatTableModule } from "@angular/material/table";
 import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
 import { of } from "rxjs";
 
-import { NotificationService } from "@services/ui/notification.service";
 import { PolicyControlComponent } from "./policy-control.component";
-import { PolicyTypeDataSource } from "@policy/policy-type/policy-type.datasource";
-import { UiService } from "@services/ui/ui.service";
-import { PolicyTypeSchema } from "@interfaces/policy.types";
-import { PolicyService } from '../services/policy/policy.service';
+import { PolicyTypes } from "@interfaces/policy.types";
+import { PolicyService } from "@services/policy/policy.service";
+import { MockComponent } from "ng-mocks";
+import { PolicyTypeComponent } from "./policy-type/policy-type.component";
 
 describe("PolicyControlComponent", () => {
   let component: PolicyControlComponent;
   let fixture: ComponentFixture<PolicyControlComponent>;
 
   beforeEach(async(() => {
-    const policyTypeDataSourceSpy = jasmine.createSpyObj(
-      "PolicyTypeDataSource",
-      ["connect", "getPolicyTypes", "disconnect"]
-    );
-    const policyServiceSpy = jasmine.createSpyObj('PolicyService', ['getPolicyTypes']);
-    var policyTypeSchema = {} as PolicyTypeSchema;
-    policyTypeSchema.name = "";
-    policyTypeSchema.schemaObject = "";
-    policyTypeDataSourceSpy.connect.and.returnValue(of([policyTypeSchema]));
-    policyTypeDataSourceSpy.disconnect();
-    policyServiceSpy.getPolicyTypes.and.returnValue(of(["type1"]));
-
-    let matDialogStub: Partial<MatDialog>;
-    let notificationServiceStub: Partial<NotificationService>;
+    const policyServiceSpy = jasmine.createSpyObj("PolicyService", [
+      "getPolicyTypes",
+    ]);
+    const policyTypes = { policytype_ids: ["type1", "type2"] } as PolicyTypes;
+    policyServiceSpy.getPolicyTypes.and.returnValue(of(policyTypes));
 
     TestBed.configureTestingModule({
       imports: [MatIconModule, MatTableModule, BrowserAnimationsModule],
       schemas: [CUSTOM_ELEMENTS_SCHEMA],
-      declarations: [PolicyControlComponent],
-      providers: [
-        { provide : PolicyService, useValue: policyServiceSpy},
-        { provide: PolicyTypeDataSource, useValue: policyTypeDataSourceSpy },
-        { provide: MatDialog, useValue: matDialogStub },
-        { provide: NotificationService, useValue: notificationServiceStub },
-        UiService,
+      declarations: [
+        PolicyControlComponent,
+        MockComponent(PolicyTypeComponent),
       ],
+      providers: [{ provide: PolicyService, useValue: policyServiceSpy }],
     }).compileComponents();
   }));
 
@@ -75,4 +62,14 @@ describe("PolicyControlComponent", () => {
   it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("should contain two PolicyType components instantiated with the correct type", () => {
+    const typeComponents: PolicyTypeComponent[] = fixture.debugElement
+      .queryAll(By.directive(PolicyTypeComponent))
+      .map((component) => component.componentInstance);
+
+    expect(typeComponents.length).toEqual(2);
+    expect(typeComponents[0].policyTypeId).toEqual("type1");
+    expect(typeComponents[1].policyTypeId).toEqual("type2");
+  });
 });
index de3f578..df49c76 100644 (file)
  * limitations under the License.
  * ========================LICENSE_END===================================
  */
-import { animate, state, style, transition, trigger } from '@angular/animations';
-import { Component, OnInit } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
+import { Component, OnInit } from "@angular/core";
 
-import { BehaviorSubject, Observable } from 'rxjs';
-
-import { PolicyTypes, PolicyTypeSchema } from '@interfaces/policy.types';
-import { PolicyTypeDataSource } from './policy-type/policy-type.datasource';
-import { getPolicyDialogProperties } from './policy-instance-dialog/policy-instance-dialog.component';
-import { PolicyInstanceDialogComponent } from './policy-instance-dialog/policy-instance-dialog.component';
-import { UiService } from '@services/ui/ui.service';
-import { PolicyService } from '@services/policy/policy.service';
-import { PolicyTypeComponent } from './policy-type/policy-type.component';
-
-class PolicyTypeInfo {
-    constructor(public type: PolicyTypeSchema) { }
-
-    isExpanded: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
-}
+import { PolicyTypes } from "@interfaces/policy.types";
+import { PolicyService } from "@services/policy/policy.service";
 
 @Component({
-    selector: 'nrcp-policy-control',
-    templateUrl: './policy-control.component.html',
-    styleUrls: ['./policy-control.component.scss'],
-    animations: [
-        trigger('detailExpand', [
-            state('collapsed, void', style({ height: '0px', minHeight: '0', display: 'none' })),
-            state('expanded', style({ height: '*' })),
-            transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
-            transition('expanded <=> void', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
-        ]),
-    ],
+  selector: "nrcp-policy-control",
+  templateUrl: "./policy-control.component.html",
+  styleUrls: ["./policy-control.component.scss"]
 })
 export class PolicyControlComponent implements OnInit {
+  policyTypeIds: Array<string>;
 
-    policyTypeInfo = new Map<string, PolicyTypeInfo>();
-    policyTypeIds: Array<string>;
-    policyTypeComponent = new PolicyTypeComponent(this.policyTypesDataSource);
-    darkMode: boolean;
-
-    constructor(
-        public policyTypesDataSource: PolicyTypeDataSource,
-        private dialog: MatDialog,
-        private policyService: PolicyService,
-        private ui: UiService) { }
-
-    ngOnInit() {
-        this.policyTypesDataSource.getPolicyTypes();
-        this.ui.darkModeState.subscribe((isDark) => {
-            this.darkMode = isDark;
-        });
-        this.policyService.getPolicyTypes().subscribe((policyType: PolicyTypes) => {
-            this.policyTypeIds = policyType.policytype_ids;
-            }
-        );
-    }
-
-    toggleListInstances(policyTypeSchema: PolicyTypeSchema): void {
-        const info = this.getPolicyTypeInfo(policyTypeSchema);
-        info.isExpanded.next(!info.isExpanded.getValue());
-    }
-
-    getPolicyTypeInfo(policyTypeSchema: PolicyTypeSchema): PolicyTypeInfo {
-        let info: PolicyTypeInfo = this.policyTypeInfo.get(policyTypeSchema.name);
-        if (!info) {
-            info = new PolicyTypeInfo(policyTypeSchema);
-            this.policyTypeInfo.set(policyTypeSchema.name, info);
-        }
-        return info;
-    }
-
-    getDisplayName(policyTypeSchema: PolicyTypeSchema): string {
-        if (policyTypeSchema.schemaObject.title) {
-            return policyTypeSchema.schemaObject.title;
-        }
-        return '< No type >';
-    }
-
-    getExpandedObserver(policyTypeSchema: PolicyTypeSchema): Observable<boolean> {
-        return this.getPolicyTypeInfo(policyTypeSchema).isExpanded.asObservable();
-    }
+  constructor(private policyService: PolicyService) {}
 
-    refreshTables() {
-        this.policyTypesDataSource.getPolicyTypes();
-        this.policyTypeComponent.setIsVisible(false);
-    }
+  ngOnInit() {
+    this.policyService.getPolicyTypes().subscribe((policyType: PolicyTypes) => {
+      this.policyTypeIds = policyType.policytype_ids;
+    });
+  }
 }
index b609904..91edaa9 100644 (file)
@@ -50,9 +50,9 @@ import { NotificationService } from "@services/ui/notification.service";
 import * as uuid from "uuid";
 
 describe("PolicyInstanceDialogComponent", () => {
-  const untypedSchema = "{}";
+  const untypedSchema = JSON.parse("{}");
   const typedSchema =
-    '{ "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "priorityLevel": "number" }}';
+    JSON.parse('{ "description": "Type 1 policy type", "title": "1", "type": "object", "properties": { "priorityLevel": "number" }}');
 
   let component: PolicyInstanceDialogComponent;
   let fixture: ComponentFixture<PolicyInstanceDialogComponent>;
@@ -210,13 +210,13 @@ describe("PolicyInstanceDialogComponent", () => {
         MatButtonHarness.with({ selector: "#submitButton" })
       );
 
-      spyOn(uuid, "v4").and.returnValue(1234567890);
+      spyOn(uuid, "v4").and.returnValue("1234567890");
       ricSelector.selectedRic.emit("ric1");
       noTypePolicyEditor.validJson.emit("{}");
       await submitButton.click();
 
       const policyInstance = {} as CreatePolicyInstance;
-      policyInstance.policy_data = "{}";
+      policyInstance.policy_data = JSON.parse("{}");
       policyInstance.policy_id = "1234567890";
       policyInstance.ric_id = "ric1";
       policyInstance.service_id = "controlpanel";
@@ -307,13 +307,12 @@ describe("PolicyInstanceDialogComponent", () => {
   });
 
   describe("content when editing policy without type", () => {
-    const instanceJson = '{"qosObjectives": {"priorityLevel": 3100}}';
+    const instanceJson = JSON.parse('{"qosObjectives": {"priorityLevel": 3100}}');
     beforeEach(async () => {
       const policyData = {
         createSchema: untypedSchema,
         instanceId: "instanceId",
         instanceJson: instanceJson,
-        name: "Type 1",
         ric: "ric1",
       };
       TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
@@ -349,7 +348,7 @@ describe("PolicyInstanceDialogComponent", () => {
         By.directive(NoTypePolicyEditorComponent)
       ).componentInstance;
       expect(noTypePolicyEditor).toBeTruthy();
-      expect(unescapeQuotes(noTypePolicyEditor.policyJson)).toEqual(
+      expect(noTypePolicyEditor.policyJson).toEqual(
         instanceJson
       );
     });
@@ -474,11 +473,13 @@ function unescapeQuotes(string: string): string {
 }
 
 function policyTester(first, second) {
-  if (typeof first === "object" && typeof second === "object") {
-    const policy1 = first as CreatePolicyInstance;
-    const policy2 = second as CreatePolicyInstance;
+  if (typeof first[0] === "object" && typeof second[0] === "object") {
+    const policy1 = first[0] as CreatePolicyInstance;
+    const policy2 = second[0] as CreatePolicyInstance;
     return (
-      policy1.policy_data === policy2.policy_data &&
+      typeof policy1.policy_data === "object" &&
+      typeof policy2.policy_data === "object" &&
+      JSON.stringify(policy1.policy_data) === JSON.stringify(policy2.policy_data) &&
       policy1.policy_id === policy2.policy_id &&
       policy1.policytype_id === policy2.policytype_id &&
       policy1.ric_id === policy2.ric_id &&
index 65d61a6..dbc62a1 100644 (file)
@@ -87,7 +87,7 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit {
   }
 
   onJsonChanged(newJson: string): void {
-    this.policyInstance.policy_data = newJson;
+    this.policyInstance.policy_data = newJson ? JSON.parse(newJson) : null;
   }
 
   onSubmit() {
@@ -110,7 +110,7 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit {
   }
 
   typeHasSchema(): boolean {
-    return this.jsonSchemaObject !== "{}";
+    return this.jsonSchemaObject.description ? true : false;
   }
 
   isFormValid(): boolean {
index 8c9f5c5..e6d483f 100644 (file)
@@ -27,7 +27,7 @@
     </button>
 </div>
 
-<table #table mat-table class="instances-table mat-elevation-z8" [ngClass]="{'table-dark': darkMode}" matSort
+<table #table mat-table class="instances-table mat-elevation-z8" [ngClass]="{'table-dark': darkMode}" matSort (matSortChange)="getSortedData($event)"
     multiTemplateDataRows [dataSource]="instanceDataSource">
 
     <ng-container matColumnDef="instanceId">
         <mat-footer-cell *matFooterCellDef>No records found.</mat-footer-cell>
     </ng-container>
 
-    <mat-header-row *matHeaderRowDef="['instanceId', 'ric', 'service', 'lastModified', 'action']"
-        [ngClass]="{'display-none': !this.hasInstances()}">
+    <mat-header-row *matHeaderRowDef="['instanceId', 'ric', 'service', 'lastModified', 'action']">
     </mat-header-row>
     <mat-row *matRowDef="let instance; columns: ['instanceId', 'ric', 'service', 'lastModified', 'action'];"></mat-row>
-
-    <mat-footer-row *matFooterRowDef="['noRecordsFound']" [ngClass]="{'display-none': this.hasInstances()}">
-    </mat-footer-row>
-
 </table>
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.spec.ts b/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.spec.ts
new file mode 100644 (file)
index 0000000..1260464
--- /dev/null
@@ -0,0 +1,126 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 Nordix Foundation
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================LICENSE_END===================================
+ */
+
+import { Component, ViewChild } from "@angular/core";
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { MatDialog } from "@angular/material/dialog";
+import {
+  PolicyInstance,
+  PolicyInstances,
+  PolicyStatus,
+  PolicyTypeSchema,
+} from "@app/interfaces/policy.types";
+import { PolicyService } from "@app/services/policy/policy.service";
+import { ConfirmDialogService } from "@app/services/ui/confirm-dialog.service";
+import { ErrorDialogService } from "@app/services/ui/error-dialog.service";
+import { NotificationService } from "@app/services/ui/notification.service";
+import { UiService } from "@app/services/ui/ui.service";
+import { ToastrModule } from "ngx-toastr";
+import { of } from "rxjs";
+import { PolicyInstanceComponent } from "./policy-instance.component";
+
+describe("PolicyInstanceComponent", () => {
+  let hostComponent: PolicyInstanceComponentHostComponent;
+  let hostFixture: ComponentFixture<PolicyInstanceComponentHostComponent>;
+  let policyServiceSpy: jasmine.SpyObj<PolicyService>;
+  let dialogSpy: jasmine.SpyObj<MatDialog>;
+
+  @Component({
+    selector: "policy-instance-compnent-host-component",
+    template:
+      "<nrcp-policy-instance [policyTypeSchema]=policyType></nrcp-policy-instance>",
+  })
+  class PolicyInstanceComponentHostComponent {
+    @ViewChild(PolicyInstanceComponent)
+    componentUnderTest: PolicyInstanceComponent;
+    policyTypeSchema = JSON.parse(
+      '{"title": "1", "description": "Type 1 policy type"}'
+    );
+    policyType = {
+      id: "type1",
+      name: "1",
+      schemaObject: this.policyTypeSchema,
+    } as PolicyTypeSchema;
+  }
+
+  beforeEach(async(() => {
+    policyServiceSpy = jasmine.createSpyObj("PolicyService", [
+      "getPolicyInstancesByType",
+      "getPolicyInstance",
+      "getPolicyStatus",
+    ]);
+    let policyInstances = { policy_ids: ["policy1", "policy2"] } as PolicyInstances;
+    policyServiceSpy.getPolicyInstancesByType.and.returnValue(
+      of(policyInstances)
+    );
+    let policy1 = {
+      policy_id: "policy1",
+      policy_data: "{}",
+      ric_id: "1",
+      service_id: "service",
+      lastModified: "Now",
+    } as PolicyInstance;
+    let policy2 = {
+      policy_id: "policy2",
+      policy_data: "{}",
+      ric_id: "2",
+      service_id: "service",
+      lastModified: "Now",
+    } as PolicyInstance;
+    policyServiceSpy.getPolicyInstance.and.returnValues(
+      of(policy1),
+      of(policy2)
+    );
+    let policy1Status = { last_modified: "Just now" } as PolicyStatus;
+    let policy2Status = { last_modified: "Before" } as PolicyStatus;
+    policyServiceSpy.getPolicyStatus.and.returnValues(
+      of(policy1Status),
+      of(policy2Status)
+    );
+
+    dialogSpy = jasmine.createSpyObj("MatDialog", ["open"]);
+
+    TestBed.configureTestingModule({
+      imports: [ToastrModule.forRoot()],
+      declarations: [
+        PolicyInstanceComponent,
+        PolicyInstanceComponentHostComponent,
+      ],
+      providers: [
+        { provide: PolicyService, useValue: policyServiceSpy },
+        { provide: MatDialog, useValue: dialogSpy },
+        ErrorDialogService,
+        NotificationService,
+        ConfirmDialogService,
+        UiService,
+      ],
+    }).compileComponents();
+  }));
+
+  beforeEach(() => {
+    hostFixture = TestBed.createComponent(PolicyInstanceComponentHostComponent);
+    hostComponent = hostFixture.componentInstance;
+    hostFixture.detectChanges();
+  });
+
+  it("should create", () => {
+    expect(hostComponent).toBeTruthy();
+  });
+});
index 24a7cc7..aafc08e 100644 (file)
  * ========================LICENSE_END===================================
  */
 
-import { MatSort, Sort } from '@angular/material/sort';
-import { Component, OnInit, ViewChild, Input, AfterViewInit } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
-import { PolicyTypeSchema } from '@interfaces/policy.types';
-import { PolicyInstanceDataSource } from './policy-instance.datasource';
-import { ErrorDialogService } from '@services/ui/error-dialog.service';
-import { NotificationService } from '@services/ui/notification.service';
-import { PolicyService } from '@services/policy/policy.service';
-import { ConfirmDialogService } from '@services/ui/confirm-dialog.service';
-import { PolicyInstance } from '@interfaces/policy.types';
-import { PolicyInstanceDialogComponent } from '../policy-instance-dialog/policy-instance-dialog.component';
-import { getPolicyDialogProperties } from '../policy-instance-dialog/policy-instance-dialog.component';
-import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
-import { BehaviorSubject, Observable } from 'rxjs';
-import { UiService } from '@services/ui/ui.service';
-import { FormControl, FormGroup } from '@angular/forms';
-import { MatTableDataSource } from '@angular/material/table';
+import { Sort } from "@angular/material/sort";
+import { Component, OnInit, Input } from "@angular/core";
+import { MatDialog } from "@angular/material/dialog";
+import { PolicyTypeSchema } from "@interfaces/policy.types";
+import { ErrorDialogService } from "@services/ui/error-dialog.service";
+import { NotificationService } from "@services/ui/notification.service";
+import { PolicyService } from "@services/policy/policy.service";
+import { ConfirmDialogService } from "@services/ui/confirm-dialog.service";
+import { PolicyInstance } from "@interfaces/policy.types";
+import { PolicyInstanceDialogComponent } from "../policy-instance-dialog/policy-instance-dialog.component";
+import { getPolicyDialogProperties } from "../policy-instance-dialog/policy-instance-dialog.component";
+import { HttpErrorResponse, HttpResponse } from "@angular/common/http";
+import { BehaviorSubject } from "rxjs";
+import { UiService } from "@services/ui/ui.service";
+import { FormControl, FormGroup } from "@angular/forms";
+import { MatTableDataSource } from "@angular/material/table";
 
 class PolicyTypeInfo {
-  constructor(public type: PolicyTypeSchema) { }
+  constructor(public type: PolicyTypeSchema) {}
 
   isExpanded: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
 }
 
 @Component({
-    selector: 'nrcp-policy-instance',
-    templateUrl: './policy-instance.component.html',
-    styleUrls: ['./policy-instance.component.scss']
+  selector: "nrcp-policy-instance",
+  templateUrl: "./policy-instance.component.html",
+  styleUrls: ["./policy-instance.component.scss"],
 })
+export class PolicyInstanceComponent implements OnInit {
+  @Input() policyTypeSchema: PolicyTypeSchema;
+  policyInstances: PolicyInstance[] = [];
+  private policyInstanceSubject = new BehaviorSubject<PolicyInstance[]>([]);
+  policyTypeInfo = new Map<string, PolicyTypeInfo>();
+  instanceDataSource: MatTableDataSource<PolicyInstance> = new MatTableDataSource<PolicyInstance>();
+  policyInstanceForm: FormGroup;
+  darkMode: boolean;
 
+  constructor(
+    private policySvc: PolicyService,
+    private dialog: MatDialog,
+    private errorDialogService: ErrorDialogService,
+    private notificationService: NotificationService,
+    private confirmDialogService: ConfirmDialogService,
+    private ui: UiService
+  ) {
+    this.policyInstanceForm = new FormGroup({
+      id: new FormControl(""),
+      target: new FormControl(""),
+      owner: new FormControl(""),
+      lastModified: new FormControl(""),
+    });
+  }
 
-export class PolicyInstanceComponent implements OnInit, AfterViewInit {
-    policyInstanceDataSource: PolicyInstanceDataSource;
-    @Input() policyTypeSchema: PolicyTypeSchema;
-    @Input() expanded: Observable<boolean>;
-    @ViewChild(MatSort, { static: true }) sort: MatSort;
-    policyTypeInfo = new Map<string, PolicyTypeInfo>();
-    instanceDataSource: MatTableDataSource<PolicyInstance> = new MatTableDataSource<PolicyInstance>();
-    policyInstanceForm: FormGroup;
-    darkMode: boolean;
-
-    constructor(
-        private policySvc: PolicyService,
-        private dialog: MatDialog,
-        private errorDialogService: ErrorDialogService,
-        private notificationService: NotificationService,
-        private confirmDialogService: ConfirmDialogService,
-        private ui: UiService) {
-            this.policyInstanceForm = new FormGroup({
-                id: new FormControl(''),
-                target: new FormControl(''),
-                owner: new FormControl(''),
-                lastModified: new FormControl('')
-            })
-    }
+  ngOnInit() {
+    this.getPolicyInstances();
+    this.policyInstanceSubject.subscribe((data) => {
+      this.instanceDataSource.data = data;
+    });
 
-    ngOnInit() {
-        let schemaId = this.policyTypeSchema.id;
-        if(schemaId.includes('<No Type>')){
-            schemaId = '';
-        }
-        this.policyInstanceDataSource = new PolicyInstanceDataSource(this.policySvc, this.sort, this.notificationService, schemaId);
-        this.expanded.subscribe((isExpanded: boolean) => this.onExpand(isExpanded));
-
-        this.policyInstanceDataSource.connect().subscribe((data) => {
-            this.instanceDataSource.data = data;
-        })
-
-        this.policyInstanceForm.valueChanges.subscribe(value => {
-            const filter = {...value, id: value.id.trim().toLowerCase()} as string;
-            this.instanceDataSource.filter = filter;
-        });
-
-        this.instanceDataSource.filterPredicate = ((data: PolicyInstance, filter) => {
-            return this.isDataIncluding(data.policy_id, filter.id)
-                && this.isDataIncluding(data.ric_id, filter.target)
-                && this.isDataIncluding(data.service_id, filter.owner)
-                && this.isDataIncluding(data.lastModified, filter.lastModified);
-          }) as (data: PolicyInstance, filter: any) => boolean;
-
-        this.ui.darkModeState.subscribe((isDark) => {
-            this.darkMode = isDark;
-        });
-    }
+    this.policyInstanceForm.valueChanges.subscribe((value) => {
+      const filter = { ...value, id: value.id.trim().toLowerCase() } as string;
+      this.instanceDataSource.filter = filter;
+    });
 
-    compare(a: any, b: any, isAsc: boolean) {
-      return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
-    }
+    this.instanceDataSource.filterPredicate = ((
+      data: PolicyInstance,
+      filter
+    ) => {
+      return (
+        this.isDataIncluding(data.policy_id, filter.id) &&
+        this.isDataIncluding(data.ric_id, filter.target) &&
+        this.isDataIncluding(data.service_id, filter.owner) &&
+        this.isDataIncluding(data.lastModified, filter.lastModified)
+      );
+    }) as (data: PolicyInstance, filter: any) => boolean;
 
-    stopSort(event: any){
-        event.stopPropagation();
-    }
+    this.ui.darkModeState.subscribe((isDark) => {
+      this.darkMode = isDark;
+    });
+  }
 
-    isDataIncluding(data: string, filter: string) : boolean {
-        return !filter || data.toLowerCase().includes(filter);
-    }
+  getPolicyInstances() {
+    this.policyInstances = [] as PolicyInstance[];
+    this.policySvc
+    .getPolicyInstancesByType(this.policyTypeSchema.id)
+    .subscribe((policies) => {
+      if (policies.policy_ids.length != 0) {
+        policies.policy_ids.forEach((policyId) => {
+          this.policySvc
+          .getPolicyInstance(policyId)
+          .subscribe((policyInstance) => {
+            this.policySvc
+                  .getPolicyStatus(policyId)
+                  .subscribe((policyStatus) => {
+                    policyInstance.lastModified = policyStatus.last_modified;
+                  });
+                this.policyInstances.push(policyInstance);
+              });
+            this.policyInstanceSubject.next(this.policyInstances);
+          });
+        }
+      });
+  }
 
-    ngAfterViewInit() {
-        this.policyInstanceDataSource.sort = this.sort;
-    }
+  getSortedData(sort: Sort) {
+    const data = this.instanceDataSource.data;
+    data.sort((a, b) => {
+      const isAsc = sort.direction === "asc";
+      switch (sort.active) {
+        case "instanceId":
+          return compare(a.policy_id, b.policy_id, isAsc);
+        case "ric":
+          return compare(a.ric_id, b.ric_id, isAsc);
+        case "service":
+          return compare(a.service_id, b.service_id, isAsc);
+        case "lastModified":
+          return compare(a.lastModified, b.lastModified, isAsc);
+        default:
+          return 0;
+      }
+    });
+    this.instanceDataSource.data = data;
+  }
 
-    private onExpand(isExpanded: boolean) {
-        if (isExpanded) {
-            this.policyInstanceDataSource.getPolicyInstances();
-        }
-    }
+  stopSort(event: any) {
+    event.stopPropagation();
+  }
 
-    private isSchemaEmpty(): boolean {
-        return this.policyTypeSchema.schemaObject === '{}';
-    }
+  isDataIncluding(data: string, filter: string): boolean {
+    return !filter || data.toLowerCase().includes(filter);
+  }
 
-    modifyInstance(instance: PolicyInstance): void {
-        this.policySvc.getPolicyInstance(instance.policy_id).subscribe(
-            (refreshedJson: any) => {
-                instance = refreshedJson;
-                this.dialog.open(
-                    PolicyInstanceDialogComponent,
-                    getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe(
-                        (_: any) => {
-                            this.policyInstanceDataSource.getPolicyInstances();
-                        }
-                    );
-            },
-            (httpError: HttpErrorResponse) => {
-                this.notificationService.error('Could not refresh instance. Please try again.' + httpError.message);
-            }
-        );
+  private onExpand(isExpanded: boolean) {
+    if (isExpanded) {
+      this.getPolicyInstances();
     }
+  }
 
-    hasInstances(): boolean {
-        return this.policyInstanceDataSource.rowCount > 0;
-    }
+  private isSchemaEmpty(): boolean {
+    return this.policyTypeSchema.schemaObject === "{}";
+  }
 
-    nbInstances(): number {
-        return this.policyInstanceDataSource.policyInstances.length;
-    }
+  modifyInstance(instance: PolicyInstance): void {
+    this.policySvc.getPolicyInstance(instance.policy_id).subscribe(
+      (refreshedJson: any) => {
+        instance = refreshedJson;
+        this.dialog
+          .open(
+            PolicyInstanceDialogComponent,
+            getPolicyDialogProperties(
+              this.policyTypeSchema,
+              instance,
+              this.darkMode
+            )
+          )
+          .afterClosed()
+          .subscribe((_: any) => {
+            this.getPolicyInstances();
+          });
+      },
+      (httpError: HttpErrorResponse) => {
+        this.notificationService.error(
+          "Could not refresh instance. Please try again." + httpError.message
+        );
+      }
+    );
+  }
 
-    toLocalTime(utcTime: string): string {
-        const date = new Date(utcTime);
-        const toutc = date.toUTCString();
-        return new Date(toutc + ' UTC').toLocaleString();
+  nbInstances(): number {
+    return this.policyInstances.length;
+  }
 
-    }
+  toLocalTime(utcTime: string): string {
+    const date = new Date(utcTime);
+    const toutc = date.toUTCString();
+    return new Date(toutc + " UTC").toLocaleString();
+  }
 
-    createPolicyInstance(policyTypeSchema: PolicyTypeSchema): void {
-        let dialogRef = this.dialog.open(PolicyInstanceDialogComponent,
-            getPolicyDialogProperties(policyTypeSchema, null, this.darkMode));
-        const info: PolicyTypeInfo = this.getPolicyTypeInfo(policyTypeSchema);
-        dialogRef.afterClosed().subscribe(
-            (_) => {
-                info.isExpanded.next(info.isExpanded.getValue());
+  createPolicyInstance(policyTypeSchema: PolicyTypeSchema): void {
+    let dialogRef = this.dialog.open(
+      PolicyInstanceDialogComponent,
+      getPolicyDialogProperties(policyTypeSchema, null, this.darkMode)
+    );
+    const info: PolicyTypeInfo = this.getPolicyTypeInfo(policyTypeSchema);
+    dialogRef.afterClosed().subscribe((_) => {
+      info.isExpanded.next(info.isExpanded.getValue());
+    });
+  }
+
+  deleteInstance(instance: PolicyInstance): void {
+    this.confirmDialogService
+      .openConfirmDialog(
+        "Are you sure you want to delete this policy instance?"
+      )
+      .afterClosed()
+      .subscribe((res: any) => {
+        if (res) {
+          this.policySvc.deletePolicy(instance.policy_id).subscribe(
+            (response: HttpResponse<Object>) => {
+              switch (response.status) {
+                case 204:
+                  this.notificationService.success("Delete succeeded!");
+                  this.getPolicyInstances();
+                  break;
+                default:
+                  this.notificationService.warn(
+                    "Delete failed " + response.status + " " + response.body
+                  );
+              }
+            },
+            (error: HttpErrorResponse) => {
+              this.errorDialogService.displayError(
+                error.statusText + ", " + error.error
+              );
             }
-        );
-    }
+          );
+        }
+      });
+  }
 
-    deleteInstance(instance: PolicyInstance): void {
-        this.confirmDialogService
-            .openConfirmDialog('Are you sure you want to delete this policy instance?')
-            .afterClosed().subscribe(
-                (res: any) => {
-                    if (res) {
-                        this.policySvc.deletePolicy(instance.policy_id)
-                            .subscribe(
-                                (response: HttpResponse<Object>) => {
-                                    switch (response.status) {
-                                        case 204:
-                                            this.notificationService.success('Delete succeeded!');
-                                            this.policyInstanceDataSource.getPolicyInstances();
-                                            break;
-                                        default:
-                                            this.notificationService.warn('Delete failed ' + response.status + ' ' + response.body);
-                                    }
-                                },
-                                (error: HttpErrorResponse) => {
-                                    this.errorDialogService.displayError(error.statusText + ', ' + error.error);
-                                });
-                    }
-                });
+  getPolicyTypeInfo(policyTypeSchema: PolicyTypeSchema): PolicyTypeInfo {
+    let info: PolicyTypeInfo = this.policyTypeInfo.get(policyTypeSchema.name);
+    if (!info) {
+      info = new PolicyTypeInfo(policyTypeSchema);
+      this.policyTypeInfo.set(policyTypeSchema.name, info);
     }
+    return info;
+  }
 
-    getPolicyTypeInfo(policyTypeSchema: PolicyTypeSchema): PolicyTypeInfo {
-        let info: PolicyTypeInfo = this.policyTypeInfo.get(policyTypeSchema.name);
-        if (!info) {
-            info = new PolicyTypeInfo(policyTypeSchema);
-            this.policyTypeInfo.set(policyTypeSchema.name, info);
-        }
-        return info;
-    }
+  refreshTable() {
+    this.getPolicyInstances();
+  }
+}
 
-    refreshTable() {
-        this.policyInstanceDataSource.getPolicyInstances();
-    }
+function compare(a: string, b: string, isAsc: boolean) {
+  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
 }
diff --git a/webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts b/webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts
deleted file mode 100644 (file)
index 225aabb..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-import { DataSource } from '@angular/cdk/collections';
-import { MatSort } from '@angular/material/sort';
-import { Observable } from 'rxjs/Observable';
-import { BehaviorSubject } from 'rxjs/BehaviorSubject';
-import { merge } from 'rxjs';
-import { map } from 'rxjs/operators';
-import { PolicyInstance } from '@interfaces/policy.types';
-import { PolicyService } from '@services/policy/policy.service';
-import { NotificationService } from '@services/ui/notification.service';
-
-export class PolicyInstanceDataSource extends DataSource<PolicyInstance> {
-
-    policyInstances: PolicyInstance[] = [];
-
-    private policyInstanceSubject = new BehaviorSubject<PolicyInstance[]>([]);
-
-    private loadingSubject = new BehaviorSubject<boolean>(false);
-
-    public loading$ = this.loadingSubject.asObservable();
-
-    public rowCount = 1; // hide footer during intial load
-
-    constructor(
-        private policySvc: PolicyService,
-        public sort: MatSort,
-        private notificationService: NotificationService,
-        private policyTypeSchemaId: string) {
-        super();
-    }
-
-    public getPolicyInstances() {
-        this.policyInstances = [] as PolicyInstance[];
-        this.policySvc.getPolicyInstancesByType(this.policyTypeSchemaId).subscribe(policies => {
-            if (policies.policy_ids.length != 0) {
-                policies.policy_ids.forEach(policyId => {
-                    this.policySvc.getPolicyInstance(policyId).subscribe(policyInstance => {
-                        this.policySvc.getPolicyStatus(policyId).subscribe(policyStatus => {
-                            policyInstance.lastModified = policyStatus.last_modified;
-                        })
-                        this.policyInstances.push(policyInstance);
-                    })
-                    this.policyInstanceSubject.next(this.policyInstances);
-                })
-            }
-        })
-    }
-
-    connect(): Observable<PolicyInstance[]> {
-        const dataMutations = [
-            this.policyInstanceSubject.asObservable(),
-            this.sort.sortChange
-        ];
-        return merge(...dataMutations).pipe(map(() => {
-            return this.getSortedData([...this.policyInstanceSubject.getValue()]);
-        }));
-    }
-
-    disconnect(): void {
-        this.policyInstanceSubject.complete();
-        this.loadingSubject.complete();
-    }
-
-    private getSortedData(data: PolicyInstance[]) {
-        if (!this.sort || !this.sort.active || this.sort.direction === '') {
-            return data;
-        }
-
-        return data.sort((a, b) => {
-            const isAsc = this.sort.direction === 'asc';
-            switch (this.sort.active) {
-                case 'instanceId': return compare(a.policy_id, b.policy_id, isAsc);
-                case 'ric': return compare(a.ric_id, b.ric_id, isAsc);
-                case 'service': return compare(a.service_id, b.service_id, isAsc);
-                case 'lastModified': return compare(a.lastModified, b.lastModified, isAsc);
-                default: return 0;
-            }
-        });
-    }
-}
-
-function compare(a: string, b: string, isAsc: boolean) {
-    return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
-}
index 6bc273d..6c95bf9 100644 (file)
   -->
 
 <div fxLayout="row" fxLayoutGap="10px">
-  <div class="default-cursor" (click)="toggleVisible()">
+  <div id="visible" class="default-cursor" (click)="toggleVisible()">
     <mat-icon matTooltip="Properties">{{isVisible.value? 'expand_less' : 'expand_more'}}</mat-icon>
   </div>
   <div>
-    <b><u>Policy type:</u></b> {{policyTypeInfo.type.id}}
+    <b><u>Policy type:</u></b> {{policyType}}
   </div>
   <div>
-    <b><u>Description:</u></b>{{policyTypeInfo.type.schemaObject.description}}
+    <b><u>Description:</u></b> {{policyDescription}}
   </div>
 </div>
 
-<nrcp-policy-instance *ngIf="isVisible.value" [policyTypeSchema]=policyTypeInfo.type [expanded]=isVisible.asObservable()>
+<nrcp-policy-instance *ngIf="isVisible.value" [policyTypeSchema]=policyTypeInfo.type>
 </nrcp-policy-instance>
\ No newline at end of file
index 4276ad3..859e1f8 100644 (file)
  * ========================LICENSE_END===================================
  */
 
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { PolicyTypeComponent } from './policy-type.component';
-import { PolicyTypeDataSource } from './policy-type.datasource';
-import { PolicyTypeSchema } from '../../interfaces/policy.types';
+import { PolicyTypeComponent } from "./policy-type.component";
+import { PolicyType, PolicyTypeSchema } from "@interfaces/policy.types";
+import { PolicyService } from "@services/policy/policy.service";
+import { of } from "rxjs";
+import { MockComponent } from "ng-mocks";
+import { PolicyInstanceComponent } from "../policy-instance/policy-instance.component";
+import { By } from "@angular/platform-browser";
 
-describe('PolicyTypeComponent', () => {
+describe("PolicyTypeComponent", () => {
   let component: PolicyTypeComponent;
+  let policyServiceSpy: jasmine.SpyObj<PolicyService>;
   let fixture: ComponentFixture<PolicyTypeComponent>;
 
   beforeEach(async(() => {
-    const policyTypeDataSourceSpy = jasmine.createSpyObj('PolicyTypeDataSource', ['getPolicyType']);
-    const policyTypeSchema = {"schemaObject": {"description": "Type 1 policy type"}} as PolicyTypeSchema;
-    policyTypeDataSourceSpy.getPolicyType.and.returnValue(policyTypeSchema);
+    policyServiceSpy = jasmine.createSpyObj("PolicyService", ["getPolicyType"]);
+    const policyTypeSchema = JSON.parse(
+      '{"title": "1", "description": "Type 1 policy type"}'
+    );
+    const policyType = { policy_schema: policyTypeSchema } as PolicyType;
+    policyServiceSpy.getPolicyType.and.returnValue(of(policyType));
 
     TestBed.configureTestingModule({
-      declarations: [ PolicyTypeComponent ],
-      providers: [
-        { provide: PolicyTypeDataSource, useValue: policyTypeDataSourceSpy }
-       ]
-    })
-    .compileComponents();
+      declarations: [
+        PolicyTypeComponent,
+        MockComponent(PolicyInstanceComponent),
+      ],
+      providers: [{ provide: PolicyService, useValue: policyServiceSpy }],
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -48,7 +56,51 @@ describe('PolicyTypeComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("should not call service when no type, display correct type info and no PolicyInstanceComponent added", () => {
+    expect(policyServiceSpy.getPolicyType).not.toHaveBeenCalled();
+
+    expect(component.policyType).toEqual("< No Type >");
+    expect(component.policyDescription).toEqual("Type with no schema");
+
+    const ele = fixture.debugElement.nativeElement.querySelector("nrcp-policy-instance");
+    expect(ele).toBeFalsy();
+});
+
+  it("should call service when type, display correct type info and no PolicyInstanceComponent added", () => {
+    component.policyTypeId = "type1";
+    component.loadTypeInfo();
+
+    expect(policyServiceSpy.getPolicyType).toHaveBeenCalledWith("type1");
+
+    expect(component.policyType).toEqual("type1");
+    expect(component.policyDescription).toEqual("Type 1 policy type");
+
+    const ele = fixture.debugElement.nativeElement.querySelector("nrcp-policy-instance");
+    expect(ele).toBeFalsy();
+  });
+
+  it("should add PolicyInstanceComponent with correct data when toggle visible to visible", async () => {
+    const ele = fixture.debugElement.nativeElement.querySelector("#visible");
+    expect(ele.innerText).toEqual("expand_more");
+
+    ele.click();
+    fixture.detectChanges();
+
+    expect(ele.innerText).toEqual("expand_less");
+
+    const policyInstanceComp: PolicyInstanceComponent = fixture.debugElement.query(
+      By.directive(PolicyInstanceComponent)
+    ).componentInstance;
+    expect(policyInstanceComp).toBeTruthy();
+    const expectedPolicyType = {
+      id: undefined,
+      name: undefined,
+      schemaObject: JSON.parse("{}")
+    } as PolicyTypeSchema;
+    expect(policyInstanceComp.policyTypeSchema).toEqual(expectedPolicyType);
+  });
 });
index be5b305..cfc0eb5 100644 (file)
  * ========================LICENSE_END===================================
  */
 
-import { Component, Input, OnInit } from '@angular/core';
-import { BehaviorSubject } from 'rxjs';
-import { PolicyTypeSchema } from '@interfaces/policy.types';
-import { PolicyService } from '@services/policy/policy.service';
-import { PolicyTypeDataSource } from './policy-type.datasource';
+import { Component, Input, OnInit } from "@angular/core";
+import { BehaviorSubject } from "rxjs";
+import { PolicyType, PolicyTypeSchema } from "@interfaces/policy.types";
+import { PolicyService } from "@app/services/policy/policy.service";
 
 class PolicyTypeInfo {
-  constructor(public type: PolicyTypeSchema) { }
+  constructor(public type: PolicyTypeSchema) {}
 
   isExpanded: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
 }
 
 @Component({
-  selector: 'nrcp-policy-type',
-  templateUrl: './policy-type.component.html',
-  styleUrls: ['./policy-type.component.scss']
+  selector: "nrcp-policy-type",
+  templateUrl: "./policy-type.component.html",
+  styleUrls: ["./policy-type.component.scss"],
 })
 export class PolicyTypeComponent implements OnInit {
-
   @Input() policyTypeId: string;
 
   isVisible: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
 
   policyTypeInfo: PolicyTypeInfo;
+  policyType: string;
+  policyDescription: string;
 
-  constructor(private policyTypeDataSource: PolicyTypeDataSource) {
-  }
+  constructor(private policyService: PolicyService) {}
 
   ngOnInit(): void {
-    const policyTypeSchema = this.policyTypeDataSource.getPolicyType(this.policyTypeId);
-    this.policyTypeInfo = new PolicyTypeInfo(policyTypeSchema);
-    console.log("this.policyType: ", this.policyTypeInfo);
+    this.loadTypeInfo();
     this.isVisible.next(false);
   }
 
-  public setIsVisible(status: boolean){
-    this.isVisible.next(status);
+  public loadTypeInfo() {
+    if (this.policyTypeId && this.policyTypeId !== "") {
+      this.policyService
+        .getPolicyType(this.policyTypeId)
+        .subscribe((policyType: PolicyType) => {
+          const policyTypeSchema = this.getSchemaObject(policyType);
+          this.policyTypeInfo = new PolicyTypeInfo(policyTypeSchema);
+          this.policyType = this.policyTypeId;
+          this.policyDescription = policyTypeSchema.schemaObject.description;
+        });
+    } else {
+      const noType = {
+        policy_schema: JSON.parse('{}'),
+      } as PolicyType;
+      const noTypeSchema = this.getSchemaObject(noType);
+      this.policyTypeInfo = new PolicyTypeInfo(noTypeSchema);
+      this.policyType = "< No Type >";
+      this.policyDescription = "Type with no schema";
+    }
+}
+
+  private getSchemaObject(policyType: PolicyType) {
+    const policyTypeSchema = {} as PolicyTypeSchema;
+    policyTypeSchema.id = this.policyTypeId;
+    policyTypeSchema.schemaObject = policyType.policy_schema;
+    policyTypeSchema.name = policyType.policy_schema.title;
+    return policyTypeSchema;
   }
 
   public toggleVisible() {
     this.isVisible.next(!this.isVisible.value);
   }
-}
\ No newline at end of file
+}
diff --git a/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.spec.ts b/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.spec.ts
deleted file mode 100644 (file)
index 770d6c7..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2021 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-import { TestBed } from '@angular/core/testing';
-import { BehaviorSubject, of } from 'rxjs';
-import { ToastrModule } from 'ngx-toastr';
-import { PolicyTypeDataSource } from './policy-type.datasource';
-import { PolicyService } from '@services/policy/policy.service';
-import { PolicyTypeSchema } from '@interfaces/policy.types';
-
-describe('PolicyTypeDataSource', () => {
-  let policyTypeDataSource: PolicyTypeDataSource;
-  let policyServiceSpy: any;
-
-  let policySchema = {
-    policy_schema: {
-      "$schema": "http://json-schema.org/draft-07/schema#",
-      "description": "Type 1 policy type",
-      "additionalProperties": false,
-      "title": "1",
-      "type": "object"
-    }
-  };
-
-  beforeEach(() => {
-    policyServiceSpy = jasmine.createSpyObj('PolicyService', ['getPolicyTypes', 'getPolicyType']);
-
-    policyServiceSpy.getPolicyTypes.and.returnValue(of({ policytype_ids: ['1', '2'] }));
-    policyServiceSpy.getPolicyType.and.returnValue(of(policySchema));
-    TestBed.configureTestingModule({
-      imports: [ToastrModule.forRoot()],
-      providers: [
-        { provide: PolicyService, useValue: policyServiceSpy }
-      ]
-    });
-  });
-
-  describe('#getPolicyTypes', () => {
-    let expectedPolicyTypeValue: PolicyTypeSchema[];
-    beforeEach(() => {
-      expectedPolicyTypeValue = [
-        {
-          'id': '1',
-          'name': '1',
-          'schemaObject': policySchema.policy_schema
-        },
-        {
-          'id': '2',
-          'name': '1',
-          'schemaObject': policySchema.policy_schema
-        }
-      ];
-    });
-
-    it('should create', () => {
-      policyTypeDataSource = TestBed.inject(PolicyTypeDataSource);
-      expect(policyTypeDataSource).toBeTruthy();
-    });
-
-    it('should return all policy type with Schema', () => {
-      policyTypeDataSource.getPolicyTypes();
-      const jobsSubject: BehaviorSubject<PolicyTypeSchema[]> = policyTypeDataSource.policyTypeSubject;
-      const value = jobsSubject.getValue();
-      expect(value).toEqual(expectedPolicyTypeValue);
-    });
-  });
-});
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.ts b/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.ts
deleted file mode 100644 (file)
index fe926ee..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-import { CollectionViewer, DataSource } from '@angular/cdk/collections';
-import { Injectable } from '@angular/core';
-import { BehaviorSubject } from 'rxjs/BehaviorSubject';
-import { of } from 'rxjs/observable/of';
-import { Observable } from 'rxjs/Observable';
-
-import { PolicyType, PolicyTypes, PolicyTypeSchema } from '@interfaces/policy.types';
-import { PolicyService } from '@services/policy/policy.service';
-
-@Injectable({
-    providedIn: 'root'
-})
-
-export class PolicyTypeDataSource extends DataSource<PolicyTypeSchema> {
-
-    policyTypes: PolicyTypeSchema[] = [];
-
-    policyTypeSubject = new BehaviorSubject<PolicyTypeSchema[]>([]);
-
-    public rowCount = 1; // hide footer during intial load
-
-    constructor(public policySvc: PolicyService) {
-        super();
-    }
-
-    public getPolicyTypes() {
-        this.policyTypes = [] as PolicyTypeSchema[];
-        this.policySvc.getPolicyTypes()
-            .subscribe((policyType: PolicyTypes) => {
-                this.rowCount = policyType.policytype_ids.length;
-                if (policyType.policytype_ids.length != 0) {
-                    policyType.policytype_ids.forEach(policyTypeId => {
-                        var policyTypeSchema = {} as PolicyTypeSchema
-                        if (policyTypeId === "") {
-                            policyTypeSchema.id = '';
-                            policyTypeSchema.name = '';
-                            policyTypeSchema.schemaObject = '{}';
-                            this.policyTypes.push(policyTypeSchema);
-                        }
-                        else {
-                            this.policySvc.getPolicyType(policyTypeId)
-                                .subscribe((policyType: PolicyType) => {
-                                    policyTypeSchema.id = policyTypeId;
-                                    policyTypeSchema.schemaObject = policyType.policy_schema;
-                                    policyTypeSchema.name = policyType.policy_schema.title;
-                                    this.policyTypes.push(policyTypeSchema);
-                                })
-                        }
-                        this.policyTypeSubject.next(this.policyTypes);
-                    })
-                }
-            })
-    }
-
-    public getPolicyType(policyTypeId: string): PolicyTypeSchema {
-        var policyTypeSchema = {} as PolicyTypeSchema;
-        this.policySvc.getPolicyType(policyTypeId)
-            .subscribe((policyType: PolicyType) => {
-                policyTypeSchema.id = policyTypeId;
-                policyTypeSchema.schemaObject = policyType.policy_schema;
-                policyTypeSchema.name = policyType.policy_schema.title;
-            })
-            if (policyTypeId === "") {
-                policyTypeSchema.id = '<No Type>';
-            }
-        return policyTypeSchema;
-    }
-
-    connect(collectionViewer: CollectionViewer): Observable<PolicyTypeSchema[]> {
-        return of(this.policyTypeSubject.getValue());
-    }
-
-    disconnect(collectionViewer: CollectionViewer): void {
-        this.policyTypeSubject.complete();
-    }
-}
index bfa9d97..6b502c6 100644 (file)
@@ -65,6 +65,7 @@ export class RicSelectorComponent implements OnInit {
   }
 
   private fetchRics() {
+    if (!this.policyTypeName) this.policyTypeName = "";
     console.log("fetchRics ", this.policyTypeName);
     const self: RicSelectorComponent = this;
     this.dataService.getRics(this.policyTypeName).subscribe({
index 185a8eb..71fd62e 100644 (file)
  * limitations under the License.
  * ========================LICENSE_END===================================
  */
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from "@angular/core/testing";
 
-import { PolicyService } from './policy.service';
-import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'
-import { PolicyInstance, PolicyInstances, PolicyTypes } from '@interfaces/policy.types';
+import { PolicyService } from "./policy.service";
+import {
+  HttpClientTestingModule,
+  HttpTestingController,
+} from "@angular/common/http/testing";
+import {
+  PolicyInstance,
+  PolicyInstances,
+  PolicyTypes,
+} from "@interfaces/policy.types";
 
-describe('PolicyService', () => {
-  let apiVersion2 = 'v2'
-  let basePath = '/a1-policy/';
+describe("PolicyService", () => {
+  let apiVersion2 = "v2";
+  let basePath = "/a1-policy/";
   let policyService: PolicyService;
   let httpTestingController: HttpTestingController;
-  beforeEach(() => TestBed.configureTestingModule({
-    imports: [HttpClientTestingModule],
-    providers: [
-      PolicyService
-    ],
-  }));
+  beforeEach(() =>
+    TestBed.configureTestingModule({
+      imports: [HttpClientTestingModule],
+      providers: [PolicyService],
+    })
+  );
 
   afterEach(() => {
     httpTestingController.verify();
   });
 
-  describe('#getPolicyTypes', () => {
+  describe("#getPolicyTypes", () => {
     let expectedPolicytypes: PolicyTypes;
     let emptyPolicyType: PolicyTypes;
 
@@ -47,80 +54,116 @@ describe('PolicyService', () => {
       policyService = TestBed.inject(PolicyService);
       httpTestingController = TestBed.inject(HttpTestingController);
       expectedPolicytypes = {
-        "policytype_ids": [
-          "",
-          "1"
-        ]
+        policytype_ids: ["", "1"],
       } as PolicyTypes;
     });
     //Policy Type Test Case 1:
-    it('should return all policy types', () => {
-      policyService.getPolicyTypes().subscribe(
-        policytypes => expect(policytypes).toEqual(expectedPolicytypes, 'should return expected PolicyTypes'),
-        fail
+    it("should return all policy types", () => {
+      policyService
+        .getPolicyTypes()
+        .subscribe(
+          (policytypes) =>
+            expect(policytypes).toEqual(
+              expectedPolicytypes,
+              "should return expected PolicyTypes"
+            ),
+          fail
+        );
+      const req = httpTestingController.expectOne(
+        basePath + apiVersion2 + "/" + policyService.policyTypesPath
       );
-      const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyTypesPath);
-      expect(req.request.method).toEqual('GET');
+      expect(req.request.method).toEqual("GET");
 
       req.flush(expectedPolicytypes);
     });
 
     //Policy Type Test Case 2:
     emptyPolicyType = {
-      "policytype_ids": [
-      ]
+      policytype_ids: [],
     } as PolicyTypes;
-    it('should return no policy types', () => {
-      policyService.getPolicyTypes().subscribe(
-        policytypes => expect(policytypes).toEqual(emptyPolicyType, 'should return empty array of Policy Types'),
-        fail
-      );
+    it("should return no policy types", () => {
+      policyService
+        .getPolicyTypes()
+        .subscribe(
+          (policytypes) =>
+            expect(policytypes).toEqual(
+              emptyPolicyType,
+              "should return empty array of Policy Types"
+            ),
+          fail
+        );
 
-      const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyTypesPath);
+      const req = httpTestingController.expectOne(
+        basePath + apiVersion2 + "/" + policyService.policyTypesPath
+      );
       req.flush(emptyPolicyType); //Return empty data
     });
   });
-  describe('#getPolicyInstances', () => {
+  describe("#getPolicyInstances", () => {
     let expectedPolicyInstances: PolicyInstances;
     let emptyPolicyInstances: PolicyInstances;
-    let policyTypeId = '1';
+    let policyTypeId = "1";
     beforeEach(() => {
       policyService = TestBed.inject(PolicyService);
       httpTestingController = TestBed.inject(HttpTestingController);
       expectedPolicyInstances = {
-        "policy_ids": [
-          "2100",
-          "2000"
-        ]
+        policy_ids: ["2100", "2000"],
       } as PolicyInstances;
     });
     //Policy Instances Test Case 1:
-    it('should return all policy instances', () => {
-      policyService.getPolicyInstancesByType(policyTypeId).subscribe(
-        policyinstances => expect(policyinstances).toEqual(expectedPolicyInstances, 'should return expected Policy Instances'),
-        fail
+    it("should return all policy instances", () => {
+      policyService
+        .getPolicyInstancesByType(policyTypeId)
+        .subscribe(
+          (policyinstances) =>
+            expect(policyinstances).toEqual(
+              expectedPolicyInstances,
+              "should return expected Policy Instances"
+            ),
+          fail
+        );
+      const req = httpTestingController.expectOne(
+        basePath +
+          apiVersion2 +
+          "/" +
+          policyService.policyPath +
+          "?" +
+          "policytype_id=" +
+          policyTypeId
       );
-      const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '?' + 'policytype_id=' + policyTypeId);
-      expect(req.request.method).toEqual('GET');
+      expect(req.request.method).toEqual("GET");
       req.flush(expectedPolicyInstances);
     });
 
     //Policy Instances Test Case 2:
     emptyPolicyInstances = {
-      "policy_ids": [
-      ]
+      policy_ids: [],
     } as PolicyInstances;
-    it('should return no policy instances', () => {
-      policyService.getPolicyInstancesByType(policyTypeId).subscribe(
-        policyinstances => expect(policyinstances.policy_ids.length).toEqual(0, 'should return empty array of Policy Instances'),
-        fail
+    it("should return no policy instances", () => {
+      policyService
+        .getPolicyInstancesByType(policyTypeId)
+        .subscribe(
+          (policyinstances) =>
+            expect(policyinstances.policy_ids.length).toEqual(
+              0,
+              "should return empty array of Policy Instances"
+            ),
+          fail
+        );
+      const req = httpTestingController.expectOne(
+        basePath +
+          apiVersion2 +
+          "/" +
+          policyService.policyPath +
+          "?" +
+          "policytype_id=" +
+          policyTypeId
       );
-      const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '?' + 'policytype_id=' + policyTypeId);
       req.flush(emptyPolicyInstances); //Return empty data
     });
   });
 
-  describe('#getPolicyInstance', () => {
+  describe("#getPolicyInstance", () => {
     let expectedPolicyInstance: PolicyInstance;
     let emptyPolicyInstances: PolicyInstances;
     let policyId = "2000";
@@ -128,22 +171,30 @@ describe('PolicyService', () => {
       policyService = TestBed.inject(PolicyService);
       httpTestingController = TestBed.inject(HttpTestingController);
       expectedPolicyInstance = {
-        "policy_id": "2000",
-        "policytype_id": "1",
-        "ric_id": "ric1",
-        "policy_data": "",
-        "service_id": "service1",
-        "lastModified": ""
+        policy_id: "2000",
+        policytype_id: "1",
+        ric_id: "ric1",
+        policy_data: "",
+        service_id: "service1",
+        lastModified: "",
       } as PolicyInstance;
     });
     //Policy Instances Test Case 1:
-    it('should return one policy instance', () => {
-      policyService.getPolicyInstance(policyId).subscribe(
-        policyinstance => expect(policyinstance).toEqual(expectedPolicyInstance, 'should return expected Policy Instances'),
-        fail
+    it("should return one policy instance", () => {
+      policyService
+        .getPolicyInstance(policyId)
+        .subscribe(
+          (policyinstance) =>
+            expect(policyinstance).toEqual(
+              expectedPolicyInstance,
+              "should return expected Policy Instances"
+            ),
+          fail
+        );
+      const req = httpTestingController.expectOne(
+        basePath + apiVersion2 + "/" + policyService.policyPath + "/" + policyId
       );
-      const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '/' + policyId);
-      expect(req.request.method).toEqual('GET');
+      expect(req.request.method).toEqual("GET");
       req.flush(expectedPolicyInstance);
     });
   });
index 354173c..8c6d015 100644 (file)
  * ========================LICENSE_END===================================
  */
 
-import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
-import { Observable } from 'rxjs';
-import { CreatePolicyInstance, PolicyInstance, PolicyInstanceAck, PolicyInstances, PolicyStatus, PolicyType, PolicyTypes } from '@interfaces/policy.types';
-import { Rics } from '@interfaces/ric';
+import { Injectable } from "@angular/core";
+import { HttpClient } from "@angular/common/http";
+import { Observable } from "rxjs";
+import {
+  CreatePolicyInstance,
+  PolicyInstance,
+  PolicyInstanceAck,
+  PolicyInstances,
+  PolicyStatus,
+  PolicyType,
+  PolicyTypes,
+} from "@interfaces/policy.types";
+import { Rics } from "@interfaces/ric";
 
 /**
  * Services for calling the policy endpoints.
  */
 @Injectable({
-    providedIn: 'root'
+  providedIn: "root",
 })
 export class PolicyService {
+  private apiVersion2 = "/v2";
+  private basePath = "/a1-policy";
+  policyTypesPath = "policy-types";
+  policyPath = "policies";
 
-    private apiVersion2 = '/v2'
-    private basePath = '/a1-policy';
-    policyTypesPath = 'policy-types';
-    policyPath = 'policies';
+  private buildPath(...args: any[]) {
+    let result = this.basePath + this.apiVersion2;
+    args.forEach((part) => {
+      result = result + "/" + part;
+    });
+    return result;
+  }
 
-    private buildPath(...args: any[]) {
-        let result = this.basePath + this.apiVersion2;
-        args.forEach(part => {
-            result = result + '/' + part;
-        });
-        return result;
-    }
+  constructor(private httpClient: HttpClient) {
+    // injects to variable httpClient
+  }
 
-    constructor(private httpClient: HttpClient) {
-        // injects to variable httpClient
-    }
+  getPolicyTypes(): Observable<PolicyTypes> {
+    const url = this.buildPath(this.policyTypesPath);
+    return this.httpClient.get<PolicyTypes>(url);
+  }
 
-    getPolicyTypes(): Observable<PolicyTypes> {
-        const url = this.buildPath(this.policyTypesPath);
-        return this.httpClient.get<PolicyTypes>(url);
-    }
+  getPolicyType(policyTypeId: string): Observable<PolicyType> {
+    const url = this.buildPath(this.policyTypesPath + "/" + policyTypeId);
+    return this.httpClient.get<PolicyType>(url);
+  }
 
-    getPolicyType(policyTypeId: string): Observable<PolicyType> {
-        const url = this.buildPath(this.policyTypesPath + '/' + policyTypeId);
-        return this.httpClient.get<PolicyType>(url);
-    }
+  getPolicyInstancesByType(policyTypeId: string): Observable<PolicyInstances> {
+    const url = this.buildPath(
+      this.policyPath + "?" + "policytype_id=" + policyTypeId
+    );
+    return this.httpClient.get<PolicyInstances>(url);
+  }
 
-    getPolicyInstancesByType(policyTypeId: string): Observable<PolicyInstances> {
-        const url = this.buildPath(this.policyPath + '?' + 'policytype_id=' + policyTypeId);
-        return this.httpClient.get<PolicyInstances>(url);
-    }
+  getPolicyInstance(policyId: string): Observable<PolicyInstance> {
+    const url = this.buildPath(this.policyPath) + "/" + policyId;
+    return this.httpClient.get<PolicyInstance>(url);
+  }
 
-    getPolicyInstance(policyId: string): Observable<PolicyInstance> {
-        const url = this.buildPath(this.policyPath) + '/' + policyId;
-        return this.httpClient.get<PolicyInstance>(url);
-    }
+  getPolicyStatus(policyId: string): Observable<PolicyStatus> {
+    const url = this.buildPath(this.policyPath) + "/" + policyId + "/status";
+    return this.httpClient.get<PolicyStatus>(url);
+  }
 
-    getPolicyStatus(policyId: string): Observable<PolicyStatus> {
-        const url = this.buildPath(this.policyPath) + '/' + policyId + '/status';
-        return this.httpClient.get<PolicyStatus>(url);
-    }
+  /**
+   * Gets policy parameters.
+   * @returns Observable that should yield a policy instance
+   */
+  getPolicy(policyTypeId: string, policyInstanceId: string): Observable<any> {
+    const url =
+      this.buildPath(this.policyPath, policyInstanceId) +
+      "?type=" +
+      policyTypeId;
+    return this.httpClient.get<any>(url);
+  }
 
-    /**
-     * Gets policy parameters.
-     * @returns Observable that should yield a policy instance
-     */
-    getPolicy(policyTypeId: string, policyInstanceId: string): Observable<any> {
-        const url = this.buildPath(this.policyPath, policyInstanceId) + '?type=' + policyTypeId;
-        return this.httpClient.get<any>(url);
-    }
+  /**
+   * Creates or replaces policy instance.
+   * @param policyTypeId ID of the policy type that the instance will have
+   * @param policyInstanceId ID of the instance
+   * @param policyJson Json with the policy content
+   * @returns Observable that should yield a response code, no data
+   */
+  putPolicy(createPolicyInstance: CreatePolicyInstance): Observable<any> {
+    const url = this.buildPath(this.policyPath);
+    return this.httpClient.put<PolicyInstanceAck>(url, createPolicyInstance, {
+      observe: "response",
+    });
+  }
 
-    /**
-     * Creates or replaces policy instance.
-     * @param policyTypeId ID of the policy type that the instance will have
-     * @param policyInstanceId ID of the instance
-     * @param policyJson Json with the policy content
-     * @returns Observable that should yield a response code, no data
-     */
-    putPolicy(createPolicyInstance: CreatePolicyInstance): Observable<any> {
-        const url = this.buildPath(this.policyPath);
-        return this.httpClient.put<PolicyInstanceAck>(url, createPolicyInstance, { observe: 'response' });
-    }
+  /**
+   * Deletes a policy instance.
+   * @param policyTypeId ID of the policy type that the instance belong to
+   * @param policyInstanceId ID of the instance
+   * @returns Observable that should yield a response code, no data
+   */
+  deletePolicy(policyInstanceId: string): Observable<any> {
+    const url = this.buildPath(this.policyPath, policyInstanceId);
+    return this.httpClient.delete(url, { observe: "response" });
+  }
 
-    /**
-     * Deletes a policy instance.
-     * @param policyTypeId ID of the policy type that the instance belong to
-     * @param policyInstanceId ID of the instance
-     * @returns Observable that should yield a response code, no data
-     */
-    deletePolicy(policyInstanceId: string): Observable<any> {
-        const url = this.buildPath(this.policyPath, policyInstanceId);
-        return this.httpClient.delete(url, { observe: 'response' });
-    }
-
-
-    getRics(policyTypeId: string): Observable<Rics> {
-        const url = this.buildPath('rics') + '?policytype_id=' + policyTypeId;
-        return this.httpClient.get<any>(url);
-    }
+  getRics(policyTypeId: string): Observable<Rics> {
+    const url = this.buildPath("rics") + "?policytype_id=" + policyTypeId;
+    return this.httpClient.get<any>(url);
+  }
 }