]>
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 | ||
f67539c2 | 6 | import _ from 'lodash'; |
11fdf7f2 TL |
7 | import { of } from 'rxjs'; |
8 | ||
f67539c2 TL |
9 | import { PgCategoryService } from '~/app/ceph/shared/pg-category.service'; |
10 | import { HealthService } from '~/app/shared/api/health.service'; | |
b3b6e05e | 11 | import { CssHelper } from '~/app/shared/classes/css-helper'; |
f67539c2 TL |
12 | import { Permissions } from '~/app/shared/models/permissions'; |
13 | import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; | |
14 | import { FeatureTogglesService } from '~/app/shared/services/feature-toggles.service'; | |
15 | import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.service'; | |
16 | import { SharedModule } from '~/app/shared/shared.module'; | |
17 | import { configureTestBed } from '~/testing/unit-test-helper'; | |
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>; | |
9f95a23c TL |
28 | let getHealthSpy: jasmine.Spy; |
29 | const healthPayload: Record<string, any> = { | |
11fdf7f2 TL |
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, | |
801d1391 | 36 | fs_map: { filesystems: [], standbys: [] }, |
11fdf7f2 TL |
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 | }; | |
9f95a23c | 49 | let fakeFeatureTogglesService: jasmine.Spy; |
11fdf7f2 TL |
50 | |
51 | configureTestBed({ | |
f67539c2 | 52 | imports: [SharedModule, HttpClientTestingModule], |
11fdf7f2 TL |
53 | declarations: [ |
54 | HealthComponent, | |
55 | HealthPieComponent, | |
56 | MonSummaryPipe, | |
57 | OsdSummaryPipe, | |
58 | MdsSummaryPipe, | |
59 | MgrSummaryPipe | |
60 | ], | |
61 | schemas: [NO_ERRORS_SCHEMA], | |
62 | providers: [ | |
11fdf7f2 TL |
63 | { provide: AuthStorageService, useValue: fakeAuthStorageService }, |
64 | PgCategoryService, | |
b3b6e05e TL |
65 | RefreshIntervalService, |
66 | CssHelper | |
11fdf7f2 TL |
67 | ] |
68 | }); | |
69 | ||
70 | beforeEach(() => { | |
f67539c2 | 71 | fakeFeatureTogglesService = spyOn(TestBed.inject(FeatureTogglesService), 'get').and.returnValue( |
11fdf7f2 TL |
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; | |
f67539c2 | 82 | getHealthSpy = spyOn(TestBed.inject(HealthService), 'getMinimalHealth'); |
11fdf7f2 TL |
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'); | |
f91f0fd5 | 97 | expect(infoCards.length).toBe(17); |
11fdf7f2 TL |
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'); | |
f91f0fd5 | 122 | expect(infoCards.length).toBe(14); |
11fdf7f2 TL |
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'); | |
f91f0fd5 | 144 | expect(infoCards.length).toBe(9); |
11fdf7f2 TL |
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'); | |
f91f0fd5 | 175 | expect(infoCards.length).toBe(12); |
11fdf7f2 TL |
176 | }); |
177 | ||
178 | it('should render all groups and 1 card per group', () => { | |
9f95a23c | 179 | const payload: Record<string, any> = { hosts: 0, scrub_status: 'Inactive', pools: [] }; |
11fdf7f2 TL |
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', () => { | |
adb31ebb | 223 | const prepareReadWriteRatio = spyOn(component, 'prepareReadWriteRatio').and.callThrough(); |
11fdf7f2 TL |
224 | |
225 | const payload = _.cloneDeep(healthPayload); | |
226 | payload.client_perf['read_op_per_sec'] = 1; | |
adb31ebb | 227 | payload.client_perf['write_op_per_sec'] = 3; |
11fdf7f2 TL |
228 | getHealthSpy.and.returnValue(of(payload)); |
229 | fixture.detectChanges(); | |
230 | ||
231 | expect(prepareReadWriteRatio).toHaveBeenCalled(); | |
adb31ebb | 232 | expect(prepareReadWriteRatio.calls.mostRecent().args[0].dataset[0].data).toEqual([25, 75]); |
11fdf7f2 TL |
233 | }); |
234 | ||
235 | it('event binding "prepareRawUsage" is called', () => { | |
236 | const prepareRawUsage = spyOn(component, 'prepareRawUsage'); | |
237 | ||
238 | fixture.detectChanges(); | |
239 | ||
240 | expect(prepareRawUsage).toHaveBeenCalled(); | |
241 | }); | |
242 | ||
243 | it('event binding "preparePgStatus" is called', () => { | |
244 | const preparePgStatus = spyOn(component, 'preparePgStatus'); | |
245 | ||
246 | fixture.detectChanges(); | |
247 | ||
248 | expect(preparePgStatus).toHaveBeenCalled(); | |
249 | }); | |
250 | ||
81eedcae TL |
251 | it('event binding "prepareObjects" is called', () => { |
252 | const prepareObjects = spyOn(component, 'prepareObjects'); | |
253 | ||
254 | fixture.detectChanges(); | |
255 | ||
256 | expect(prepareObjects).toHaveBeenCalled(); | |
257 | }); | |
258 | ||
11fdf7f2 | 259 | describe('preparePgStatus', () => { |
f91f0fd5 | 260 | const expectedChart = (data: number[], label: string = null) => ({ |
81eedcae | 261 | labels: [ |
f91f0fd5 TL |
262 | `Clean: ${component['dimless'].transform(data[0])}`, |
263 | `Working: ${component['dimless'].transform(data[1])}`, | |
264 | `Warning: ${component['dimless'].transform(data[2])}`, | |
265 | `Unknown: ${component['dimless'].transform(data[3])}` | |
11fdf7f2 | 266 | ], |
81eedcae | 267 | options: {}, |
f91f0fd5 TL |
268 | dataset: [ |
269 | { | |
270 | data: data.map((i) => | |
271 | component['calcPercentage']( | |
272 | i, | |
273 | data.reduce((j, k) => j + k) | |
274 | ) | |
275 | ), | |
276 | label: label | |
277 | } | |
278 | ] | |
11fdf7f2 TL |
279 | }); |
280 | ||
281 | it('gets no data', () => { | |
81eedcae TL |
282 | const chart = { dataset: [{}], options: {} }; |
283 | component.preparePgStatus(chart, { | |
eafe8130 | 284 | pg_info: {} |
81eedcae | 285 | }); |
f91f0fd5 | 286 | expect(chart).toEqual(expectedChart([0, 0, 0, 0], '0\nPGs')); |
11fdf7f2 TL |
287 | }); |
288 | ||
289 | it('gets data from all categories', () => { | |
81eedcae | 290 | const chart = { dataset: [{}], options: {} }; |
11fdf7f2 TL |
291 | component.preparePgStatus(chart, { |
292 | pg_info: { | |
293 | statuses: { | |
294 | 'clean+active+scrubbing+nonMappedState': 4, | |
295 | 'clean+active+scrubbing': 2, | |
296 | 'clean+active': 1, | |
297 | 'clean+active+scrubbing+down': 3 | |
298 | } | |
299 | } | |
300 | }); | |
f91f0fd5 | 301 | expect(chart).toEqual(expectedChart([1, 2, 3, 4], '10\nPGs')); |
11fdf7f2 TL |
302 | }); |
303 | }); | |
304 | ||
305 | describe('isClientReadWriteChartShowable', () => { | |
306 | beforeEach(() => { | |
307 | component.healthData = healthPayload; | |
308 | }); | |
309 | ||
310 | it('returns false', () => { | |
311 | component.healthData['client_perf'] = {}; | |
312 | ||
313 | expect(component.isClientReadWriteChartShowable()).toBeFalsy(); | |
314 | }); | |
315 | ||
316 | it('returns false', () => { | |
317 | component.healthData['client_perf'] = { read_op_per_sec: undefined, write_op_per_sec: 0 }; | |
318 | ||
319 | expect(component.isClientReadWriteChartShowable()).toBeFalsy(); | |
320 | }); | |
321 | ||
322 | it('returns true', () => { | |
323 | component.healthData['client_perf'] = { read_op_per_sec: 1, write_op_per_sec: undefined }; | |
324 | ||
325 | expect(component.isClientReadWriteChartShowable()).toBeTruthy(); | |
326 | }); | |
327 | ||
328 | it('returns true', () => { | |
329 | component.healthData['client_perf'] = { read_op_per_sec: 2, write_op_per_sec: 3 }; | |
330 | ||
331 | expect(component.isClientReadWriteChartShowable()).toBeTruthy(); | |
332 | }); | |
333 | }); | |
81eedcae TL |
334 | |
335 | describe('calcPercentage', () => { | |
336 | it('returns correct value', () => { | |
337 | expect(component['calcPercentage'](1, undefined)).toEqual(0); | |
338 | expect(component['calcPercentage'](1, null)).toEqual(0); | |
339 | expect(component['calcPercentage'](1, 0)).toEqual(0); | |
340 | expect(component['calcPercentage'](undefined, 1)).toEqual(0); | |
341 | expect(component['calcPercentage'](null, 1)).toEqual(0); | |
342 | expect(component['calcPercentage'](0, 1)).toEqual(0); | |
343 | expect(component['calcPercentage'](2.346, 10)).toEqual(23); | |
344 | expect(component['calcPercentage'](2.35, 10)).toEqual(24); | |
345 | }); | |
346 | }); | |
11fdf7f2 | 347 | }); |