]>
Commit | Line | Data |
---|---|---|
494da23a TL |
1 | import { HttpClientTestingModule } from '@angular/common/http/testing'; |
2 | import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; | |
3 | import { ReactiveFormsModule } from '@angular/forms'; | |
494da23a TL |
4 | import { ActivatedRoute, Router, Routes } from '@angular/router'; |
5 | import { RouterTestingModule } from '@angular/router/testing'; | |
6 | ||
f67539c2 TL |
7 | import { NgbPopoverModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; |
8 | import _ from 'lodash'; | |
9 | import moment from 'moment'; | |
494da23a TL |
10 | import { ToastrModule } from 'ngx-toastr'; |
11 | import { of, throwError } from 'rxjs'; | |
12 | ||
f67539c2 TL |
13 | import { DashboardNotFoundError } from '~/app/core/error/error'; |
14 | import { ErrorComponent } from '~/app/core/error/error.component'; | |
15 | import { PrometheusService } from '~/app/shared/api/prometheus.service'; | |
16 | import { NotificationType } from '~/app/shared/enum/notification-type.enum'; | |
17 | import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; | |
18 | import { AlertmanagerSilence } from '~/app/shared/models/alertmanager-silence'; | |
19 | import { Permission } from '~/app/shared/models/permissions'; | |
20 | import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; | |
21 | import { ModalService } from '~/app/shared/services/modal.service'; | |
22 | import { NotificationService } from '~/app/shared/services/notification.service'; | |
23 | import { SharedModule } from '~/app/shared/shared.module'; | |
494da23a TL |
24 | import { |
25 | configureTestBed, | |
26 | FixtureHelper, | |
27 | FormHelper, | |
494da23a | 28 | PrometheusHelper |
f67539c2 | 29 | } from '~/testing/unit-test-helper'; |
494da23a TL |
30 | import { SilenceFormComponent } from './silence-form.component'; |
31 | ||
32 | describe('SilenceFormComponent', () => { | |
33 | // SilenceFormComponent specific | |
34 | let component: SilenceFormComponent; | |
35 | let fixture: ComponentFixture<SilenceFormComponent>; | |
36 | let form: CdFormGroup; | |
37 | // Spied on | |
38 | let prometheusService: PrometheusService; | |
39 | let authStorageService: AuthStorageService; | |
40 | let notificationService: NotificationService; | |
41 | let router: Router; | |
42 | // Spies | |
9f95a23c TL |
43 | let rulesSpy: jasmine.Spy; |
44 | let ifPrometheusSpy: jasmine.Spy; | |
494da23a TL |
45 | // Helper |
46 | let prometheus: PrometheusHelper; | |
9f95a23c | 47 | let formHelper: FormHelper; |
494da23a | 48 | let fixtureH: FixtureHelper; |
9f95a23c | 49 | let params: Record<string, any>; |
494da23a | 50 | // Date mocking related |
f67539c2 TL |
51 | const baseTime = '2022-02-22 00:00'; |
52 | const beginningDate = '2022-02-22T00:00:12.35'; | |
53 | let prometheusPermissions: Permission; | |
494da23a | 54 | |
f67539c2 | 55 | const routes: Routes = [{ path: '404', component: ErrorComponent }]; |
494da23a | 56 | configureTestBed({ |
f67539c2 | 57 | declarations: [ErrorComponent, SilenceFormComponent], |
494da23a TL |
58 | imports: [ |
59 | HttpClientTestingModule, | |
60 | RouterTestingModule.withRoutes(routes), | |
494da23a TL |
61 | SharedModule, |
62 | ToastrModule.forRoot(), | |
f67539c2 TL |
63 | NgbTooltipModule, |
64 | NgbPopoverModule, | |
494da23a TL |
65 | ReactiveFormsModule |
66 | ], | |
67 | providers: [ | |
494da23a TL |
68 | { |
69 | provide: ActivatedRoute, | |
9f95a23c | 70 | useValue: { params: { subscribe: (fn: Function) => fn(params) } } |
494da23a TL |
71 | } |
72 | ] | |
73 | }); | |
74 | ||
9f95a23c | 75 | const createMatcher = (name: string, value: any, isRegex: boolean) => ({ name, value, isRegex }); |
494da23a | 76 | |
9f95a23c | 77 | const addMatcher = (name: string, value: any, isRegex: boolean) => |
494da23a TL |
78 | component['setMatcher'](createMatcher(name, value, isRegex)); |
79 | ||
80 | const callInit = () => | |
81 | fixture.ngZone.run(() => { | |
82 | component['init'](); | |
83 | }); | |
84 | ||
85 | const changeAction = (action: string) => { | |
86 | const modes = { | |
f67539c2 TL |
87 | add: '/monitoring/silences/add', |
88 | alertAdd: '/monitoring/silences/add/someAlert', | |
89 | recreate: '/monitoring/silences/recreate/someExpiredId', | |
90 | edit: '/monitoring/silences/edit/someNotExpiredId' | |
494da23a TL |
91 | }; |
92 | Object.defineProperty(router, 'url', { value: modes[action] }); | |
93 | callInit(); | |
94 | }; | |
95 | ||
96 | beforeEach(() => { | |
97 | params = {}; | |
f67539c2 | 98 | spyOn(Date, 'now').and.returnValue(new Date(beginningDate)); |
494da23a TL |
99 | |
100 | prometheus = new PrometheusHelper(); | |
f67539c2 | 101 | prometheusService = TestBed.inject(PrometheusService); |
494da23a TL |
102 | spyOn(prometheusService, 'getAlerts').and.callFake(() => |
103 | of([prometheus.createAlert('alert0')]) | |
104 | ); | |
105 | ifPrometheusSpy = spyOn(prometheusService, 'ifPrometheusConfigured').and.callFake((fn) => fn()); | |
106 | rulesSpy = spyOn(prometheusService, 'getRules').and.callFake(() => | |
9f95a23c TL |
107 | of({ |
108 | groups: [ | |
109 | { | |
110 | file: '', | |
111 | interval: 0, | |
112 | name: '', | |
113 | rules: [ | |
114 | prometheus.createRule('alert0', 'someSeverity', [prometheus.createAlert('alert0')]), | |
115 | prometheus.createRule('alert1', 'someSeverity', []), | |
116 | prometheus.createRule('alert2', 'someOtherSeverity', [ | |
117 | prometheus.createAlert('alert2') | |
118 | ]) | |
119 | ] | |
120 | } | |
121 | ] | |
122 | }) | |
494da23a TL |
123 | ); |
124 | ||
f67539c2 | 125 | router = TestBed.inject(Router); |
494da23a | 126 | |
f67539c2 | 127 | notificationService = TestBed.inject(NotificationService); |
494da23a TL |
128 | spyOn(notificationService, 'show').and.stub(); |
129 | ||
f67539c2 | 130 | authStorageService = TestBed.inject(AuthStorageService); |
494da23a TL |
131 | spyOn(authStorageService, 'getUsername').and.returnValue('someUser'); |
132 | ||
f67539c2 TL |
133 | spyOn(authStorageService, 'getPermissions').and.callFake(() => ({ |
134 | prometheus: prometheusPermissions | |
135 | })); | |
136 | prometheusPermissions = new Permission(['update', 'delete', 'read', 'create']); | |
494da23a TL |
137 | fixture = TestBed.createComponent(SilenceFormComponent); |
138 | fixtureH = new FixtureHelper(fixture); | |
139 | component = fixture.componentInstance; | |
140 | form = component.form; | |
9f95a23c | 141 | formHelper = new FormHelper(form); |
494da23a TL |
142 | fixture.detectChanges(); |
143 | }); | |
144 | ||
145 | it('should create', () => { | |
146 | expect(component).toBeTruthy(); | |
147 | expect(_.isArray(component.rules)).toBeTruthy(); | |
148 | }); | |
149 | ||
150 | it('should have set the logged in user name as creator', () => { | |
151 | expect(component.form.getValue('createdBy')).toBe('someUser'); | |
152 | }); | |
153 | ||
154 | it('should call disablePrometheusConfig on error calling getRules', () => { | |
155 | spyOn(prometheusService, 'disablePrometheusConfig'); | |
156 | rulesSpy.and.callFake(() => throwError({})); | |
157 | callInit(); | |
158 | expect(component.rules).toEqual([]); | |
159 | expect(prometheusService.disablePrometheusConfig).toHaveBeenCalled(); | |
160 | }); | |
161 | ||
162 | it('should remind user if prometheus is not set when it is not configured', () => { | |
9f95a23c | 163 | ifPrometheusSpy.and.callFake((_x: any, fn: Function) => fn()); |
494da23a TL |
164 | callInit(); |
165 | expect(component.rules).toEqual([]); | |
166 | expect(notificationService.show).toHaveBeenCalledWith( | |
167 | NotificationType.info, | |
168 | 'Please add your Prometheus host to the dashboard configuration and refresh the page', | |
169 | undefined, | |
170 | undefined, | |
171 | 'Prometheus' | |
172 | ); | |
173 | }); | |
174 | ||
f67539c2 | 175 | describe('throw error for not allowed users', () => { |
9f95a23c | 176 | let navigateSpy: jasmine.Spy; |
494da23a | 177 | |
f67539c2 TL |
178 | const expectError = (action: string, redirected: boolean) => { |
179 | Object.defineProperty(router, 'url', { value: action }); | |
494da23a | 180 | if (redirected) { |
f67539c2 TL |
181 | expect(() => callInit()).toThrowError(DashboardNotFoundError); |
182 | } else { | |
183 | expect(() => callInit()).not.toThrowError(); | |
494da23a TL |
184 | } |
185 | navigateSpy.calls.reset(); | |
186 | }; | |
187 | ||
188 | beforeEach(() => { | |
189 | navigateSpy = spyOn(router, 'navigate').and.stub(); | |
494da23a TL |
190 | }); |
191 | ||
f67539c2 | 192 | it('should throw error if not allowed', () => { |
494da23a | 193 | prometheusPermissions = new Permission(['delete', 'read']); |
f67539c2 TL |
194 | expectError('add', true); |
195 | expectError('alertAdd', true); | |
494da23a TL |
196 | }); |
197 | ||
f67539c2 | 198 | it('should throw error if user does not have minimum permissions to create silences', () => { |
494da23a | 199 | prometheusPermissions = new Permission(['update', 'delete', 'read']); |
f67539c2 | 200 | expectError('add', true); |
494da23a | 201 | prometheusPermissions = new Permission(['update', 'delete', 'create']); |
f67539c2 | 202 | expectError('recreate', true); |
494da23a TL |
203 | }); |
204 | ||
f67539c2 TL |
205 | it('should throw error if user does not have minimum permissions to update silences', () => { |
206 | prometheusPermissions = new Permission(['delete', 'read']); | |
207 | expectError('edit', true); | |
494da23a | 208 | prometheusPermissions = new Permission(['create', 'delete', 'update']); |
f67539c2 | 209 | expectError('edit', true); |
494da23a TL |
210 | }); |
211 | ||
f67539c2 | 212 | it('does not throw error if user has minimum permissions to create silences', () => { |
494da23a | 213 | prometheusPermissions = new Permission(['create', 'read']); |
f67539c2 TL |
214 | expectError('add', false); |
215 | expectError('alertAdd', false); | |
216 | expectError('recreate', false); | |
494da23a TL |
217 | }); |
218 | ||
f67539c2 TL |
219 | it('does not throw error if user has minimum permissions to update silences', () => { |
220 | prometheusPermissions = new Permission(['read', 'create']); | |
221 | expectError('edit', false); | |
494da23a TL |
222 | }); |
223 | }); | |
224 | ||
225 | describe('choose the right action', () => { | |
226 | const expectMode = (routerMode: string, edit: boolean, recreate: boolean, action: string) => { | |
227 | changeAction(routerMode); | |
228 | expect(component.recreate).toBe(recreate); | |
229 | expect(component.edit).toBe(edit); | |
230 | expect(component.action).toBe(action); | |
231 | }; | |
232 | ||
233 | beforeEach(() => { | |
234 | spyOn(prometheusService, 'getSilences').and.callFake((p) => | |
235 | of([prometheus.createSilence(p.id)]) | |
236 | ); | |
237 | }); | |
238 | ||
239 | it('should have no special action activate by default', () => { | |
240 | expectMode('add', false, false, 'Create'); | |
241 | expect(prometheusService.getSilences).not.toHaveBeenCalled(); | |
242 | expect(component.form.value).toEqual({ | |
243 | comment: null, | |
244 | createdBy: 'someUser', | |
245 | duration: '2h', | |
246 | startsAt: baseTime, | |
f67539c2 | 247 | endsAt: '2022-02-22 02:00' |
494da23a TL |
248 | }); |
249 | }); | |
250 | ||
251 | it('should be in edit action if route includes edit', () => { | |
252 | params = { id: 'someNotExpiredId' }; | |
253 | expectMode('edit', true, false, 'Edit'); | |
254 | expect(prometheusService.getSilences).toHaveBeenCalledWith(params); | |
255 | expect(component.form.value).toEqual({ | |
256 | comment: `A comment for ${params.id}`, | |
257 | createdBy: `Creator of ${params.id}`, | |
258 | duration: '1d', | |
f67539c2 TL |
259 | startsAt: '2022-02-22 22:22', |
260 | endsAt: '2022-02-23 22:22' | |
494da23a TL |
261 | }); |
262 | expect(component.matchers).toEqual([createMatcher('job', 'someJob', true)]); | |
263 | }); | |
264 | ||
265 | it('should be in recreation action if route includes recreate', () => { | |
266 | params = { id: 'someExpiredId' }; | |
267 | expectMode('recreate', false, true, 'Recreate'); | |
268 | expect(prometheusService.getSilences).toHaveBeenCalledWith(params); | |
269 | expect(component.form.value).toEqual({ | |
270 | comment: `A comment for ${params.id}`, | |
271 | createdBy: `Creator of ${params.id}`, | |
272 | duration: '2h', | |
273 | startsAt: baseTime, | |
f67539c2 | 274 | endsAt: '2022-02-22 02:00' |
494da23a TL |
275 | }); |
276 | expect(component.matchers).toEqual([createMatcher('job', 'someJob', true)]); | |
277 | }); | |
278 | ||
279 | it('adds matchers based on the label object of the alert with the given id', () => { | |
280 | params = { id: 'someAlert' }; | |
281 | expectMode('alertAdd', false, false, 'Create'); | |
282 | expect(prometheusService.getSilences).not.toHaveBeenCalled(); | |
283 | expect(prometheusService.getAlerts).toHaveBeenCalled(); | |
284 | expect(component.matchers).toEqual([ | |
285 | createMatcher('alertname', 'alert0', false), | |
286 | createMatcher('instance', 'someInstance', false), | |
287 | createMatcher('job', 'someJob', false), | |
288 | createMatcher('severity', 'someSeverity', false) | |
289 | ]); | |
290 | expect(component.matcherMatch).toEqual({ | |
291 | cssClass: 'has-success', | |
292 | status: 'Matches 1 rule with 1 active alert.' | |
293 | }); | |
294 | }); | |
295 | }); | |
296 | ||
297 | describe('time', () => { | |
f67539c2 TL |
298 | const changeEndDate = (text: string) => component.form.patchValue({ endsAt: text }); |
299 | const changeStartDate = (text: string) => component.form.patchValue({ startsAt: text }); | |
494da23a TL |
300 | |
301 | it('have all dates set at beginning', () => { | |
302 | expect(form.getValue('startsAt')).toEqual(baseTime); | |
303 | expect(form.getValue('duration')).toBe('2h'); | |
f67539c2 | 304 | expect(form.getValue('endsAt')).toEqual('2022-02-22 02:00'); |
494da23a TL |
305 | }); |
306 | ||
307 | describe('on start date change', () => { | |
308 | it('changes end date on start date change if it exceeds it', fakeAsync(() => { | |
f67539c2 | 309 | changeStartDate('2022-02-28 04:05'); |
494da23a | 310 | expect(form.getValue('duration')).toEqual('2h'); |
f67539c2 | 311 | expect(form.getValue('endsAt')).toEqual('2022-02-28 06:05'); |
494da23a | 312 | |
f67539c2 | 313 | changeStartDate('2022-12-31 22:00'); |
494da23a | 314 | expect(form.getValue('duration')).toEqual('2h'); |
f67539c2 | 315 | expect(form.getValue('endsAt')).toEqual('2023-01-01 00:00'); |
494da23a TL |
316 | })); |
317 | ||
318 | it('changes duration if start date does not exceed end date ', fakeAsync(() => { | |
f67539c2 | 319 | changeStartDate('2022-02-22 00:45'); |
494da23a | 320 | expect(form.getValue('duration')).toEqual('1h 15m'); |
f67539c2 | 321 | expect(form.getValue('endsAt')).toEqual('2022-02-22 02:00'); |
494da23a TL |
322 | })); |
323 | ||
324 | it('should raise invalid start date error', fakeAsync(() => { | |
325 | changeStartDate('No valid date'); | |
f67539c2 TL |
326 | formHelper.expectError('startsAt', 'format'); |
327 | expect(form.getValue('startsAt').toString()).toBe('No valid date'); | |
328 | expect(form.getValue('endsAt')).toEqual('2022-02-22 02:00'); | |
494da23a TL |
329 | })); |
330 | }); | |
331 | ||
332 | describe('on duration change', () => { | |
333 | it('changes end date if duration is changed', () => { | |
9f95a23c | 334 | formHelper.setValue('duration', '15m'); |
f67539c2 | 335 | expect(form.getValue('endsAt')).toEqual('2022-02-22 00:15'); |
9f95a23c | 336 | formHelper.setValue('duration', '5d 23h'); |
f67539c2 | 337 | expect(form.getValue('endsAt')).toEqual('2022-02-27 23:00'); |
494da23a TL |
338 | }); |
339 | }); | |
340 | ||
341 | describe('on end date change', () => { | |
342 | it('changes duration on end date change if it exceeds start date', fakeAsync(() => { | |
f67539c2 | 343 | changeEndDate('2022-02-28 04:05'); |
494da23a TL |
344 | expect(form.getValue('duration')).toEqual('6d 4h 5m'); |
345 | expect(form.getValue('startsAt')).toEqual(baseTime); | |
346 | })); | |
347 | ||
348 | it('changes start date if end date happens before it', fakeAsync(() => { | |
f67539c2 | 349 | changeEndDate('2022-02-21 02:00'); |
494da23a | 350 | expect(form.getValue('duration')).toEqual('2h'); |
f67539c2 | 351 | expect(form.getValue('startsAt')).toEqual('2022-02-21 00:00'); |
494da23a TL |
352 | })); |
353 | ||
354 | it('should raise invalid end date error', fakeAsync(() => { | |
355 | changeEndDate('No valid date'); | |
f67539c2 TL |
356 | formHelper.expectError('endsAt', 'format'); |
357 | expect(form.getValue('endsAt').toString()).toBe('No valid date'); | |
494da23a TL |
358 | expect(form.getValue('startsAt')).toEqual(baseTime); |
359 | })); | |
360 | }); | |
361 | }); | |
362 | ||
363 | it('should have a creator field', () => { | |
9f95a23c TL |
364 | formHelper.expectValid('createdBy'); |
365 | formHelper.expectErrorChange('createdBy', '', 'required'); | |
366 | formHelper.expectValidChange('createdBy', 'Mighty FSM'); | |
494da23a TL |
367 | }); |
368 | ||
369 | it('should have a comment field', () => { | |
9f95a23c TL |
370 | formHelper.expectError('comment', 'required'); |
371 | formHelper.expectValidChange('comment', 'A pretty long comment'); | |
494da23a TL |
372 | }); |
373 | ||
374 | it('should be a valid form if all inputs are filled and at least one matcher was added', () => { | |
375 | expect(form.valid).toBeFalsy(); | |
9f95a23c TL |
376 | formHelper.expectValidChange('createdBy', 'Mighty FSM'); |
377 | formHelper.expectValidChange('comment', 'A pretty long comment'); | |
494da23a TL |
378 | addMatcher('job', 'someJob', false); |
379 | expect(form.valid).toBeTruthy(); | |
380 | }); | |
381 | ||
382 | describe('matchers', () => { | |
9f95a23c | 383 | const expectMatch = (helpText: string) => { |
494da23a TL |
384 | expect(fixtureH.getText('#match-state')).toBe(helpText); |
385 | }; | |
386 | ||
387 | it('should show the add matcher button', () => { | |
388 | fixtureH.expectElementVisible('#add-matcher', true); | |
389 | fixtureH.expectIdElementsVisible( | |
390 | [ | |
391 | 'matcher-name-0', | |
392 | 'matcher-value-0', | |
393 | 'matcher-isRegex-0', | |
394 | 'matcher-edit-0', | |
395 | 'matcher-delete-0' | |
396 | ], | |
397 | false | |
398 | ); | |
399 | expectMatch(null); | |
400 | }); | |
401 | ||
402 | it('should show added matcher', () => { | |
403 | addMatcher('job', 'someJob', true); | |
404 | fixtureH.expectIdElementsVisible( | |
405 | [ | |
406 | 'matcher-name-0', | |
407 | 'matcher-value-0', | |
408 | 'matcher-isRegex-0', | |
409 | 'matcher-edit-0', | |
410 | 'matcher-delete-0' | |
411 | ], | |
412 | true | |
413 | ); | |
414 | expectMatch(null); | |
415 | }); | |
416 | ||
417 | it('should show multiple matchers', () => { | |
418 | addMatcher('severity', 'someSeverity', false); | |
419 | addMatcher('alertname', 'alert0', false); | |
420 | fixtureH.expectIdElementsVisible( | |
421 | [ | |
422 | 'matcher-name-0', | |
423 | 'matcher-value-0', | |
424 | 'matcher-isRegex-0', | |
425 | 'matcher-edit-0', | |
426 | 'matcher-delete-0', | |
427 | 'matcher-name-1', | |
428 | 'matcher-value-1', | |
429 | 'matcher-isRegex-1', | |
430 | 'matcher-edit-1', | |
431 | 'matcher-delete-1' | |
432 | ], | |
433 | true | |
434 | ); | |
435 | expectMatch('Matches 1 rule with 1 active alert.'); | |
436 | }); | |
437 | ||
438 | it('should show the right matcher values', () => { | |
439 | addMatcher('alertname', 'alert.*', true); | |
440 | addMatcher('job', 'someJob', false); | |
441 | fixture.detectChanges(); | |
442 | fixtureH.expectFormFieldToBe('#matcher-name-0', 'alertname'); | |
443 | fixtureH.expectFormFieldToBe('#matcher-value-0', 'alert.*'); | |
444 | fixtureH.expectFormFieldToBe('#matcher-isRegex-0', 'true'); | |
445 | fixtureH.expectFormFieldToBe('#matcher-isRegex-1', 'false'); | |
446 | expectMatch(null); | |
447 | }); | |
448 | ||
449 | it('should be able to edit a matcher', () => { | |
450 | addMatcher('alertname', 'alert.*', true); | |
451 | expectMatch(null); | |
452 | ||
f67539c2 | 453 | const modalService = TestBed.inject(ModalService); |
494da23a TL |
454 | spyOn(modalService, 'show').and.callFake(() => { |
455 | return { | |
f67539c2 | 456 | componentInstance: { |
9f95a23c | 457 | preFillControls: (matcher: any) => { |
494da23a TL |
458 | expect(matcher).toBe(component.matchers[0]); |
459 | }, | |
460 | submitAction: of({ name: 'alertname', value: 'alert0', isRegex: false }) | |
461 | } | |
462 | }; | |
463 | }); | |
464 | fixtureH.clickElement('#matcher-edit-0'); | |
465 | ||
466 | fixtureH.expectFormFieldToBe('#matcher-name-0', 'alertname'); | |
467 | fixtureH.expectFormFieldToBe('#matcher-value-0', 'alert0'); | |
468 | fixtureH.expectFormFieldToBe('#matcher-isRegex-0', 'false'); | |
469 | expectMatch('Matches 1 rule with 1 active alert.'); | |
470 | }); | |
471 | ||
472 | it('should be able to remove a matcher', () => { | |
473 | addMatcher('alertname', 'alert0', false); | |
474 | expectMatch('Matches 1 rule with 1 active alert.'); | |
475 | fixtureH.clickElement('#matcher-delete-0'); | |
476 | expect(component.matchers).toEqual([]); | |
477 | fixtureH.expectIdElementsVisible( | |
478 | ['matcher-name-0', 'matcher-value-0', 'matcher-isRegex-0'], | |
479 | false | |
480 | ); | |
481 | expectMatch(null); | |
482 | }); | |
483 | ||
484 | it('should be able to remove a matcher and update the matcher text', () => { | |
485 | addMatcher('alertname', 'alert0', false); | |
486 | addMatcher('alertname', 'alert1', false); | |
487 | expectMatch('Your matcher seems to match no currently defined rule or active alert.'); | |
488 | fixtureH.clickElement('#matcher-delete-1'); | |
489 | expectMatch('Matches 1 rule with 1 active alert.'); | |
490 | }); | |
491 | ||
492 | it('should show form as invalid if no matcher is set', () => { | |
493 | expect(form.errors).toEqual({ matcherRequired: true }); | |
494 | }); | |
495 | ||
496 | it('should show form as valid if matcher was added', () => { | |
497 | addMatcher('some name', 'some value', true); | |
498 | expect(form.errors).toEqual(null); | |
499 | }); | |
500 | }); | |
501 | ||
502 | describe('submit tests', () => { | |
f67539c2 | 503 | const endsAt = '2022-02-22 02:00'; |
494da23a TL |
504 | let silence: AlertmanagerSilence; |
505 | const silenceId = '50M3-10N6-1D'; | |
506 | ||
9f95a23c | 507 | const expectSuccessNotification = (titleStartsWith: string) => |
494da23a TL |
508 | expect(notificationService.show).toHaveBeenCalledWith( |
509 | NotificationType.success, | |
510 | `${titleStartsWith} silence ${silenceId}`, | |
511 | undefined, | |
512 | undefined, | |
513 | 'Prometheus' | |
514 | ); | |
515 | ||
516 | const fillAndSubmit = () => { | |
517 | ['createdBy', 'comment'].forEach((attr) => { | |
9f95a23c | 518 | formHelper.setValue(attr, silence[attr]); |
494da23a TL |
519 | }); |
520 | silence.matchers.forEach((matcher) => | |
521 | addMatcher(matcher.name, matcher.value, matcher.isRegex) | |
522 | ); | |
523 | component.submit(); | |
524 | }; | |
525 | ||
526 | beforeEach(() => { | |
527 | spyOn(prometheusService, 'setSilence').and.callFake(() => of({ body: { silenceId } })); | |
528 | spyOn(router, 'navigate').and.stub(); | |
529 | silence = { | |
530 | createdBy: 'some creator', | |
531 | comment: 'some comment', | |
f67539c2 TL |
532 | startsAt: moment(baseTime).toISOString(), |
533 | endsAt: moment(endsAt).toISOString(), | |
494da23a TL |
534 | matchers: [ |
535 | { | |
536 | name: 'some attribute name', | |
537 | value: 'some value', | |
538 | isRegex: false | |
539 | }, | |
540 | { | |
541 | name: 'job', | |
542 | value: 'node-exporter', | |
543 | isRegex: false | |
544 | }, | |
545 | { | |
546 | name: 'instance', | |
547 | value: 'localhost:9100', | |
548 | isRegex: false | |
549 | }, | |
550 | { | |
551 | name: 'alertname', | |
552 | value: 'load_0', | |
553 | isRegex: false | |
554 | } | |
555 | ] | |
556 | }; | |
557 | }); | |
558 | ||
f67539c2 TL |
559 | // it('should not create a silence if the form is invalid', () => { |
560 | // component.submit(); | |
561 | // expect(notificationService.show).not.toHaveBeenCalled(); | |
562 | // expect(form.valid).toBeFalsy(); | |
563 | // expect(prometheusService.setSilence).not.toHaveBeenCalledWith(silence); | |
564 | // expect(router.navigate).not.toHaveBeenCalled(); | |
565 | // }); | |
566 | ||
567 | // it('should route back to previous tab on success', () => { | |
568 | // fillAndSubmit(); | |
569 | // expect(form.valid).toBeTruthy(); | |
570 | // expect(router.navigate).toHaveBeenCalledWith(['/monitoring'], { fragment: 'silences' }); | |
571 | // }); | |
494da23a TL |
572 | |
573 | it('should create a silence', () => { | |
574 | fillAndSubmit(); | |
575 | expect(prometheusService.setSilence).toHaveBeenCalledWith(silence); | |
576 | expectSuccessNotification('Created'); | |
577 | }); | |
578 | ||
579 | it('should recreate a silence', () => { | |
580 | component.recreate = true; | |
581 | component.id = 'recreateId'; | |
582 | fillAndSubmit(); | |
583 | expect(prometheusService.setSilence).toHaveBeenCalledWith(silence); | |
584 | expectSuccessNotification('Recreated'); | |
585 | }); | |
586 | ||
587 | it('should edit a silence', () => { | |
588 | component.edit = true; | |
589 | component.id = 'editId'; | |
590 | silence.id = component.id; | |
591 | fillAndSubmit(); | |
592 | expect(prometheusService.setSilence).toHaveBeenCalledWith(silence); | |
593 | expectSuccessNotification('Edited'); | |
594 | }); | |
595 | }); | |
596 | }); |