Polling mechanism to get jobs
[portal/nonrtric-controlpanel.git] / webapp-frontend / src / app / ei-coordinator / jobs-list / jobs-list.component.spec.ts
1 /*-
2  * ========================LICENSE_START=================================
3  * O-RAN-SC
4  * %%
5  * Copyright (C) 2021 Nordix Foundation
6  * %%
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ========================LICENSE_END===================================
19  */
20 import { HarnessLoader } from "@angular/cdk/testing";
21 import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed";
22 import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
23 import {
24   async,
25   ComponentFixture,
26   discardPeriodicTasks,
27   fakeAsync,
28   TestBed,
29   tick,
30 } from "@angular/core/testing";
31 import { FormsModule, ReactiveFormsModule } from "@angular/forms";
32 import { MatFormFieldModule } from "@angular/material/form-field";
33 import { MatInputModule } from "@angular/material/input";
34 import { MatInputHarness } from "@angular/material/input/testing";
35 import { MatPaginatorModule } from "@angular/material/paginator";
36 import { MatSortModule } from "@angular/material/sort";
37 import { MatSortHarness } from "@angular/material/sort/testing";
38 import { MatPaginatorHarness } from "@angular/material/paginator/testing";
39 import { MatTableModule } from "@angular/material/table";
40 import { MatTableHarness } from "@angular/material/table/testing";
41 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
42 import { of } from "rxjs/observable/of";
43 import { EIJob } from "@interfaces/ei.types";
44 import { EIService } from "@services/ei/ei.service";
45 import { UiService } from "@services/ui/ui.service";
46
47 import { Job, JobsListComponent } from "./jobs-list.component";
48 import { Subscription } from "rxjs";
49
50 let component: JobsListComponent;
51 let fixture: ComponentFixture<JobsListComponent>;
52
53 const eijob1 = {
54   ei_job_identity: "job1",
55   ei_type_identity: "type1",
56   owner: "owner1",
57   target_uri: "http://one",
58 } as EIJob;
59 const eijob2 = {
60   ei_job_identity: "job2",
61   ei_type_identity: "type2",
62   owner: "owner2",
63   target_uri: "http://two",
64 } as EIJob;
65
66 const job1 = {
67   jobId: "job1",
68   typeId: "type1",
69   owner: "owner1",
70   targetUri: "http://one",
71   prodId: "producer1",
72 } as Job;
73 const job2 = {
74   jobId: "job2",
75   typeId: "type2",
76   owner: "owner2",
77   targetUri: "http://two",
78   prodId: "producer1",
79 } as Job;
80 const job3 = {
81   jobId: "job1",
82   typeId: "type1",
83   owner: "owner1",
84   targetUri: "http://one",
85   prodId: "producer2",
86 } as Job;
87 const job4 = {
88   jobId: "job2",
89   typeId: "type2",
90   owner: "owner2",
91   targetUri: "http://two",
92   prodId: "producer2",
93 } as Job;
94
95 describe("JobsListComponent", () => {
96   let loader: HarnessLoader;
97
98   beforeEach(async(() => {
99     const spy = jasmine.createSpyObj("EIService", [
100       "getProducerIds",
101       "getJobsForProducer",
102     ]);
103
104     TestBed.configureTestingModule({
105       imports: [
106         MatTableModule,
107         MatPaginatorModule,
108         FormsModule,
109         MatSortModule,
110         ReactiveFormsModule,
111         BrowserAnimationsModule,
112         MatFormFieldModule,
113         MatInputModule,
114       ],
115       schemas: [CUSTOM_ELEMENTS_SCHEMA],
116       declarations: [JobsListComponent],
117       providers: [{ provide: EIService, useValue: spy }, UiService],
118     })
119       .compileComponents()
120       .then(() => {
121         fixture = TestBed.createComponent(JobsListComponent);
122         component = fixture.componentInstance;
123         loader = TestbedHarnessEnvironment.loader(fixture);
124       });
125   }));
126
127   const expectedJob1Row = {
128     jobId: "job1",
129     prodId: "producer1",
130     typeId: "type1",
131     owner: "owner1",
132     targetUri: "http://one",
133   };
134
135   it("should create", () => {
136     expect(component).toBeTruthy();
137   });
138
139   describe("#content", () => {
140     it("should loadJobs", fakeAsync(() => {
141       setServiceSpy();
142       const newSub: Subscription = component.dataSubscription();
143       tick(0);
144
145       const actualJobs: Job[] = component.jobs();
146       expect(actualJobs.length).toEqual(4);
147       expect(actualJobs).toEqual([job1, job2, job3, job4]);
148       newSub.unsubscribe();
149     }));
150
151     it("should contain job table with correct columns", fakeAsync(() => {
152       setServiceSpy();
153       component.ngOnInit();
154       tick(0);
155
156       loader
157         .getHarness(MatTableHarness.with({ selector: "#jobsTable" }))
158         .then((loadTable) => {
159           loadTable.getHeaderRows().then((headerRow) => {
160             headerRow[0].getCellTextByColumnName().then((header) => {
161               expect(header).toEqual({
162                 jobId: "Job ID",
163                 prodId: "Producer ID",
164                 typeId: "Type ID",
165                 owner: "Owner",
166                 targetUri: "Target URI",
167               });
168             });
169           });
170         });
171
172       discardPeriodicTasks();
173     }));
174
175     it("should set correct dark mode from UIService", fakeAsync(() => {
176       setServiceSpy();
177       component.ngOnInit();
178       tick(0);
179
180       const uiService: UiService = TestBed.inject(UiService);
181       expect(component.darkMode).toBeTruthy();
182
183       uiService.darkModeState.next(false);
184       fixture.detectChanges();
185       expect(component.darkMode).toBeFalsy();
186       discardPeriodicTasks();
187     }));
188   });
189
190   describe("#jobsTable", () => {
191     it("should contain data after initialization", fakeAsync(() => {
192       setServiceSpy();
193       component.ngOnInit();
194       tick(0);
195
196       const expectedJobRows = [
197         expectedJob1Row,
198         {
199           jobId: "job2",
200           prodId: "producer1",
201           typeId: "type2",
202           owner: "owner2",
203           targetUri: "http://two",
204         },
205         {
206           jobId: "job1",
207           prodId: "producer2",
208           typeId: "type1",
209           owner: "owner1",
210           targetUri: "http://one",
211         },
212         {
213           jobId: "job2",
214           prodId: "producer2",
215           typeId: "type2",
216           owner: "owner2",
217           targetUri: "http://two",
218         },
219       ];
220
221       loader
222         .getHarness(MatTableHarness.with({ selector: "#jobsTable" }))
223         .then((loadTable) => {
224           loadTable.getRows().then((jobRows) => {
225             expect(jobRows.length).toEqual(4);
226             jobRows.forEach((row) => {
227               row.getCellTextByColumnName().then((values) => {
228                 expect(expectedJobRows).toContain(
229                   jasmine.objectContaining(values)
230                 );
231               });
232             });
233           });
234         });
235       discardPeriodicTasks();
236     }));
237
238     it("should display default values for non required properties ", fakeAsync(() => {
239       const jobMissingProperties = {
240         ei_job_identity: "job1",
241         ei_job_data: {
242           jobparam2: "value2_job2",
243           jobparam3: "value3_job2",
244           jobparam1: "value1_job2",
245         },
246         target_uri: "http://one",
247       } as EIJob;
248
249       let eiServiceSpy = TestBed.inject(EIService) as jasmine.SpyObj<EIService>;
250       eiServiceSpy.getProducerIds.and.returnValue(of(["producer1"]));
251       eiServiceSpy.getJobsForProducer.and.returnValue(
252         of([jobMissingProperties])
253       );
254
255       component.ngOnInit();
256       tick(0);
257       const expectedJobRow = {
258         jobId: "job1",
259         prodId: "producer1",
260         typeId: "< No type >",
261         owner: "< No owner >",
262         targetUri: "http://one",
263       };
264
265       loader
266         .getHarness(MatTableHarness.with({ selector: "#jobsTable" }))
267         .then((loadTable) => {
268           loadTable.getRows().then((jobRows) => {
269             jobRows[0].getCellTextByColumnName().then((value) => {
270               expect(expectedJobRow).toContain(jasmine.objectContaining(value));
271             });
272           });
273         });
274       discardPeriodicTasks();
275     }));
276
277     it("filtering", fakeAsync(() => {
278       setServiceSpy();
279       component.ngOnInit();
280       tick(0);
281
282       loader
283         .getHarness(MatTableHarness.with({ selector: "#jobsTable" }))
284         .then((loadTable) => {
285           loader
286             .getHarness(MatInputHarness.with({ selector: "#jobIdFilter" }))
287             .then((idFilter) => {
288               idFilter.setValue("1");
289               loadTable.getRows().then((jobRows) => {
290                 expect(jobRows.length).toEqual(2);
291                 jobRows[0].getCellTextByColumnName().then((value) => {
292                   expect(expectedJob1Row).toContain(
293                     jasmine.objectContaining(value)
294                   );
295                 });
296               });
297               idFilter.setValue("");
298             });
299           loader
300             .getHarness(MatInputHarness.with({ selector: "#jobTypeIdFilter" }))
301             .then((typeIdFilter) => {
302               typeIdFilter.setValue("1");
303               loadTable.getRows().then((jobRows) => {
304                 expect(jobRows.length).toEqual(2);
305                 jobRows[0].getCellTextByColumnName().then((value) => {
306                   expect(expectedJob1Row).toContain(
307                     jasmine.objectContaining(value)
308                   );
309                 });
310               });
311               typeIdFilter.setValue("");
312             });
313           loader
314             .getHarness(MatInputHarness.with({ selector: "#jobOwnerFilter" }))
315             .then((ownerFilter) => {
316               ownerFilter.setValue("1");
317               loadTable.getRows().then((jobRows) => {
318                 expect(jobRows.length).toEqual(2);
319                 jobRows[0].getCellTextByColumnName().then((value) => {
320                   expect(expectedJob1Row).toContain(
321                     jasmine.objectContaining(value)
322                   );
323                 });
324               });
325               ownerFilter.setValue("");
326             });
327           loader
328             .getHarness(
329               MatInputHarness.with({ selector: "#jobTargetUriFilter" })
330             )
331             .then((targetUriFilter) => {
332               targetUriFilter.setValue("1");
333               loadTable.getRows().then((jobRows) => {
334                 expect(jobRows.length).toEqual(2);
335                 jobRows[0].getCellTextByColumnName().then((value) => {
336                   expect(expectedJob1Row).toContain(
337                     jasmine.objectContaining(value)
338                   );
339                 });
340               });
341               targetUriFilter.setValue("");
342             });
343         });
344
345       discardPeriodicTasks();
346     }));
347
348     describe("#sorting", () => {
349       it("should verify sort functionality on the table", fakeAsync(() => {
350         setServiceSpy();
351         tick(0);
352
353         loader.getHarness(MatSortHarness).then((sort) => {
354           sort.getSortHeaders({ sortDirection: "" }).then((headers) => {
355             expect(headers.length).toBe(5);
356
357             headers[0].click().then((_) => {
358               headers[0].isActive().then((active) => {
359                 expect(active).toBe(true);
360               });
361               headers[0].getSortDirection().then((direction) => {
362                 expect(direction).toBe("asc");
363               });
364             });
365             headers[0].click().then((_) => {
366               headers[0].getSortDirection().then((direction) => {
367                 expect(direction).toBe("desc");
368               });
369             });
370           });
371         });
372         discardPeriodicTasks();
373       }));
374
375       it("should sort table asc and desc by first header", fakeAsync(() => {
376         setServiceSpy();
377         tick(0);
378
379         loader.getHarness(MatSortHarness).then((sort) => {
380           loader
381             .getHarness(MatTableHarness.with({ selector: "#jobsTable" }))
382             .then((loadTable) => {
383               sort.getSortHeaders().then((headers) => {
384                 headers[0].click().then((_) => {
385                   headers[0].getSortDirection().then((direction) => {
386                     expect(direction).toBe("");
387                   });
388                 });
389                 headers[0].click().then((_) => {
390                   headers[0].getSortDirection().then((direction) => {
391                     expect(direction).toBe("asc");
392                   });
393                 });
394                 loadTable.getRows().then((jobRows) => {
395                   jobRows[0].getCellTextByColumnName().then((value) => {
396                     expect(expectedJob1Row).toContain(
397                       jasmine.objectContaining(value)
398                     );
399                   });
400                 });
401                 headers[0].click().then((_) => {
402                   headers[0].getSortDirection().then((direction) => {
403                     expect(direction).toBe("desc");
404                   });
405                 });
406                 loadTable.getRows().then((jobRows) => {
407                   jobRows[jobRows.length - 1]
408                     .getCellTextByColumnName()
409                     .then((value) => {
410                       expect(expectedJob1Row).toContain(
411                         jasmine.objectContaining(value)
412                       );
413                     });
414                 });
415               });
416             });
417         });
418         discardPeriodicTasks();
419       }));
420     });
421
422     describe("#paging", () => {
423       it("should work properly on the table", fakeAsync(() => {
424         let eiServiceSpy = TestBed.inject(
425           EIService
426         ) as jasmine.SpyObj<EIService>;
427         eiServiceSpy.getProducerIds.and.returnValue(
428           of(["producer1", "producer2"])
429         );
430         eiServiceSpy.getJobsForProducer.and.returnValue(
431           of([eijob1, eijob2, eijob1])
432         );
433         tick(0);
434
435         loader.getHarness(MatPaginatorHarness).then((paging) => {
436           paging.setPageSize(5);
437
438           loader
439             .getHarness(MatTableHarness.with({ selector: "#jobsTable" }))
440             .then((loadTable) => {
441               loadTable.getRows().then((jobRows) => {
442                 expect(jobRows.length).toEqual(5);
443               });
444               paging.goToNextPage();
445               loadTable.getRows().then((jobRows) => {
446                 expect(jobRows.length).toEqual(1);
447                 jobRows[0].getCellTextByColumnName().then((value) => {
448                   const expectedRow = {
449                     jobId: "job1",
450                     prodId: "producer2",
451                     typeId: "type1",
452                     owner: "owner1",
453                     targetUri: "http://one",
454                   };
455                   expect(expectedRow).toContain(
456                     jasmine.objectContaining(value)
457                   );
458                 });
459               });
460             });
461         });
462
463         discardPeriodicTasks();
464       }));
465     });
466   });
467 });
468
469 function setServiceSpy() {
470   let eiServiceSpy = TestBed.inject(EIService) as jasmine.SpyObj<EIService>;
471   eiServiceSpy.getProducerIds.and.returnValue(of(["producer1", "producer2"]));
472   eiServiceSpy.getJobsForProducer.and.returnValue(of([eijob1, eijob2]));
473 }