]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.spec.ts
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / prometheus / silence-list / silence-list.component.spec.ts
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 });