expect(notification.title).toBe(`Failed to create RBD 'somePool/someImage'`);
expect(notification.message).toBe(`Name is already used by RBD 'somePool/someImage'.`);
}));
+
+ describe('notification queue', () => {
+ const n1 = new CdNotificationConfig(NotificationType.success, 'Some success');
+ const n2 = new CdNotificationConfig(NotificationType.info, 'Some info');
+
+ beforeEach(() => {
+ spyOn(notificationService, 'show').and.stub();
+ });
+
+ it('filters out duplicated notifications on single call', fakeAsync(() => {
+ notificationService.queueNotifications([n1, n1, n2, n2]);
+ tick(500);
+ expect(notificationService.show).toHaveBeenCalledTimes(2);
+ }));
+
+ it('filters out duplicated notifications presented in different calls', fakeAsync(() => {
+ notificationService.queueNotifications([n1, n2]);
+ notificationService.queueNotifications([n1, n2]);
+ tick(500);
+ expect(notificationService.show).toHaveBeenCalledTimes(2);
+ }));
+
+ it('will reset the timeout on every call', fakeAsync(() => {
+ notificationService.queueNotifications([n1, n2]);
+ tick(400);
+ notificationService.queueNotifications([n1, n2]);
+ tick(100);
+ expect(notificationService.show).toHaveBeenCalledTimes(0);
+ tick(400);
+ expect(notificationService.show).toHaveBeenCalledTimes(2);
+ }));
+
+ it('wont filter out duplicated notifications if timeout was reached before', fakeAsync(() => {
+ notificationService.queueNotifications([n1, n2]);
+ tick(500);
+ notificationService.queueNotifications([n1, n2]);
+ tick(500);
+ expect(notificationService.show).toHaveBeenCalledTimes(4);
+ }));
+ });
});
export class NotificationService {
// Observable sources
private dataSource = new BehaviorSubject<CdNotification[]>([]);
+ private queuedNotifications: CdNotificationConfig[] = [];
// Observable streams
data$ = this.dataSource.asObservable();
+ private queueTimeoutId: number;
KEY = 'cdNotifications';
constructor(public toastr: ToastsManager, private taskMessageService: TaskMessageService) {
localStorage.setItem(this.KEY, JSON.stringify(recent));
}
+ queueNotifications(notifications: CdNotificationConfig[]) {
+ this.queuedNotifications = this.queuedNotifications.concat(notifications);
+ this.cancel(this.queueTimeoutId);
+ this.queueTimeoutId = window.setTimeout(() => {
+ this.sendQueuedNotifications();
+ }, 500);
+ }
+
+ private sendQueuedNotifications() {
+ _.uniqWith(this.queuedNotifications, _.isEqual).forEach((notification) => {
+ this.show(notification);
+ });
+ this.queuedNotifications = [];
+ }
+
/**
* Method for showing a notification.
* @param {NotificationType} type toastr type
} else {
type = arg;
}
- return setTimeout(() => {
+ return window.setTimeout(() => {
this.save(type, title, message);
if (!message) {
message = '';
* @param {number} timeoutId A number representing the ID of the timeout to be canceled.
*/
cancel(timeoutId) {
- clearTimeout(timeoutId);
+ window.clearTimeout(timeoutId);
}
}