]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { HttpClientTestingModule } from '@angular/common/http/testing'; |
2 | import { NO_ERRORS_SCHEMA } from '@angular/core'; | |
3 | import { ComponentFixture, TestBed } from '@angular/core/testing'; | |
4 | import { By } from '@angular/platform-browser'; | |
5 | ||
6 | import * as _ from 'lodash'; | |
7 | import { PopoverModule } from 'ngx-bootstrap/popover'; | |
8 | import { of } from 'rxjs'; | |
9 | ||
10 | import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper'; | |
11 | import { HealthService } from '../../../shared/api/health.service'; | |
12 | import { Permissions } from '../../../shared/models/permissions'; | |
13 | import { AuthStorageService } from '../../../shared/services/auth-storage.service'; | |
14 | import { FeatureTogglesService } from '../../../shared/services/feature-toggles.service'; | |
15 | import { RefreshIntervalService } from '../../../shared/services/refresh-interval.service'; | |
16 | import { SharedModule } from '../../../shared/shared.module'; | |
17 | import { PgCategoryService } from '../../shared/pg-category.service'; | |
11fdf7f2 TL |
18 | import { HealthPieComponent } from '../health-pie/health-pie.component'; |
19 | import { MdsSummaryPipe } from '../mds-summary.pipe'; | |
20 | import { MgrSummaryPipe } from '../mgr-summary.pipe'; | |
21 | import { MonSummaryPipe } from '../mon-summary.pipe'; | |
22 | import { OsdSummaryPipe } from '../osd-summary.pipe'; | |
23 | import { HealthComponent } from './health.component'; | |
24 | ||
25 | describe('HealthComponent', () => { | |
26 | let component: HealthComponent; | |
27 | let fixture: ComponentFixture<HealthComponent>; | |
28 | let getHealthSpy; | |
29 | const healthPayload = { | |
30 | health: { status: 'HEALTH_OK' }, | |
31 | mon_status: { monmap: { mons: [] }, quorum: [] }, | |
32 | osd_map: { osds: [] }, | |
33 | mgr_map: { standbys: [] }, | |
34 | hosts: 0, | |
35 | rgw: 0, | |
36 | fs_map: { filesystems: [] }, | |
37 | iscsi_daemons: 0, | |
38 | client_perf: {}, | |
39 | scrub_status: 'Inactive', | |
40 | pools: [], | |
81eedcae TL |
41 | df: { stats: {} }, |
42 | pg_info: { object_stats: { num_objects: 0 } } | |
11fdf7f2 TL |
43 | }; |
44 | const fakeAuthStorageService = { | |
45 | getPermissions: () => { | |
46 | return new Permissions({ log: ['read'] }); | |
47 | } | |
48 | }; | |
49 | let fakeFeatureTogglesService; | |
50 | ||
51 | configureTestBed({ | |
52 | imports: [SharedModule, HttpClientTestingModule, PopoverModule.forRoot()], | |
53 | declarations: [ | |
54 | HealthComponent, | |
55 | HealthPieComponent, | |
56 | MonSummaryPipe, | |
57 | OsdSummaryPipe, | |
58 | MdsSummaryPipe, | |
59 | MgrSummaryPipe | |
60 | ], | |
61 | schemas: [NO_ERRORS_SCHEMA], | |
62 | providers: [ | |
63 | i18nProviders, | |
64 | { provide: AuthStorageService, useValue: fakeAuthStorageService }, | |
65 | PgCategoryService, | |
66 | RefreshIntervalService | |
67 | ] | |
68 | }); | |
69 | ||
70 | beforeEach(() => { | |
71 | fakeFeatureTogglesService = spyOn(TestBed.get(FeatureTogglesService), 'get').and.returnValue( | |
72 | of({ | |
73 | rbd: true, | |
74 | mirroring: true, | |
75 | iscsi: true, | |
76 | cephfs: true, | |
77 | rgw: true | |
78 | }) | |
79 | ); | |
80 | fixture = TestBed.createComponent(HealthComponent); | |
81 | component = fixture.componentInstance; | |
82 | getHealthSpy = spyOn(TestBed.get(HealthService), 'getMinimalHealth'); | |
83 | getHealthSpy.and.returnValue(of(healthPayload)); | |
84 | }); | |
85 | ||
86 | it('should create', () => { | |
87 | expect(component).toBeTruthy(); | |
88 | }); | |
89 | ||
90 | it('should render all info groups and all info cards', () => { | |
91 | fixture.detectChanges(); | |
92 | ||
93 | const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group'); | |
94 | expect(infoGroups.length).toBe(3); | |
95 | ||
96 | const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card'); | |
97 | expect(infoCards.length).toBe(18); | |
98 | }); | |
99 | ||
100 | describe('features disabled', () => { | |
101 | beforeEach(() => { | |
102 | fakeFeatureTogglesService.and.returnValue( | |
103 | of({ | |
104 | rbd: false, | |
105 | mirroring: false, | |
106 | iscsi: false, | |
107 | cephfs: false, | |
108 | rgw: false | |
109 | }) | |
110 | ); | |
111 | fixture = TestBed.createComponent(HealthComponent); | |
112 | component = fixture.componentInstance; | |
113 | }); | |
114 | ||
115 | it('should not render cards related to disabled features', () => { | |
116 | fixture.detectChanges(); | |
117 | ||
118 | const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group'); | |
119 | expect(infoGroups.length).toBe(3); | |
120 | ||
121 | const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card'); | |
122 | expect(infoCards.length).toBe(15); | |
123 | }); | |
124 | }); | |
125 | ||
126 | it('should render all except "Status" group and cards', () => { | |
127 | const payload = _.cloneDeep(healthPayload); | |
128 | payload.health.status = ''; | |
129 | payload.mon_status = null; | |
130 | payload.osd_map = null; | |
131 | payload.mgr_map = null; | |
132 | payload.hosts = null; | |
133 | payload.rgw = null; | |
134 | payload.fs_map = null; | |
135 | payload.iscsi_daemons = null; | |
136 | ||
137 | getHealthSpy.and.returnValue(of(payload)); | |
138 | fixture.detectChanges(); | |
139 | ||
140 | const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group'); | |
141 | expect(infoGroups.length).toBe(2); | |
142 | ||
143 | const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card'); | |
144 | expect(infoCards.length).toBe(10); | |
145 | }); | |
146 | ||
147 | it('should render all except "Performance" group and cards', () => { | |
148 | const payload = _.cloneDeep(healthPayload); | |
149 | payload.scrub_status = ''; | |
150 | payload.client_perf = null; | |
151 | ||
152 | getHealthSpy.and.returnValue(of(payload)); | |
153 | fixture.detectChanges(); | |
154 | ||
155 | const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group'); | |
156 | expect(infoGroups.length).toBe(2); | |
157 | ||
158 | const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card'); | |
159 | expect(infoCards.length).toBe(13); | |
160 | }); | |
161 | ||
162 | it('should render all except "Capacity" group and cards', () => { | |
163 | const payload = _.cloneDeep(healthPayload); | |
164 | payload.pools = null; | |
165 | payload.df = null; | |
166 | payload.pg_info = null; | |
167 | ||
168 | getHealthSpy.and.returnValue(of(payload)); | |
169 | fixture.detectChanges(); | |
170 | ||
171 | const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group'); | |
172 | expect(infoGroups.length).toBe(2); | |
173 | ||
174 | const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card'); | |
175 | expect(infoCards.length).toBe(13); | |
176 | }); | |
177 | ||
178 | it('should render all groups and 1 card per group', () => { | |
179 | const payload = { hosts: 0, scrub_status: 'Inactive', pools: [] }; | |
180 | ||
181 | getHealthSpy.and.returnValue(of(payload)); | |
182 | fixture.detectChanges(); | |
183 | ||
184 | const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group'); | |
185 | expect(infoGroups.length).toBe(3); | |
186 | ||
187 | _.each(infoGroups, (infoGroup) => { | |
188 | expect(infoGroup.querySelectorAll('cd-info-card').length).toBe(1); | |
189 | }); | |
190 | }); | |
191 | ||
192 | it('should render "Cluster Status" card text that is not clickable', () => { | |
193 | fixture.detectChanges(); | |
194 | ||
195 | const clusterStatusCard = fixture.debugElement.query( | |
196 | By.css('cd-info-card[cardTitle="Cluster Status"]') | |
197 | ); | |
198 | const clickableContent = clusterStatusCard.query(By.css('.info-card-content-clickable')); | |
199 | expect(clickableContent).toBeNull(); | |
200 | expect(clusterStatusCard.nativeElement.textContent).toEqual(` ${healthPayload.health.status} `); | |
201 | }); | |
202 | ||
203 | it('should render "Cluster Status" card text that is clickable (popover)', () => { | |
204 | const payload = _.cloneDeep(healthPayload); | |
205 | payload.health['status'] = 'HEALTH_WARN'; | |
206 | payload.health['checks'] = [ | |
207 | { severity: 'HEALTH_WARN', type: 'WRN', summary: { message: 'fake warning' } } | |
208 | ]; | |
209 | ||
210 | getHealthSpy.and.returnValue(of(payload)); | |
211 | fixture.detectChanges(); | |
212 | ||
213 | expect(component.permissions.log.read).toBeTruthy(); | |
214 | ||
215 | const clusterStatusCard = fixture.debugElement.query( | |
216 | By.css('cd-info-card[cardTitle="Cluster Status"]') | |
217 | ); | |
218 | const clickableContent = clusterStatusCard.query(By.css('.info-card-content-clickable')); | |
219 | expect(clickableContent.nativeElement.textContent).toEqual(` ${payload.health.status} `); | |
220 | }); | |
221 | ||
222 | it('event binding "prepareReadWriteRatio" is called', () => { | |
223 | const prepareReadWriteRatio = spyOn(component, 'prepareReadWriteRatio'); | |
224 | ||
225 | const payload = _.cloneDeep(healthPayload); | |
226 | payload.client_perf['read_op_per_sec'] = 1; | |
227 | payload.client_perf['write_op_per_sec'] = 1; | |
228 | getHealthSpy.and.returnValue(of(payload)); | |
229 | fixture.detectChanges(); | |
230 | ||
231 | expect(prepareReadWriteRatio).toHaveBeenCalled(); | |
232 | }); | |
233 | ||
234 | it('event binding "prepareRawUsage" is called', () => { | |
235 | const prepareRawUsage = spyOn(component, 'prepareRawUsage'); | |
236 | ||
237 | fixture.detectChanges(); | |
238 | ||
239 | expect(prepareRawUsage).toHaveBeenCalled(); | |
240 | }); | |
241 | ||
242 | it('event binding "preparePgStatus" is called', () => { | |
243 | const preparePgStatus = spyOn(component, 'preparePgStatus'); | |
244 | ||
245 | fixture.detectChanges(); | |
246 | ||
247 | expect(preparePgStatus).toHaveBeenCalled(); | |
248 | }); | |
249 | ||
81eedcae TL |
250 | it('event binding "prepareObjects" is called', () => { |
251 | const prepareObjects = spyOn(component, 'prepareObjects'); | |
252 | ||
253 | fixture.detectChanges(); | |
254 | ||
255 | expect(prepareObjects).toHaveBeenCalled(); | |
256 | }); | |
257 | ||
11fdf7f2 | 258 | describe('preparePgStatus', () => { |
81eedcae TL |
259 | const calcPercentage = (data) => Math.round((data / 10) * 100) || 0; |
260 | ||
11fdf7f2 | 261 | const expectedChart = (data: number[]) => ({ |
81eedcae TL |
262 | labels: [ |
263 | `Clean (${calcPercentage(data[0])}%)`, | |
264 | `Working (${calcPercentage(data[1])}%)`, | |
265 | `Warning (${calcPercentage(data[2])}%)`, | |
266 | `Unknown (${calcPercentage(data[3])}%)` | |
11fdf7f2 | 267 | ], |
81eedcae | 268 | options: {}, |
11fdf7f2 TL |
269 | dataset: [{ data: data }] |
270 | }); | |
271 | ||
272 | it('gets no data', () => { | |
81eedcae TL |
273 | const chart = { dataset: [{}], options: {} }; |
274 | component.preparePgStatus(chart, { | |
eafe8130 | 275 | pg_info: {} |
81eedcae | 276 | }); |
11fdf7f2 TL |
277 | expect(chart).toEqual(expectedChart([undefined, undefined, undefined, undefined])); |
278 | }); | |
279 | ||
280 | it('gets data from all categories', () => { | |
81eedcae | 281 | const chart = { dataset: [{}], options: {} }; |
11fdf7f2 TL |
282 | component.preparePgStatus(chart, { |
283 | pg_info: { | |
284 | statuses: { | |
285 | 'clean+active+scrubbing+nonMappedState': 4, | |
286 | 'clean+active+scrubbing': 2, | |
287 | 'clean+active': 1, | |
288 | 'clean+active+scrubbing+down': 3 | |
289 | } | |
290 | } | |
291 | }); | |
292 | expect(chart).toEqual(expectedChart([1, 2, 3, 4])); | |
293 | }); | |
294 | }); | |
295 | ||
296 | describe('isClientReadWriteChartShowable', () => { | |
297 | beforeEach(() => { | |
298 | component.healthData = healthPayload; | |
299 | }); | |
300 | ||
301 | it('returns false', () => { | |
302 | component.healthData['client_perf'] = {}; | |
303 | ||
304 | expect(component.isClientReadWriteChartShowable()).toBeFalsy(); | |
305 | }); | |
306 | ||
307 | it('returns false', () => { | |
308 | component.healthData['client_perf'] = { read_op_per_sec: undefined, write_op_per_sec: 0 }; | |
309 | ||
310 | expect(component.isClientReadWriteChartShowable()).toBeFalsy(); | |
311 | }); | |
312 | ||
313 | it('returns true', () => { | |
314 | component.healthData['client_perf'] = { read_op_per_sec: 1, write_op_per_sec: undefined }; | |
315 | ||
316 | expect(component.isClientReadWriteChartShowable()).toBeTruthy(); | |
317 | }); | |
318 | ||
319 | it('returns true', () => { | |
320 | component.healthData['client_perf'] = { read_op_per_sec: 2, write_op_per_sec: 3 }; | |
321 | ||
322 | expect(component.isClientReadWriteChartShowable()).toBeTruthy(); | |
323 | }); | |
324 | }); | |
81eedcae TL |
325 | |
326 | describe('calcPercentage', () => { | |
327 | it('returns correct value', () => { | |
328 | expect(component['calcPercentage'](1, undefined)).toEqual(0); | |
329 | expect(component['calcPercentage'](1, null)).toEqual(0); | |
330 | expect(component['calcPercentage'](1, 0)).toEqual(0); | |
331 | expect(component['calcPercentage'](undefined, 1)).toEqual(0); | |
332 | expect(component['calcPercentage'](null, 1)).toEqual(0); | |
333 | expect(component['calcPercentage'](0, 1)).toEqual(0); | |
334 | expect(component['calcPercentage'](2.346, 10)).toEqual(23); | |
335 | expect(component['calcPercentage'](2.35, 10)).toEqual(24); | |
336 | }); | |
337 | }); | |
11fdf7f2 | 338 | }); |