Increase test coverage for SO MON UI
[so.git] / so-monitoring / so-monitoring-ui / src / main / frontend / src / app / home / home.component.spec.ts
1 /**
2 ============LICENSE_START=======================================================
3  Copyright (C) 2018 Ericsson. All rights reserved.
4 ================================================================================
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9     http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15  limitations under the License.
16
17 SPDX-License-Identifier: Apache-2.0
18 ============LICENSE_END=========================================================
19
20 @authors: ronan.kenny@ericsson.com, waqas.ikram@ericsson.com, andrei.barcovschi@ericsson.com
21 */
22
23 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
24
25 import { HomeComponent } from './home.component';
26 import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
27 import { MatTableModule, MatNativeDateModule, MatTableDataSource, MatPaginatorModule } from '@angular/material';
28 import { FormsModule } from '@angular/forms';
29 import { MatDatepickerModule } from '@angular/material/datepicker';
30 import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
31 import { HttpClientModule } from '@angular/common/http';
32 import { HttpClient } from '@angular/common/http';
33 import { inject } from '@angular/core/testing';
34 import { RouterModule } from '@angular/router';
35 import { APP_BASE_HREF } from '@angular/common';
36 import { ToastrNotificationService } from '../toastr-notification-service.service';
37 import { environment } from '../../environments/environment.prod';
38 import { Observable, of, throwError } from 'rxjs';
39 import { SearchRequest } from '../model/SearchRequest.model';
40 import { DataService } from '../data.service'; // may be able to remove
41 import { Process } from '../model/process.model';
42 import { By } from '@angular/platform-browser';
43 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
44 import { ProcessInstanceId } from '../model/processInstanceId.model';
45 import { HttpResponse } from '@angular/common/http';
46 import { Router } from '@angular/router';
47 import { Routes } from '@angular/router';
48 import { RouterTestingModule } from '@angular/router/testing';
49 import { DetailsComponent } from '../details/details.component';
50
51 // Generate stub for toastr popup notifications
52 class StubbedToastrNotificationService extends ToastrNotificationService {
53   toastrSettings() {}
54   info() {}
55   error() {}
56 }
57
58 const routes: Routes = [ { path: 'details/114e9ae4-4a32-11e9-8646-d663bd873d93' , component: DetailsComponent} ]
59
60 describe('HomeComponent', () => {
61   let spyDataService: jasmine.SpyObj<DataService>;
62   let router: Router;
63   let component: HomeComponent;
64   let fixture: ComponentFixture<HomeComponent>;
65
66   beforeEach(() => {
67     spyDataService = jasmine.createSpyObj('DataService', ['retrieveInstance', 'getProcessInstanceId']);
68
69     TestBed.configureTestingModule({
70       providers: [
71         { provide: DataService, useValue: spyDataService },
72         { provide: APP_BASE_HREF, useValue: '/' },
73         { provide: ToastrNotificationService, useClass: StubbedToastrNotificationService }],
74       imports: [MatPaginatorModule, BrowserAnimationsModule, MatTableModule, FormsModule, MatDatepickerModule, MatNativeDateModule, HttpClientModule, RouterTestingModule.withRoutes(routes)],
75       declarations: [HomeComponent, DetailsComponent],
76       schemas: [
77         CUSTOM_ELEMENTS_SCHEMA
78       ]
79     });
80
81     fixture = TestBed.createComponent(HomeComponent);
82     router = TestBed.get(Router);
83     component = fixture.componentInstance;
84     fixture.detectChanges();
85   });
86
87   // Ensure creation of HomeComponent component
88   it('component should be created', () => {
89     expect(component).toBeTruthy();
90   });
91
92   // Ensure all statistic variables are initialised to zero
93   it('should ensure statistic variables are defaulted at zero', () => {
94     expect(component.totalVal === 0 && component.completeVal === 0 &&
95       component.inProgressVal === 0 && component.failedVal === 0 &&
96       component.pendingVal === 0 && component.unlockedVal === 0 &&
97       component.percentageComplete === 0 && component.percentageFailed === 0 &&
98       component.percentageInProg === 0 && component.percentagePending === 0 &&
99       component.percentageUnlocked === 0).toBeTruthy();
100   });
101
102   it('should should navigate to a process if response status is OK', async(() => {
103       spyDataService.getProcessInstanceId.and.returnValue(of(<HttpResponse<ProcessInstanceId>>{body: {processInstanceId: '114e9ae4-4a32-11e9-8646-d663bd873d93'}, status: 200}));
104       spyOn(router, 'navigate');
105       component.getProcessIsntanceId('e8a75940-4a32-11e9-8646-d663bd873d93');
106
107       fixture.whenStable().then(() => {
108         expect(router.navigate).toHaveBeenCalledWith(['/details/114e9ae4-4a32-11e9-8646-d663bd873d93']);
109       });
110     }));
111
112   it('should handle error if no process instance id found', () => {
113     spyDataService.getProcessInstanceId.and.returnValue(of(<HttpResponse<ProcessInstanceId>>{body: {processInstanceId: 'getProcessInstanceId error not found'}, status: 404}));
114     component.getProcessIsntanceId('e8a75940-4a32-11e9-8646-d663bd873d93');
115   });
116
117   it('should handle error when searchData.getSearchRequest returns an error', () => {
118       spyOn(component.searchData, 'getSearchRequest').and.callFake(() => {
119         return throwError(new Error('getSearchRequest error'));
120       });
121       component.makeCall();
122   });
123
124   it('should handle error when dataService.retrieveInstance returns an error', () => {
125       spyOn(component.searchData, 'getSearchRequest').and.returnValue(of(getSearchRequest("965d3c92-44e0-11e9-b210-d663bd873d93", "85a7c354-44e0-11e9-b210-d663bd873d93", undefined, undefined, undefined, undefined, undefined, undefined, "ALL")));
126       spyDataService.retrieveInstance.and.callFake(() => {
127         return throwError(new Error('retrieveInstance error'));
128       });
129       component.makeCall();
130   });
131
132   it('should calculate statistics correctly', async(() => {
133     let requestStatusTypes: string[] = ["COMPLETE", "IN_PROGRESS", "FAILED", "PENDING", "UNLOCKED"];
134     let processArr: Process[] = [];
135
136     // create 5 processes, one of each requestStatusType, with default time.
137     requestStatusTypes.forEach((status) => {
138       let serviceName = "service-" + status;
139       var process = getProcess("85a7c354-44e0-11e9-b210-d663bd873d93", "965d3c92-44e0-11e9-b210-d663bd873d93", serviceName, "048a6212-44e1-11e9-b210-d663bd873d93", status, "TestType", undefined, undefined);
140       processArr.push(process);
141     })
142
143       // search request has default filter.
144       spyOn(component.searchData, 'getSearchRequest').and.returnValue(of(getSearchRequest(undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, "ALL")));
145       spyDataService.retrieveInstance.and.returnValue(of(processArr));
146       component.makeCall();
147
148       fixture.whenStable().then(() => {
149         fixture.detectChanges();
150
151         expect(
152           component.totalVal === 5 && component.completeVal === 1 &&
153           component.inProgressVal === 1 && component.failedVal === 1 &&
154           component.pendingVal === 1 && component.unlockedVal === 1 &&
155           component.percentageComplete === 20 &&
156           component.percentageFailed === 20 &&
157           component.percentageInProg === 20 &&
158           component.percentagePending === 20 &&
159           component.percentageUnlocked === 20)
160           .toBeTruthy();
161       });
162     }));
163
164   function getSearchRequest(selectedValueSII = "EQ", serviceInstanceIdVal: string, selectedValueRI = "EQ", requestIdVal: string, selectedValueSN = "EQ", serviceInstanceNameVal: string, startTimeInMilliseconds = 0, endTimeInMilliseconds = 4, selectedValueSTATUS?: string): SearchRequest {
165     if (startTimeInMilliseconds > endTimeInMilliseconds) {
166       console.error("End time cannot be greater than start time.");
167       return undefined;
168     }
169     if (typeof selectedValueSTATUS === "string")
170       return new SearchRequest({ serviceInstanceId: [selectedValueSII, serviceInstanceIdVal], requestId: [selectedValueRI, requestIdVal], serviceInstanceName: [selectedValueSN, serviceInstanceNameVal], requestStatus: ["EQ", selectedValueSTATUS] }, startTimeInMilliseconds, endTimeInMilliseconds);
171     else
172       return new SearchRequest({ serviceInstanceId: [selectedValueSII, serviceInstanceIdVal], requestId: [selectedValueRI, requestIdVal], serviceInstanceName: [selectedValueSN, serviceInstanceNameVal] }, startTimeInMilliseconds, endTimeInMilliseconds);
173   }
174
175   function getProcess(requestIdVal: string, serviceInstanceIdVal: string, serviceIstanceNameVal: string, networkIdVal: string, requestStatusVal: string, serviceTypeVal: string, startTimeVal = "1", endTimeVal = "2"): Process {
176     return <Process>{ requestId: requestIdVal, serviceInstanceId: serviceInstanceIdVal, serviceIstanceName: serviceIstanceNameVal, networkId: networkIdVal, requestStatus: requestStatusVal, serviceType: serviceTypeVal, startTime: startTimeVal, endTime: endTimeVal };
177   }
178 });