]> git.apps.os.sepia.ceph.com Git - ceph.git/blob
10eeb061dfb7018ddcf2db0c29fba351b69f4d91
[ceph.git] /
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { By } from '@angular/platform-browser';
4 import { RouterTestingModule } from '@angular/router/testing';
5
6 import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
7 import { BsModalRef, BsModalService, ModalModule } from 'ngx-bootstrap/modal';
8 import { TabsModule } from 'ngx-bootstrap/tabs';
9 import { ToastrModule } from 'ngx-toastr';
10 import { of } from 'rxjs';
11
12 import {
13   configureTestBed,
14   i18nProviders,
15   PermissionHelper
16 } from '../../../../../testing/unit-test-helper';
17 import { PrometheusService } from '../../../../shared/api/prometheus.service';
18 import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
19 import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
20 import { NotificationType } from '../../../../shared/enum/notification-type.enum';
21 import { NotificationService } from '../../../../shared/services/notification.service';
22 import { SharedModule } from '../../../../shared/shared.module';
23 import { PrometheusTabsComponent } from '../prometheus-tabs/prometheus-tabs.component';
24 import { SilenceListComponent } from './silence-list.component';
25
26 describe('SilenceListComponent', () => {
27   let component: SilenceListComponent;
28   let fixture: ComponentFixture<SilenceListComponent>;
29   let prometheusService: PrometheusService;
30
31   configureTestBed({
32     imports: [
33       SharedModule,
34       BsDropdownModule.forRoot(),
35       TabsModule.forRoot(),
36       ModalModule.forRoot(),
37       ToastrModule.forRoot(),
38       RouterTestingModule,
39       HttpClientTestingModule
40     ],
41     declarations: [SilenceListComponent, PrometheusTabsComponent],
42     providers: [i18nProviders]
43   });
44
45   beforeEach(() => {
46     fixture = TestBed.createComponent(SilenceListComponent);
47     component = fixture.componentInstance;
48     prometheusService = TestBed.get(PrometheusService);
49   });
50
51   it('should create', () => {
52     fixture.detectChanges();
53     expect(component).toBeTruthy();
54   });
55
56   describe('show action buttons and drop down actions depending on permissions', () => {
57     let tableActions: TableActionsComponent;
58     let scenario: { fn; empty; single };
59     let permissionHelper: PermissionHelper;
60     let silenceState: string;
61
62     const getTableActionComponent = (): TableActionsComponent => {
63       fixture.detectChanges();
64       return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
65     };
66
67     const setSilenceState = (state) => {
68       silenceState = state;
69     };
70
71     const testNonExpiredSilenceScenario = () => {
72       setSilenceState('active');
73       permissionHelper.testScenarios(scenario);
74       setSilenceState('pending');
75       permissionHelper.testScenarios(scenario);
76     };
77
78     beforeEach(() => {
79       permissionHelper = new PermissionHelper(component.permission, () =>
80         getTableActionComponent()
81       );
82       permissionHelper.createSelection = () => ({ status: { state: silenceState } });
83       scenario = {
84         fn: () => tableActions.getCurrentButton().name,
85         single: 'Edit',
86         empty: 'Create'
87       };
88     });
89
90     describe('with all', () => {
91       beforeEach(() => {
92         tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
93       });
94
95       it(`shows 'Edit' for single non expired silence else 'Create' as main action`, () => {
96         scenario.single = 'Edit';
97         testNonExpiredSilenceScenario();
98       });
99
100       it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
101         scenario.single = 'Recreate';
102         setSilenceState('expired');
103         permissionHelper.testScenarios(scenario);
104       });
105
106       it('can use all actions', () => {
107         expect(tableActions.tableActions.length).toBe(4);
108         expect(tableActions.tableActions).toEqual(component.tableActions);
109       });
110     });
111
112     describe('with read, create and update', () => {
113       beforeEach(() => {
114         tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
115       });
116
117       it(`shows 'Edit' for single non expired silence else 'Create' as main action`, () => {
118         scenario.single = 'Edit';
119         testNonExpiredSilenceScenario();
120       });
121
122       it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
123         scenario.single = 'Recreate';
124         setSilenceState('expired');
125         permissionHelper.testScenarios(scenario);
126       });
127
128       it(`can use all actions except for 'Expire'`, () => {
129         expect(tableActions.tableActions.length).toBe(3);
130         expect(tableActions.tableActions).toEqual([
131           component.tableActions[0],
132           component.tableActions[1],
133           component.tableActions[2]
134         ]);
135       });
136     });
137
138     describe('with read, create and delete', () => {
139       beforeEach(() => {
140         tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
141       });
142
143       it(`shows 'Expire' for single non expired silence else 'Create' as main action`, () => {
144         scenario.single = 'Expire';
145         testNonExpiredSilenceScenario();
146       });
147
148       it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
149         scenario.single = 'Recreate';
150         setSilenceState('expired');
151         permissionHelper.testScenarios(scenario);
152       });
153
154       it(`can use 'Create' and 'Expire' action`, () => {
155         expect(tableActions.tableActions.length).toBe(3);
156         expect(tableActions.tableActions).toEqual([
157           component.tableActions[0],
158           component.tableActions[1],
159           component.tableActions[3]
160         ]);
161       });
162     });
163
164     describe('with read, edit and delete', () => {
165       beforeEach(() => {
166         tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
167       });
168
169       it(`shows always 'Edit' as main action for any state`, () => {
170         scenario.single = 'Edit';
171         scenario.empty = 'Edit';
172         testNonExpiredSilenceScenario();
173         setSilenceState('expired');
174         permissionHelper.testScenarios(scenario);
175       });
176
177       it(`can use 'Edit' and 'Expire' action`, () => {
178         expect(tableActions.tableActions.length).toBe(2);
179         expect(tableActions.tableActions).toEqual([
180           component.tableActions[2],
181           component.tableActions[3]
182         ]);
183       });
184     });
185
186     describe('with read and create', () => {
187       beforeEach(() => {
188         tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
189       });
190
191       it(`shows always 'Create' as main action for single non expired silences`, () => {
192         scenario.single = 'Create';
193         testNonExpiredSilenceScenario();
194       });
195
196       it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
197         scenario.single = 'Recreate';
198         setSilenceState('expired');
199         permissionHelper.testScenarios(scenario);
200       });
201
202       it(`can use 'Create' and 'Recreate' actions`, () => {
203         expect(tableActions.tableActions.length).toBe(2);
204         expect(tableActions.tableActions).toEqual([
205           component.tableActions[0],
206           component.tableActions[1]
207         ]);
208       });
209     });
210
211     describe('with read and edit', () => {
212       beforeEach(() => {
213         tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
214       });
215
216       it(`shows always 'Edit' as main action for any state`, () => {
217         scenario.single = 'Edit';
218         scenario.empty = 'Edit';
219         testNonExpiredSilenceScenario();
220         setSilenceState('expired');
221         permissionHelper.testScenarios(scenario);
222       });
223
224       it(`can use 'Edit' action`, () => {
225         expect(tableActions.tableActions.length).toBe(1);
226         expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
227       });
228     });
229
230     describe('with read and delete', () => {
231       beforeEach(() => {
232         tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
233       });
234
235       it(`shows always 'Expire' as main action for any state`, () => {
236         scenario.single = 'Expire';
237         scenario.empty = 'Expire';
238         testNonExpiredSilenceScenario();
239         setSilenceState('expired');
240         permissionHelper.testScenarios(scenario);
241       });
242
243       it(`can use 'Expire' action`, () => {
244         expect(tableActions.tableActions.length).toBe(1);
245         expect(tableActions.tableActions).toEqual([component.tableActions[3]]);
246       });
247     });
248
249     describe('with only read', () => {
250       beforeEach(() => {
251         tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
252       });
253
254       it('shows no main action', () => {
255         permissionHelper.testScenarios({
256           fn: () => tableActions.getCurrentButton(),
257           single: undefined,
258           empty: undefined
259         });
260       });
261
262       it('can use no actions', () => {
263         expect(tableActions.tableActions.length).toBe(0);
264         expect(tableActions.tableActions).toEqual([]);
265       });
266     });
267   });
268
269   describe('expire silence', () => {
270     const setSelectedSilence = (silenceName: string) => {
271       component.selection.selected = [{ id: silenceName }];
272       component.selection.update();
273     };
274
275     const expireSilence = () => {
276       component.expireSilence();
277       const deletion: CriticalConfirmationModalComponent = component.modalRef.content;
278       deletion.modalRef = new BsModalRef();
279       deletion.ngOnInit();
280       deletion.callSubmitAction();
281     };
282
283     const expectSilenceToExpire = (silenceId) => {
284       setSelectedSilence(silenceId);
285       expireSilence();
286       expect(prometheusService.expireSilence).toHaveBeenCalledWith(silenceId);
287     };
288
289     beforeEach(() => {
290       const mockObservable = () => of([]);
291       spyOn(component, 'refresh').and.callFake(mockObservable);
292       spyOn(prometheusService, 'expireSilence').and.callFake(mockObservable);
293       spyOn(TestBed.get(BsModalService), 'show').and.callFake((deletionClass, config) => {
294         return {
295           content: Object.assign(new deletionClass(), config.initialState)
296         };
297       });
298     });
299
300     it('should expire a silence', () => {
301       const notificationService = TestBed.get(NotificationService);
302       spyOn(notificationService, 'show').and.stub();
303       expectSilenceToExpire('someSilenceId');
304       expect(notificationService.show).toHaveBeenCalledWith(
305         NotificationType.success,
306         'Expired Silence someSilenceId',
307         undefined,
308         undefined,
309         'Prometheus'
310       );
311     });
312
313     it('should refresh after expiring a silence', () => {
314       expectSilenceToExpire('someId');
315       expect(component.refresh).toHaveBeenCalledTimes(1);
316       expectSilenceToExpire('someOtherId');
317       expect(component.refresh).toHaveBeenCalledTimes(2);
318     });
319   });
320 });