]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / services / notification.service.spec.ts
1 import { DatePipe } from '@angular/common';
2 import { fakeAsync, TestBed, tick } from '@angular/core/testing';
3
4 import * as _ from 'lodash';
5 import { ToastsManager } from 'ng2-toastr';
6
7 import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
8 import { NotificationType } from '../enum/notification-type.enum';
9 import { CdNotificationConfig } from '../models/cd-notification';
10 import { FinishedTask } from '../models/finished-task';
11 import { CdDatePipe } from '../pipes/cd-date.pipe';
12 import { NotificationService } from './notification.service';
13 import { TaskMessageService } from './task-message.service';
14
15 describe('NotificationService', () => {
16 let service: NotificationService;
17 const toastFakeService = {
18 error: () => true,
19 info: () => true,
20 success: () => true
21 };
22
23 configureTestBed({
24 providers: [
25 CdDatePipe,
26 DatePipe,
27 NotificationService,
28 TaskMessageService,
29 { provide: ToastsManager, useValue: toastFakeService },
30 { provide: CdDatePipe, useValue: { transform: (d) => d } },
31 i18nProviders
32 ]
33 });
34
35 beforeEach(() => {
36 service = TestBed.get(NotificationService);
37 service.removeAll();
38 });
39
40 it('should be created', () => {
41 expect(service).toBeTruthy();
42 });
43
44 it('should read empty notification list', () => {
45 localStorage.setItem('cdNotifications', '[]');
46 expect(service['dataSource'].getValue()).toEqual([]);
47 });
48
49 it('should read old notifications', fakeAsync(() => {
50 localStorage.setItem(
51 'cdNotifications',
52 '[{"type":2,"message":"foobar","timestamp":"2018-05-24T09:41:32.726Z"}]'
53 );
54 service = new NotificationService(null, null, null);
55 expect(service['dataSource'].getValue().length).toBe(1);
56 }));
57
58 it('should cancel a notification', fakeAsync(() => {
59 const timeoutId = service.show(NotificationType.error, 'Simple test');
60 service.cancel(timeoutId);
61 tick(5000);
62 expect(service['dataSource'].getValue().length).toBe(0);
63 }));
64
65 it('should create a success notification and save it', fakeAsync(() => {
66 service.show(new CdNotificationConfig(NotificationType.success, 'Simple test'));
67 tick(100);
68 expect(service['dataSource'].getValue().length).toBe(1);
69 expect(service['dataSource'].getValue()[0].type).toBe(NotificationType.success);
70 }));
71
72 it('should create an error notification and save it', fakeAsync(() => {
73 service.show(NotificationType.error, 'Simple test');
74 tick(100);
75 expect(service['dataSource'].getValue().length).toBe(1);
76 expect(service['dataSource'].getValue()[0].type).toBe(NotificationType.error);
77 }));
78
79 it('should create an info notification and save it', fakeAsync(() => {
80 service.show(new CdNotificationConfig(NotificationType.info, 'Simple test'));
81 tick(100);
82 expect(service['dataSource'].getValue().length).toBe(1);
83 const notification = service['dataSource'].getValue()[0];
84 expect(notification.type).toBe(NotificationType.info);
85 expect(notification.title).toBe('Simple test');
86 expect(notification.message).toBe(undefined);
87 }));
88
89 it('should never have more then 10 notifications', fakeAsync(() => {
90 for (let index = 0; index < 15; index++) {
91 service.show(NotificationType.info, 'Simple test');
92 tick(100);
93 }
94 expect(service['dataSource'].getValue().length).toBe(10);
95 }));
96
97 it('should show a success task notification', fakeAsync(() => {
98 const task = _.assign(new FinishedTask(), {
99 success: true
100 });
101 service.notifyTask(task, true);
102 tick(100);
103 expect(service['dataSource'].getValue().length).toBe(1);
104 const notification = service['dataSource'].getValue()[0];
105 expect(notification.type).toBe(NotificationType.success);
106 expect(notification.title).toBe('Executed unknown task');
107 expect(notification.message).toBe(undefined);
108 }));
109
110 it('should be able to stop notifyTask from notifying', fakeAsync(() => {
111 const task = _.assign(new FinishedTask(), {
112 success: true
113 });
114 const timeoutId = service.notifyTask(task, true);
115 service.cancel(timeoutId);
116 tick(100);
117 expect(service['dataSource'].getValue().length).toBe(0);
118 }));
119
120 it('should show a error task notification', fakeAsync(() => {
121 const task = _.assign(
122 new FinishedTask('rbd/create', {
123 pool_name: 'somePool',
124 image_name: 'someImage'
125 }),
126 {
127 success: false,
128 exception: {
129 code: 17
130 }
131 }
132 );
133 service.notifyTask(task);
134 tick(100);
135 expect(service['dataSource'].getValue().length).toBe(1);
136 const notification = service['dataSource'].getValue()[0];
137 expect(notification.type).toBe(NotificationType.error);
138 expect(notification.title).toBe(`Failed to create RBD 'somePool/someImage'`);
139 expect(notification.message).toBe(`Name is already used by RBD 'somePool/someImage'.`);
140 }));
141
142 describe('notification queue', () => {
143 const n1 = new CdNotificationConfig(NotificationType.success, 'Some success');
144 const n2 = new CdNotificationConfig(NotificationType.info, 'Some info');
145
146 beforeEach(() => {
147 spyOn(service, 'show').and.stub();
148 });
149
150 it('filters out duplicated notifications on single call', fakeAsync(() => {
151 service.queueNotifications([n1, n1, n2, n2]);
152 tick(500);
153 expect(service.show).toHaveBeenCalledTimes(2);
154 }));
155
156 it('filters out duplicated notifications presented in different calls', fakeAsync(() => {
157 service.queueNotifications([n1, n2]);
158 service.queueNotifications([n1, n2]);
159 tick(500);
160 expect(service.show).toHaveBeenCalledTimes(2);
161 }));
162
163 it('will reset the timeout on every call', fakeAsync(() => {
164 service.queueNotifications([n1, n2]);
165 tick(400);
166 service.queueNotifications([n1, n2]);
167 tick(100);
168 expect(service.show).toHaveBeenCalledTimes(0);
169 tick(400);
170 expect(service.show).toHaveBeenCalledTimes(2);
171 }));
172
173 it('wont filter out duplicated notifications if timeout was reached before', fakeAsync(() => {
174 service.queueNotifications([n1, n2]);
175 tick(500);
176 service.queueNotifications([n1, n2]);
177 tick(500);
178 expect(service.show).toHaveBeenCalledTimes(4);
179 }));
180 });
181
182 describe('showToasty', () => {
183 let toastr: ToastsManager;
184 const time = '2022-02-22T00:00:00.000Z';
185
186 beforeEach(() => {
187 const baseTime = new Date(time);
188 spyOn(global, 'Date').and.returnValue(baseTime);
189 spyOn(window, 'setTimeout').and.callFake((fn) => fn());
190
191 toastr = TestBed.get(ToastsManager);
192 // spyOn needs to know the methods before spying and can't read the array for clarification
193 ['error', 'info', 'success'].forEach((method: 'error' | 'info' | 'success') =>
194 spyOn(toastr, method).and.stub()
195 );
196 });
197
198 it('should show with only title defined', () => {
199 service.show(NotificationType.info, 'Some info');
200 expect(toastr.info).toHaveBeenCalledWith(
201 `<small class="date">${time}</small>` +
202 '<i class="pull-right custom-icon ceph-icon" title="Ceph"></i>',
203 'Some info',
204 undefined
205 );
206 });
207
208 it('should show with title and message defined', () => {
209 service.show(
210 () =>
211 new CdNotificationConfig(NotificationType.error, 'Some error', 'Some operation failed')
212 );
213 expect(toastr.error).toHaveBeenCalledWith(
214 'Some operation failed<br>' +
215 `<small class="date">${time}</small>` +
216 '<i class="pull-right custom-icon ceph-icon" title="Ceph"></i>',
217 'Some error',
218 undefined
219 );
220 });
221
222 it('should show with title, message and application defined', () => {
223 service.show(
224 new CdNotificationConfig(
225 NotificationType.success,
226 'Alert resolved',
227 'Some alert resolved',
228 undefined,
229 'Prometheus'
230 )
231 );
232 expect(toastr.success).toHaveBeenCalledWith(
233 'Some alert resolved<br>' +
234 `<small class="date">${time}</small>` +
235 '<i class="pull-right custom-icon prometheus-icon" title="Prometheus"></i>',
236 'Alert resolved',
237 undefined
238 );
239 });
240 });
241 });