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';
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';
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';
26 describe('SilenceListComponent', () => {
27 let component: SilenceListComponent;
28 let fixture: ComponentFixture<SilenceListComponent>;
29 let prometheusService: PrometheusService;
34 BsDropdownModule.forRoot(),
36 ModalModule.forRoot(),
37 ToastrModule.forRoot(),
39 HttpClientTestingModule
41 declarations: [SilenceListComponent, PrometheusTabsComponent],
42 providers: [i18nProviders]
46 fixture = TestBed.createComponent(SilenceListComponent);
47 component = fixture.componentInstance;
48 prometheusService = TestBed.get(PrometheusService);
51 it('should create', () => {
52 fixture.detectChanges();
53 expect(component).toBeTruthy();
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;
62 const getTableActionComponent = (): TableActionsComponent => {
63 fixture.detectChanges();
64 return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
67 const setSilenceState = (state) => {
71 const testNonExpiredSilenceScenario = () => {
72 setSilenceState('active');
73 permissionHelper.testScenarios(scenario);
74 setSilenceState('pending');
75 permissionHelper.testScenarios(scenario);
79 permissionHelper = new PermissionHelper(component.permission, () =>
80 getTableActionComponent()
82 permissionHelper.createSelection = () => ({ status: { state: silenceState } });
84 fn: () => tableActions.getCurrentButton().name,
90 describe('with all', () => {
92 tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
95 it(`shows 'Edit' for single non expired silence else 'Create' as main action`, () => {
96 scenario.single = 'Edit';
97 testNonExpiredSilenceScenario();
100 it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
101 scenario.single = 'Recreate';
102 setSilenceState('expired');
103 permissionHelper.testScenarios(scenario);
106 it('can use all actions', () => {
107 expect(tableActions.tableActions.length).toBe(4);
108 expect(tableActions.tableActions).toEqual(component.tableActions);
112 describe('with read, create and update', () => {
114 tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
117 it(`shows 'Edit' for single non expired silence else 'Create' as main action`, () => {
118 scenario.single = 'Edit';
119 testNonExpiredSilenceScenario();
122 it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
123 scenario.single = 'Recreate';
124 setSilenceState('expired');
125 permissionHelper.testScenarios(scenario);
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]
138 describe('with read, create and delete', () => {
140 tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
143 it(`shows 'Expire' for single non expired silence else 'Create' as main action`, () => {
144 scenario.single = 'Expire';
145 testNonExpiredSilenceScenario();
148 it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
149 scenario.single = 'Recreate';
150 setSilenceState('expired');
151 permissionHelper.testScenarios(scenario);
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]
164 describe('with read, edit and delete', () => {
166 tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
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);
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]
186 describe('with read and create', () => {
188 tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
191 it(`shows always 'Create' as main action for single non expired silences`, () => {
192 scenario.single = 'Create';
193 testNonExpiredSilenceScenario();
196 it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
197 scenario.single = 'Recreate';
198 setSilenceState('expired');
199 permissionHelper.testScenarios(scenario);
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]
211 describe('with read and edit', () => {
213 tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
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);
224 it(`can use 'Edit' action`, () => {
225 expect(tableActions.tableActions.length).toBe(1);
226 expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
230 describe('with read and delete', () => {
232 tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
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);
243 it(`can use 'Expire' action`, () => {
244 expect(tableActions.tableActions.length).toBe(1);
245 expect(tableActions.tableActions).toEqual([component.tableActions[3]]);
249 describe('with only read', () => {
251 tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
254 it('shows no main action', () => {
255 permissionHelper.testScenarios({
256 fn: () => tableActions.getCurrentButton(),
262 it('can use no actions', () => {
263 expect(tableActions.tableActions.length).toBe(0);
264 expect(tableActions.tableActions).toEqual([]);
269 describe('expire silence', () => {
270 const setSelectedSilence = (silenceName: string) => {
271 component.selection.selected = [{ id: silenceName }];
272 component.selection.update();
275 const expireSilence = () => {
276 component.expireSilence();
277 const deletion: CriticalConfirmationModalComponent = component.modalRef.content;
278 deletion.modalRef = new BsModalRef();
280 deletion.callSubmitAction();
283 const expectSilenceToExpire = (silenceId) => {
284 setSelectedSilence(silenceId);
286 expect(prometheusService.expireSilence).toHaveBeenCalledWith(silenceId);
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) => {
295 content: Object.assign(new deletionClass(), config.initialState)
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',
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);