1 import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { ReactiveFormsModule } from '@angular/forms';
5 import { NgbActiveModal, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
6 import { ToastrModule } from 'ngx-toastr';
7 import { of as observableOf } from 'rxjs';
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';
17 describe('OsdFlagsIndivModalComponent', () => {
18 let component: OsdFlagsIndivModalComponent;
19 let fixture: ComponentFixture<OsdFlagsIndivModalComponent>;
20 let httpTesting: HttpTestingController;
21 let osdService: OsdService;
25 HttpClientTestingModule,
28 ToastrModule.forRoot(),
31 declarations: [OsdFlagsIndivModalComponent],
32 providers: [NgbActiveModal]
36 httpTesting = TestBed.inject(HttpTestingController);
37 fixture = TestBed.createComponent(OsdFlagsIndivModalComponent);
38 component = fixture.componentInstance;
39 osdService = TestBed.inject(OsdService);
42 it('should create', () => {
43 expect(component).toBeTruthy();
46 describe('getActivatedIndivFlags', () => {
47 function checkFlagsCount(
48 counts: { [key: string]: number },
49 expected: { [key: string]: number }
51 Object.entries(expected).forEach(([expectedKey, expectedValue]) => {
52 expect(counts[expectedKey]).toBe(expectedValue);
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 });
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 });
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();
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();
86 describe('OSD single-select', () => {
88 component.selected = [{ osd: 0 }];
91 describe('ngOnInit', () => {
92 it('should clone flags as initial selection', () => {
93 expect(component.flags === component.initialSelection).toBeFalsy();
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);
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();
108 noout: { value: true, clusterWide: false, indeterminate: false }
110 checkFlags(component.flags, expected);
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();
118 noout: { value: true, clusterWide: false, indeterminate: false },
119 noin: { value: true, clusterWide: false, indeterminate: false }
121 checkFlags(component.flags, expected);
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();
129 noout: { value: false, clusterWide: true, indeterminate: false }
131 checkFlags(component.flags, expected);
135 describe('submitAction', () => {
136 let notificationType: NotificationType;
137 let notificationService: NotificationService;
138 let bsModalRef: NgbActiveModal;
142 notificationService = TestBed.inject(NotificationService);
143 spyOn(notificationService, 'show').and.callFake((type) => {
144 notificationType = type;
146 bsModalRef = TestBed.inject(NgbActiveModal);
147 spyOn(bsModalRef, 'close').and.callThrough();
156 it('should submit an activated flag', () => {
157 const code = component.flags[0].code;
158 component.flags[0].value = true;
159 component.submitAction();
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);
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;
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);
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);
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();
202 noin: { value: true, clusterWide: false, indeterminate: false }
204 checkFlags(component.flags, expected);
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();
212 noin: { value: false, clusterWide: false, indeterminate: true },
213 noout: { value: false, clusterWide: false, indeterminate: true }
215 checkFlags(component.flags, expected);
218 it('should initialize form correctly if different and same individual and no global flags are set', () => {
219 component.selected = generateSelected([
224 spyOn(osdService, 'getFlags').and.callFake(() => observableOf([]));
225 fixture.detectChanges();
227 noin: { value: false, clusterWide: false, indeterminate: true },
228 noout: { value: false, clusterWide: false, indeterminate: true },
229 nodown: { value: true, clusterWide: false, indeterminate: false }
231 checkFlags(component.flags, expected);
234 it('should initialize form correctly if a flag is set for all OSDs individually and globally', () => {
235 component.selected = generateSelected([
240 spyOn(osdService, 'getFlags').and.callFake(() => observableOf(['noout']));
241 fixture.detectChanges();
243 noin: { value: false, clusterWide: false, indeterminate: true },
244 noout: { value: false, clusterWide: true, indeterminate: true },
245 nodown: { value: true, clusterWide: false, indeterminate: false }
247 checkFlags(component.flags, expected);
250 it('should initialize form correctly if different individual and global flags are set', () => {
251 component.selected = generateSelected([
252 ['noin', 'nodown', 'noout'],
254 ['noin', 'nodown', 'noout']
256 spyOn(osdService, 'getFlags').and.callFake(() => observableOf(['noout']));
257 fixture.detectChanges();
259 noin: { value: false, clusterWide: false, indeterminate: true },
260 noout: { value: true, clusterWide: true, indeterminate: false },
261 nodown: { value: true, clusterWide: false, indeterminate: false }
263 checkFlags(component.flags, expected);
267 describe('submitAction', () => {
268 let notificationType: NotificationType;
269 let notificationService: NotificationService;
270 let bsModalRef: NgbActiveModal;
274 notificationService = TestBed.inject(NotificationService);
275 spyOn(notificationService, 'show').and.callFake((type) => {
276 notificationType = type;
278 bsModalRef = TestBed.inject(NgbActiveModal);
279 spyOn(bsModalRef, 'close').and.callThrough();
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();
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);
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;
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);
322 function checkFlags(flags: Flag[], expected: object = {}) {
323 flags.forEach((flag) => {
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'];
332 expect(flag.value).toBe(value);
333 expect(flag.clusterWide).toBe(clusterWide);
334 expect(flag.indeterminate).toBe(indeterminate);
338 function generateSelected(flags: string[][] = []) {
339 const defaultFlags = ['exists', 'up'];
341 const count = flags.length || 3;
342 for (let i = 0; i < count; i++) {
345 state: defaultFlags.concat(flags[i]) || defaultFlags