]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { HttpClientTestingModule } from '@angular/common/http/testing'; |
2 | import { ComponentFixture, TestBed } from '@angular/core/testing'; | |
3 | import { RouterTestingModule } from '@angular/router/testing'; | |
4 | ||
5 | import { ToastModule } from 'ng2-toastr'; | |
6 | import { BsModalService } from 'ngx-bootstrap/modal'; | |
7 | import { TabsModule } from 'ngx-bootstrap/tabs'; | |
8 | import { of } from 'rxjs'; | |
9 | ||
10 | import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper'; | |
11 | import { PoolService } from '../../../shared/api/pool.service'; | |
12 | import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component'; | |
13 | import { ExecutingTask } from '../../../shared/models/executing-task'; | |
14 | import { SummaryService } from '../../../shared/services/summary.service'; | |
15 | import { TaskWrapperService } from '../../../shared/services/task-wrapper.service'; | |
16 | import { SharedModule } from '../../../shared/shared.module'; | |
17 | import { RbdConfigurationListComponent } from '../../block/rbd-configuration-list/rbd-configuration-list.component'; | |
18 | import { PgCategoryService } from '../../shared/pg-category.service'; | |
19 | import { Pool } from '../pool'; | |
20 | import { PoolDetailsComponent } from '../pool-details/pool-details.component'; | |
21 | import { PoolListComponent } from './pool-list.component'; | |
22 | ||
23 | describe('PoolListComponent', () => { | |
24 | let component: PoolListComponent; | |
25 | let fixture: ComponentFixture<PoolListComponent>; | |
26 | let poolService: PoolService; | |
27 | ||
28 | const addPool = (pools, name, id) => { | |
29 | const pool = new Pool(name); | |
30 | pool.pool = id; | |
31 | pool.pg_num = 256; | |
32 | pools.push(pool); | |
33 | }; | |
34 | ||
35 | const setUpPools = (pools) => { | |
36 | addPool(pools, 'a', 0); | |
37 | addPool(pools, 'b', 1); | |
38 | addPool(pools, 'c', 2); | |
39 | component.pools = pools; | |
40 | }; | |
41 | ||
42 | configureTestBed({ | |
43 | declarations: [PoolListComponent, PoolDetailsComponent, RbdConfigurationListComponent], | |
44 | imports: [ | |
45 | SharedModule, | |
46 | ToastModule.forRoot(), | |
47 | RouterTestingModule, | |
48 | TabsModule.forRoot(), | |
49 | HttpClientTestingModule | |
50 | ], | |
51 | providers: [i18nProviders, PgCategoryService] | |
52 | }); | |
53 | ||
54 | beforeEach(() => { | |
55 | fixture = TestBed.createComponent(PoolListComponent); | |
56 | component = fixture.componentInstance; | |
57 | component.permissions.pool.read = true; | |
58 | poolService = TestBed.get(PoolService); | |
59 | fixture.detectChanges(); | |
60 | }); | |
61 | ||
62 | it('should create', () => { | |
63 | expect(component).toBeTruthy(); | |
64 | }); | |
65 | ||
81eedcae TL |
66 | it('should have columns that are sortable', () => { |
67 | expect(component.columns.every((column) => Boolean(column.prop))).toBeTruthy(); | |
68 | }); | |
69 | ||
11fdf7f2 TL |
70 | describe('pool deletion', () => { |
71 | let taskWrapper: TaskWrapperService; | |
72 | ||
73 | const setSelectedPool = (poolName: string) => { | |
74 | component.selection.selected = [{ pool_name: poolName }]; | |
75 | component.selection.update(); | |
76 | }; | |
77 | ||
78 | const callDeletion = () => { | |
79 | component.deletePoolModal(); | |
80 | const deletion: CriticalConfirmationModalComponent = component.modalRef.content; | |
81 | deletion.submitActionObservable(); | |
82 | }; | |
83 | ||
84 | const testPoolDeletion = (poolName) => { | |
85 | setSelectedPool(poolName); | |
86 | callDeletion(); | |
87 | expect(poolService.delete).toHaveBeenCalledWith(poolName); | |
88 | expect(taskWrapper.wrapTaskAroundCall).toHaveBeenCalledWith({ | |
89 | task: { | |
90 | name: 'pool/delete', | |
91 | metadata: { | |
92 | pool_name: poolName | |
93 | } | |
94 | }, | |
95 | call: undefined // because of stub | |
96 | }); | |
97 | }; | |
98 | ||
99 | beforeEach(() => { | |
100 | spyOn(TestBed.get(BsModalService), 'show').and.callFake((deletionClass, config) => { | |
101 | return { | |
102 | content: Object.assign(new deletionClass(), config.initialState) | |
103 | }; | |
104 | }); | |
105 | spyOn(poolService, 'delete').and.stub(); | |
106 | taskWrapper = TestBed.get(TaskWrapperService); | |
107 | spyOn(taskWrapper, 'wrapTaskAroundCall').and.callThrough(); | |
108 | }); | |
109 | ||
110 | it('should pool deletion with two different pools', () => { | |
111 | testPoolDeletion('somePoolName'); | |
112 | testPoolDeletion('aDifferentPoolName'); | |
113 | }); | |
114 | }); | |
115 | ||
116 | describe('handling of executing tasks', () => { | |
117 | let pools: Pool[]; | |
118 | let summaryService: SummaryService; | |
119 | ||
120 | const addTask = (name: string, pool: string) => { | |
121 | const task = new ExecutingTask(); | |
122 | task.name = name; | |
123 | task.metadata = { pool_name: pool }; | |
124 | summaryService.addRunningTask(task); | |
125 | }; | |
126 | ||
127 | beforeEach(() => { | |
128 | summaryService = TestBed.get(SummaryService); | |
129 | summaryService['summaryDataSource'].next({ executing_tasks: [], finished_tasks: [] }); | |
130 | pools = []; | |
131 | setUpPools(pools); | |
132 | spyOn(poolService, 'getList').and.callFake(() => of(pools)); | |
133 | fixture.detectChanges(); | |
134 | }); | |
135 | ||
136 | it('gets all pools without executing pools', () => { | |
137 | expect(component.pools.length).toBe(3); | |
138 | expect(component.pools.every((pool) => !pool.executingTasks)).toBeTruthy(); | |
139 | }); | |
140 | ||
141 | it('gets a pool from a task during creation', () => { | |
142 | addTask('pool/create', 'd'); | |
143 | expect(component.pools.length).toBe(4); | |
144 | expect(component.pools[3].cdExecuting).toBe('Creating'); | |
145 | }); | |
146 | ||
147 | it('gets all pools with one executing pools', () => { | |
148 | addTask('pool/create', 'a'); | |
149 | expect(component.pools.length).toBe(3); | |
150 | expect(component.pools[0].cdExecuting).toBe('Creating'); | |
151 | expect(component.pools[1].cdExecuting).toBeFalsy(); | |
152 | expect(component.pools[2].cdExecuting).toBeFalsy(); | |
153 | }); | |
154 | ||
155 | it('gets all pools with multiple executing pools', () => { | |
156 | addTask('pool/create', 'a'); | |
157 | addTask('pool/edit', 'a'); | |
158 | addTask('pool/delete', 'a'); | |
159 | addTask('pool/edit', 'b'); | |
160 | addTask('pool/delete', 'b'); | |
161 | addTask('pool/delete', 'c'); | |
162 | expect(component.pools.length).toBe(3); | |
163 | expect(component.pools[0].cdExecuting).toBe('Creating, Updating, Deleting'); | |
164 | expect(component.pools[1].cdExecuting).toBe('Updating, Deleting'); | |
165 | expect(component.pools[2].cdExecuting).toBe('Deleting'); | |
166 | }); | |
167 | ||
168 | it('gets all pools with multiple executing tasks (not only pool tasks)', () => { | |
169 | addTask('rbd/create', 'a'); | |
170 | addTask('rbd/edit', 'a'); | |
171 | addTask('pool/delete', 'a'); | |
172 | addTask('pool/edit', 'b'); | |
173 | addTask('rbd/delete', 'b'); | |
174 | addTask('rbd/delete', 'c'); | |
175 | expect(component.pools.length).toBe(3); | |
176 | expect(component.pools[0].cdExecuting).toBe('Deleting'); | |
177 | expect(component.pools[1].cdExecuting).toBe('Updating'); | |
178 | expect(component.pools[2].cdExecuting).toBeFalsy(); | |
179 | }); | |
180 | }); | |
181 | ||
182 | describe('getPgStatusCellClass', () => { | |
183 | const testMethod = (value, expected) => | |
184 | expect(component.getPgStatusCellClass('', '', value)).toEqual({ | |
185 | 'text-right': true, | |
186 | [expected]: true | |
187 | }); | |
188 | ||
189 | it('pg-clean', () => { | |
190 | testMethod('8 active+clean', 'pg-clean'); | |
191 | }); | |
192 | ||
193 | it('pg-working', () => { | |
194 | testMethod(' 8 active+clean+scrubbing+deep, 255 active+clean ', 'pg-working'); | |
195 | }); | |
196 | ||
197 | it('pg-warning', () => { | |
198 | testMethod('8 active+clean+scrubbing+down', 'pg-warning'); | |
199 | testMethod('8 active+clean+scrubbing+down+nonMappedState', 'pg-warning'); | |
200 | }); | |
201 | ||
202 | it('pg-unknown', () => { | |
203 | testMethod('8 active+clean+scrubbing+nonMappedState', 'pg-unknown'); | |
204 | testMethod('8 ', 'pg-unknown'); | |
205 | testMethod('', 'pg-unknown'); | |
206 | }); | |
207 | }); | |
208 | ||
209 | describe('transformPoolsData', () => { | |
210 | it('transforms pools data correctly', () => { | |
211 | const pools = [ | |
212 | { | |
81eedcae TL |
213 | stats: { |
214 | bytes_used: { latest: 5, rate: 0, series: [] }, | |
215 | max_avail: { latest: 15, rate: 0, series: [] }, | |
216 | rd_bytes: { latest: 6, rate: 4, series: [[0, 2], [1, 6]] } | |
217 | }, | |
11fdf7f2 TL |
218 | pg_status: { 'active+clean': 8, down: 2 } |
219 | } | |
220 | ]; | |
221 | const expected = [ | |
222 | { | |
223 | cdIsBinary: true, | |
224 | pg_status: '8 active+clean, 2 down', | |
225 | stats: { | |
81eedcae TL |
226 | bytes_used: { latest: 5, rate: 0, series: [] }, |
227 | max_avail: { latest: 15, rate: 0, series: [] }, | |
11fdf7f2 TL |
228 | rd: { latest: 0, rate: 0, series: [] }, |
229 | rd_bytes: { latest: 6, rate: 4, series: [2, 6] }, | |
230 | wr: { latest: 0, rate: 0, series: [] }, | |
231 | wr_bytes: { latest: 0, rate: 0, series: [] } | |
81eedcae TL |
232 | }, |
233 | usage: 0.25 | |
11fdf7f2 TL |
234 | } |
235 | ]; | |
81eedcae TL |
236 | expect(component.transformPoolsData(pools)).toEqual(expected); |
237 | }); | |
11fdf7f2 | 238 | |
81eedcae TL |
239 | it('transforms pools data correctly if stats are missing', () => { |
240 | const pools = [{}]; | |
241 | const expected = [ | |
242 | { | |
243 | cdIsBinary: true, | |
244 | pg_status: '', | |
245 | stats: { | |
246 | bytes_used: { latest: 0, rate: 0, series: [] }, | |
247 | max_avail: { latest: 0, rate: 0, series: [] }, | |
248 | rd: { latest: 0, rate: 0, series: [] }, | |
249 | rd_bytes: { latest: 0, rate: 0, series: [] }, | |
250 | wr: { latest: 0, rate: 0, series: [] }, | |
251 | wr_bytes: { latest: 0, rate: 0, series: [] } | |
252 | }, | |
253 | usage: 0 | |
254 | } | |
255 | ]; | |
11fdf7f2 TL |
256 | expect(component.transformPoolsData(pools)).toEqual(expected); |
257 | }); | |
258 | ||
259 | it('transforms empty pools data correctly', () => { | |
260 | const pools = undefined; | |
261 | const expected = undefined; | |
11fdf7f2 TL |
262 | expect(component.transformPoolsData(pools)).toEqual(expected); |
263 | }); | |
264 | }); | |
265 | ||
266 | describe('transformPgStatus', () => { | |
267 | it('returns status groups correctly', () => { | |
268 | const pgStatus = { 'active+clean': 8 }; | |
269 | const expected = '8 active+clean'; | |
270 | ||
271 | expect(component.transformPgStatus(pgStatus)).toEqual(expected); | |
272 | }); | |
273 | ||
274 | it('returns separated status groups', () => { | |
275 | const pgStatus = { 'active+clean': 8, down: 2 }; | |
276 | const expected = '8 active+clean, 2 down'; | |
277 | ||
278 | expect(component.transformPgStatus(pgStatus)).toEqual(expected); | |
279 | }); | |
280 | ||
281 | it('returns separated statuses correctly', () => { | |
282 | const pgStatus = { active: 8, down: 2 }; | |
283 | const expected = '8 active, 2 down'; | |
284 | ||
285 | expect(component.transformPgStatus(pgStatus)).toEqual(expected); | |
286 | }); | |
287 | ||
288 | it('returns empty string', () => { | |
289 | const pgStatus = undefined; | |
290 | const expected = ''; | |
291 | ||
292 | expect(component.transformPgStatus(pgStatus)).toEqual(expected); | |
293 | }); | |
294 | }); | |
295 | ||
296 | describe('getPoolDetails', () => { | |
297 | it('returns pool details corretly', () => { | |
298 | const pool = { prop1: 1, cdIsBinary: true, prop2: 2, cdExecuting: true, prop3: 3 }; | |
299 | const expected = { prop1: 1, prop2: 2, prop3: 3 }; | |
300 | ||
301 | expect(component.getPoolDetails(pool)).toEqual(expected); | |
302 | }); | |
303 | }); | |
304 | ||
305 | describe('getSelectionTiers', () => { | |
306 | let pools: Pool[]; | |
307 | const setSelectionTiers = (tiers: number[]) => { | |
308 | component.selection.selected = [ | |
309 | { | |
310 | tiers | |
311 | } | |
312 | ]; | |
313 | component.selection.update(); | |
314 | component.getSelectionTiers(); | |
315 | }; | |
316 | ||
317 | beforeEach(() => { | |
318 | pools = []; | |
319 | setUpPools(pools); | |
320 | }); | |
321 | ||
322 | it('should select multiple existing cache tiers', () => { | |
323 | setSelectionTiers([0, 1, 2]); | |
324 | expect(component.selectionCacheTiers).toEqual(pools); | |
325 | }); | |
326 | ||
327 | it('should select correct existing cache tier', () => { | |
328 | setSelectionTiers([0]); | |
329 | expect(component.selectionCacheTiers).toEqual([{ pg_num: 256, pool: 0, pool_name: 'a' }]); | |
330 | }); | |
331 | ||
332 | it('should not select cache tier if id is invalid', () => { | |
333 | setSelectionTiers([-1]); | |
334 | expect(component.selectionCacheTiers).toEqual([]); | |
335 | }); | |
336 | ||
337 | it('should not select cache tier if empty', () => { | |
338 | setSelectionTiers([]); | |
339 | expect(component.selectionCacheTiers).toEqual([]); | |
340 | }); | |
341 | ||
342 | it('should be able to selected one pool with multiple tiers, than with a single tier, than with no tiers', () => { | |
343 | setSelectionTiers([0, 1, 2]); | |
344 | expect(component.selectionCacheTiers).toEqual(pools); | |
345 | setSelectionTiers([0]); | |
346 | expect(component.selectionCacheTiers).toEqual([{ pg_num: 256, pool: 0, pool_name: 'a' }]); | |
347 | setSelectionTiers([]); | |
348 | expect(component.selectionCacheTiers).toEqual([]); | |
349 | }); | |
350 | }); | |
351 | }); |