1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { TestBed } from '@angular/core/testing';
4 import { ToastrModule } from 'ngx-toastr';
5 import { Observable, of } from 'rxjs';
11 } from '../../../testing/unit-test-helper';
12 import { PrometheusService } from '../api/prometheus.service';
13 import { NotificationType } from '../enum/notification-type.enum';
14 import { CdNotificationConfig } from '../models/cd-notification';
15 import { AlertmanagerAlert } from '../models/prometheus-alerts';
16 import { SharedModule } from '../shared.module';
17 import { NotificationService } from './notification.service';
18 import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
19 import { PrometheusAlertService } from './prometheus-alert.service';
21 describe('PrometheusAlertService', () => {
22 let service: PrometheusAlertService;
23 let notificationService: NotificationService;
24 let alerts: AlertmanagerAlert[];
25 let prometheusService: PrometheusService;
26 let prometheus: PrometheusHelper;
29 imports: [ToastrModule.forRoot(), SharedModule, HttpClientTestingModule],
30 providers: [PrometheusAlertService, PrometheusAlertFormatter, i18nProviders]
34 prometheus = new PrometheusHelper();
37 it('should create', () => {
38 expect(TestBed.get(PrometheusAlertService)).toBeTruthy();
41 describe('test failing status codes and verify disabling of the alertmanager', () => {
42 const isDisabledByStatusCode = (statusCode: number, expectedStatus: boolean, done: any) => {
43 service = TestBed.get(PrometheusAlertService);
44 prometheusService = TestBed.get(PrometheusService);
45 spyOn(prometheusService, 'ifAlertmanagerConfigured').and.callFake((fn) => fn());
46 spyOn(prometheusService, 'getAlerts').and.returnValue(
47 Observable.create((observer: any) => observer.error({ status: statusCode, error: {} }))
49 const disableFn = spyOn(prometheusService, 'disableAlertmanagerConfig').and.callFake(() => {
50 expect(expectedStatus).toBe(true);
54 if (!expectedStatus) {
55 expect(disableFn).not.toHaveBeenCalled();
62 it('disables on 504 error which is thrown if the mgr failed', (done) => {
63 isDisabledByStatusCode(504, true, done);
66 it('disables on 404 error which is thrown if the external api cannot be reached', (done) => {
67 isDisabledByStatusCode(404, true, done);
70 it('does not disable on 400 error which is thrown if the external api receives unexpected data', (done) => {
71 isDisabledByStatusCode(400, false, done);
75 it('should flatten the response of getRules()', () => {
76 service = TestBed.get(PrometheusAlertService);
77 prometheusService = TestBed.get(PrometheusService);
79 spyOn(service['prometheusService'], 'ifPrometheusConfigured').and.callFake((fn) => fn());
80 spyOn(prometheusService, 'getRules').and.returnValue(
85 rules: [{ name: 'nearly_full', type: 'alerting' }]
90 { name: 'load_0', type: 'alerting' },
91 { name: 'load_1', type: 'alerting' },
92 { name: 'load_2', type: 'alerting' }
101 expect(service.rules as any).toEqual([
102 { name: 'nearly_full', type: 'alerting', group: 'group1' },
103 { name: 'load_0', type: 'alerting', group: 'test' },
104 { name: 'load_1', type: 'alerting', group: 'test' },
105 { name: 'load_2', type: 'alerting', group: 'test' }
109 describe('refresh', () => {
111 service = TestBed.get(PrometheusAlertService);
112 service['alerts'] = [];
113 service['canAlertsBeNotified'] = false;
115 spyOn(window, 'setTimeout').and.callFake((fn: Function) => fn());
117 notificationService = TestBed.get(NotificationService);
118 spyOn(notificationService, 'show').and.stub();
120 prometheusService = TestBed.get(PrometheusService);
121 spyOn(prometheusService, 'ifAlertmanagerConfigured').and.callFake((fn) => fn());
122 spyOn(prometheusService, 'getAlerts').and.callFake(() => of(alerts));
124 alerts = [prometheus.createAlert('alert0')];
128 it('should not notify on first call', () => {
129 expect(notificationService.show).not.toHaveBeenCalled();
132 it('should not notify with no change', () => {
134 expect(notificationService.show).not.toHaveBeenCalled();
137 it('should notify on alert change', () => {
138 alerts = [prometheus.createAlert('alert0', 'suppressed')];
140 expect(notificationService.show).toHaveBeenCalledWith(
141 new CdNotificationConfig(
142 NotificationType.info,
143 'alert0 (suppressed)',
144 'alert0 is suppressed ' + prometheus.createLink('http://alert0'),
151 it('should notify on a new alert', () => {
152 alerts = [prometheus.createAlert('alert1'), prometheus.createAlert('alert0')];
154 expect(notificationService.show).toHaveBeenCalledTimes(1);
155 expect(notificationService.show).toHaveBeenCalledWith(
156 new CdNotificationConfig(
157 NotificationType.error,
159 'alert1 is active ' + prometheus.createLink('http://alert1'),
166 it('should notify a resolved alert if it is not there anymore', () => {
169 expect(notificationService.show).toHaveBeenCalledTimes(1);
170 expect(notificationService.show).toHaveBeenCalledWith(
171 new CdNotificationConfig(
172 NotificationType.success,
174 'alert0 is active ' + prometheus.createLink('http://alert0'),
181 it('should call multiple times for multiple changes', () => {
182 const alert1 = prometheus.createAlert('alert1');
185 alerts = [alert1, prometheus.createAlert('alert2')];
187 expect(notificationService.show).toHaveBeenCalledTimes(2);