]> git.apps.os.sepia.ceph.com Git - ceph.git/blob
e85223c80e39ce950830871a5f9f6eddeb036f6f
[ceph.git] /
1 import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { ReactiveFormsModule } from '@angular/forms';
4
5 import { NgbActiveModal, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
6 import { ToastrModule } from 'ngx-toastr';
7 import { of as observableOf } from 'rxjs';
8
9 import { OsdService } from '~/app/shared/api/osd.service';
10 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
11 import { Flag } from '~/app/shared/models/flag';
12 import { NotificationService } from '~/app/shared/services/notification.service';
13 import { SharedModule } from '~/app/shared/shared.module';
14 import { configureTestBed } from '~/testing/unit-test-helper';
15 import { OsdFlagsIndivModalComponent } from './osd-flags-indiv-modal.component';
16
17 describe('OsdFlagsIndivModalComponent', () => {
18   let component: OsdFlagsIndivModalComponent;
19   let fixture: ComponentFixture<OsdFlagsIndivModalComponent>;
20   let httpTesting: HttpTestingController;
21   let osdService: OsdService;
22
23   configureTestBed({
24     imports: [
25       HttpClientTestingModule,
26       ReactiveFormsModule,
27       SharedModule,
28       ToastrModule.forRoot(),
29       NgbTooltipModule
30     ],
31     declarations: [OsdFlagsIndivModalComponent],
32     providers: [NgbActiveModal]
33   });
34
35   beforeEach(() => {
36     httpTesting = TestBed.inject(HttpTestingController);
37     fixture = TestBed.createComponent(OsdFlagsIndivModalComponent);
38     component = fixture.componentInstance;
39     osdService = TestBed.inject(OsdService);
40   });
41
42   it('should create', () => {
43     expect(component).toBeTruthy();
44   });
45
46   describe('getActivatedIndivFlags', () => {
47     function checkFlagsCount(
48       counts: { [key: string]: number },
49       expected: { [key: string]: number }
50     ) {
51       Object.entries(expected).forEach(([expectedKey, expectedValue]) => {
52         expect(counts[expectedKey]).toBe(expectedValue);
53       });
54     }
55
56     it('should count correctly if no flag has been set', () => {
57       component.selected = generateSelected();
58       const countedFlags = component.getActivatedIndivFlags();
59       checkFlagsCount(countedFlags, { noup: 0, nodown: 0, noin: 0, noout: 0 });
60     });
61
62     it('should count correctly if some of the flags have been set', () => {
63       component.selected = generateSelected([['noin'], ['noin', 'noout'], ['nodown']]);
64       const countedFlags = component.getActivatedIndivFlags();
65       checkFlagsCount(countedFlags, { noup: 0, nodown: 1, noin: 2, noout: 1 });
66     });
67   });
68
69   describe('changeValue', () => {
70     it('should change value correctly and set indeterminate to false', () => {
71       const testFlag = component.flags[0];
72       const value = testFlag.value;
73       component.changeValue(testFlag);
74       expect(testFlag.value).toBe(!value);
75       expect(testFlag.indeterminate).toBeFalsy();
76     });
77   });
78
79   describe('resetSelection', () => {
80     it('should set a new flags object by deep cloning the initial selection', () => {
81       component.resetSelection();
82       expect(component.flags === component.initialSelection).toBeFalsy();
83     });
84   });
85
86   describe('OSD single-select', () => {
87     beforeEach(() => {
88       component.selected = [{ osd: 0 }];
89     });
90
91     describe('ngOnInit', () => {
92       it('should clone flags as initial selection', () => {
93         expect(component.flags === component.initialSelection).toBeFalsy();
94       });
95
96       it('should initialize form correctly if no individual and global flags are set', () => {
97         component.selected[0]['state'] = ['exists', 'up'];
98         spyOn(osdService, 'getFlags').and.callFake(() => observableOf([]));
99         fixture.detectChanges();
100         checkFlags(component.flags);
101       });
102
103       it('should initialize form correctly if individual but no global flags are set', () => {
104         component.selected[0]['state'] = ['exists', 'noout', 'up'];
105         spyOn(osdService, 'getFlags').and.callFake(() => observableOf([]));
106         fixture.detectChanges();
107         const expected = {
108           noout: { value: true, clusterWide: false, indeterminate: false }
109         };
110         checkFlags(component.flags, expected);
111       });
112
113       it('should initialize form correctly if multiple individual but no global flags are set', () => {
114         component.selected[0]['state'] = ['exists', 'noin', 'noout', 'up'];
115         spyOn(osdService, 'getFlags').and.callFake(() => observableOf([]));
116         fixture.detectChanges();
117         const expected = {
118           noout: { value: true, clusterWide: false, indeterminate: false },
119           noin: { value: true, clusterWide: false, indeterminate: false }
120         };
121         checkFlags(component.flags, expected);
122       });
123
124       it('should initialize form correctly if no individual but global flags are set', () => {
125         component.selected[0]['state'] = ['exists', 'up'];
126         spyOn(osdService, 'getFlags').and.callFake(() => observableOf(['noout']));
127         fixture.detectChanges();
128         const expected = {
129           noout: { value: false, clusterWide: true, indeterminate: false }
130         };
131         checkFlags(component.flags, expected);
132       });
133     });
134
135     describe('submitAction', () => {
136       let notificationType: NotificationType;
137       let notificationService: NotificationService;
138       let bsModalRef: NgbActiveModal;
139       let flags: object;
140
141       beforeEach(() => {
142         notificationService = TestBed.inject(NotificationService);
143         spyOn(notificationService, 'show').and.callFake((type) => {
144           notificationType = type;
145         });
146         bsModalRef = TestBed.inject(NgbActiveModal);
147         spyOn(bsModalRef, 'close').and.callThrough();
148         flags = {
149           nodown: false,
150           noin: false,
151           noout: false,
152           noup: false
153         };
154       });
155
156       it('should submit an activated flag', () => {
157         const code = component.flags[0].code;
158         component.flags[0].value = true;
159         component.submitAction();
160         flags[code] = true;
161
162         const req = httpTesting.expectOne('api/osd/flags/individual');
163         req.flush({ flags, ids: [0] });
164         expect(req.request.body).toEqual({ flags, ids: [0] });
165         expect(notificationType).toBe(NotificationType.success);
166         expect(component.activeModal.close).toHaveBeenCalledTimes(1);
167       });
168
169       it('should submit multiple flags', () => {
170         const codes = [component.flags[0].code, component.flags[1].code];
171         component.flags[0].value = true;
172         component.flags[1].value = true;
173         component.submitAction();
174         flags[codes[0]] = true;
175         flags[codes[1]] = true;
176
177         const req = httpTesting.expectOne('api/osd/flags/individual');
178         req.flush({ flags, ids: [0] });
179         expect(req.request.body).toEqual({ flags, ids: [0] });
180         expect(notificationType).toBe(NotificationType.success);
181         expect(component.activeModal.close).toHaveBeenCalledTimes(1);
182       });
183
184       it('should hide modal if request fails', () => {
185         component.flags = [];
186         component.submitAction();
187         const req = httpTesting.expectOne('api/osd/flags/individual');
188         req.flush([], { status: 500, statusText: 'failure' });
189         expect(notificationService.show).toHaveBeenCalledTimes(0);
190         expect(component.activeModal.close).toHaveBeenCalledTimes(1);
191       });
192     });
193   });
194
195   describe('OSD multi-select', () => {
196     describe('ngOnInit', () => {
197       it('should initialize form correctly if same individual and no global flags are set', () => {
198         component.selected = generateSelected([['noin'], ['noin'], ['noin']]);
199         spyOn(osdService, 'getFlags').and.callFake(() => observableOf([]));
200         fixture.detectChanges();
201         const expected = {
202           noin: { value: true, clusterWide: false, indeterminate: false }
203         };
204         checkFlags(component.flags, expected);
205       });
206
207       it('should initialize form correctly if different individual and no global flags are set', () => {
208         component.selected = generateSelected([['noin'], ['noout'], ['noin']]);
209         spyOn(osdService, 'getFlags').and.callFake(() => observableOf([]));
210         fixture.detectChanges();
211         const expected = {
212           noin: { value: false, clusterWide: false, indeterminate: true },
213           noout: { value: false, clusterWide: false, indeterminate: true }
214         };
215         checkFlags(component.flags, expected);
216       });
217
218       it('should initialize form correctly if different and same individual and no global flags are set', () => {
219         component.selected = generateSelected([
220           ['noin', 'nodown'],
221           ['noout', 'nodown'],
222           ['noin', 'nodown']
223         ]);
224         spyOn(osdService, 'getFlags').and.callFake(() => observableOf([]));
225         fixture.detectChanges();
226         const expected = {
227           noin: { value: false, clusterWide: false, indeterminate: true },
228           noout: { value: false, clusterWide: false, indeterminate: true },
229           nodown: { value: true, clusterWide: false, indeterminate: false }
230         };
231         checkFlags(component.flags, expected);
232       });
233
234       it('should initialize form correctly if a flag is set for all OSDs individually and globally', () => {
235         component.selected = generateSelected([
236           ['noin', 'nodown'],
237           ['noout', 'nodown'],
238           ['noin', 'nodown']
239         ]);
240         spyOn(osdService, 'getFlags').and.callFake(() => observableOf(['noout']));
241         fixture.detectChanges();
242         const expected = {
243           noin: { value: false, clusterWide: false, indeterminate: true },
244           noout: { value: false, clusterWide: true, indeterminate: true },
245           nodown: { value: true, clusterWide: false, indeterminate: false }
246         };
247         checkFlags(component.flags, expected);
248       });
249
250       it('should initialize form correctly if different individual and global flags are set', () => {
251         component.selected = generateSelected([
252           ['noin', 'nodown', 'noout'],
253           ['noout', 'nodown'],
254           ['noin', 'nodown', 'noout']
255         ]);
256         spyOn(osdService, 'getFlags').and.callFake(() => observableOf(['noout']));
257         fixture.detectChanges();
258         const expected = {
259           noin: { value: false, clusterWide: false, indeterminate: true },
260           noout: { value: true, clusterWide: true, indeterminate: false },
261           nodown: { value: true, clusterWide: false, indeterminate: false }
262         };
263         checkFlags(component.flags, expected);
264       });
265     });
266
267     describe('submitAction', () => {
268       let notificationType: NotificationType;
269       let notificationService: NotificationService;
270       let bsModalRef: NgbActiveModal;
271       let flags: object;
272
273       beforeEach(() => {
274         notificationService = TestBed.inject(NotificationService);
275         spyOn(notificationService, 'show').and.callFake((type) => {
276           notificationType = type;
277         });
278         bsModalRef = TestBed.inject(NgbActiveModal);
279         spyOn(bsModalRef, 'close').and.callThrough();
280         flags = {
281           nodown: false,
282           noin: false,
283           noout: false,
284           noup: false
285         };
286       });
287
288       it('should submit an activated flag for multiple OSDs', () => {
289         component.selected = generateSelected();
290         const code = component.flags[0].code;
291         const submittedIds = [0, 1, 2];
292         component.flags[0].value = true;
293         component.submitAction();
294         flags[code] = true;
295
296         const req = httpTesting.expectOne('api/osd/flags/individual');
297         req.flush({ flags, ids: submittedIds });
298         expect(req.request.body).toEqual({ flags, ids: submittedIds });
299         expect(notificationType).toBe(NotificationType.success);
300         expect(component.activeModal.close).toHaveBeenCalledTimes(1);
301       });
302
303       it('should submit multiple flags for multiple OSDs', () => {
304         component.selected = generateSelected();
305         const codes = [component.flags[0].code, component.flags[1].code];
306         const submittedIds = [0, 1, 2];
307         component.flags[0].value = true;
308         component.flags[1].value = true;
309         component.submitAction();
310         flags[codes[0]] = true;
311         flags[codes[1]] = true;
312
313         const req = httpTesting.expectOne('api/osd/flags/individual');
314         req.flush({ flags, ids: submittedIds });
315         expect(req.request.body).toEqual({ flags, ids: submittedIds });
316         expect(notificationType).toBe(NotificationType.success);
317         expect(component.activeModal.close).toHaveBeenCalledTimes(1);
318       });
319     });
320   });
321
322   function checkFlags(flags: Flag[], expected: object = {}) {
323     flags.forEach((flag) => {
324       let value = false;
325       let clusterWide = false;
326       let indeterminate = false;
327       if (Object.keys(expected).includes(flag.code)) {
328         value = expected[flag.code]['value'];
329         clusterWide = expected[flag.code]['clusterWide'];
330         indeterminate = expected[flag.code]['indeterminate'];
331       }
332       expect(flag.value).toBe(value);
333       expect(flag.clusterWide).toBe(clusterWide);
334       expect(flag.indeterminate).toBe(indeterminate);
335     });
336   }
337
338   function generateSelected(flags: string[][] = []) {
339     const defaultFlags = ['exists', 'up'];
340     const osds = [];
341     const count = flags.length || 3;
342     for (let i = 0; i < count; i++) {
343       const osd = {
344         osd: i,
345         state: defaultFlags.concat(flags[i]) || defaultFlags
346       };
347       osds.push(osd);
348     }
349     return osds;
350   }
351 });