]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/components/notifications-sidebar/notifications-sidebar.component.spec.ts
596f3c358bf4d8b9f44de077ef225364645068f1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / components / notifications-sidebar / notifications-sidebar.component.spec.ts
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3 import { NoopAnimationsModule } from '@angular/platform-browser/animations';
4 import { RouterTestingModule } from '@angular/router/testing';
5
6 import { NgbProgressbarModule } from '@ng-bootstrap/ng-bootstrap';
7 import { ClickOutsideModule } from 'ng-click-outside';
8 import { ToastrModule } from 'ngx-toastr';
9 import { SimplebarAngularModule } from 'simplebar-angular';
10
11 import { PrometheusService } from '~/app/shared/api/prometheus.service';
12 import { RbdService } from '~/app/shared/api/rbd.service';
13 import { SettingsService } from '~/app/shared/api/settings.service';
14 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
15 import { ExecutingTask } from '~/app/shared/models/executing-task';
16 import { Permissions } from '~/app/shared/models/permissions';
17 import { PipesModule } from '~/app/shared/pipes/pipes.module';
18 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
19 import { NotificationService } from '~/app/shared/services/notification.service';
20 import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
21 import { PrometheusNotificationService } from '~/app/shared/services/prometheus-notification.service';
22 import { SummaryService } from '~/app/shared/services/summary.service';
23 import { configureTestBed } from '~/testing/unit-test-helper';
24 import { NotificationsSidebarComponent } from './notifications-sidebar.component';
25
26 describe('NotificationsSidebarComponent', () => {
27 let component: NotificationsSidebarComponent;
28 let fixture: ComponentFixture<NotificationsSidebarComponent>;
29
30 configureTestBed({
31 imports: [
32 HttpClientTestingModule,
33 PipesModule,
34 NgbProgressbarModule,
35 RouterTestingModule,
36 ToastrModule.forRoot(),
37 NoopAnimationsModule,
38 SimplebarAngularModule,
39 ClickOutsideModule
40 ],
41 declarations: [NotificationsSidebarComponent],
42 providers: [PrometheusService, SettingsService, SummaryService, NotificationService, RbdService]
43 });
44
45 beforeEach(() => {
46 fixture = TestBed.createComponent(NotificationsSidebarComponent);
47 component = fixture.componentInstance;
48 });
49
50 it('should create', () => {
51 fixture.detectChanges();
52 expect(component).toBeTruthy();
53 });
54
55 describe('prometheus alert handling', () => {
56 let prometheusAlertService: PrometheusAlertService;
57 let prometheusNotificationService: PrometheusNotificationService;
58 let prometheusReadPermission: string;
59 let configOptReadPermission: string;
60
61 const expectPrometheusServicesToBeCalledTimes = (n: number) => {
62 expect(prometheusNotificationService.refresh).toHaveBeenCalledTimes(n);
63 expect(prometheusAlertService.refresh).toHaveBeenCalledTimes(n);
64 };
65
66 beforeEach(() => {
67 prometheusReadPermission = 'read';
68 configOptReadPermission = 'read';
69 spyOn(TestBed.inject(AuthStorageService), 'getPermissions').and.callFake(
70 () =>
71 new Permissions({
72 prometheus: [prometheusReadPermission],
73 'config-opt': [configOptReadPermission]
74 })
75 );
76
77 spyOn(TestBed.inject(PrometheusService), 'ifAlertmanagerConfigured').and.callFake((fn) =>
78 fn()
79 );
80
81 prometheusAlertService = TestBed.inject(PrometheusAlertService);
82 spyOn(prometheusAlertService, 'refresh').and.stub();
83
84 prometheusNotificationService = TestBed.inject(PrometheusNotificationService);
85 spyOn(prometheusNotificationService, 'refresh').and.stub();
86 });
87
88 it('should not refresh prometheus services if not allowed', () => {
89 prometheusReadPermission = '';
90 configOptReadPermission = 'read';
91 fixture.detectChanges();
92
93 expectPrometheusServicesToBeCalledTimes(0);
94
95 prometheusReadPermission = 'read';
96 configOptReadPermission = '';
97 fixture.detectChanges();
98
99 expectPrometheusServicesToBeCalledTimes(0);
100 });
101
102 it('should first refresh prometheus notifications and alerts during init', () => {
103 fixture.detectChanges();
104
105 expect(prometheusAlertService.refresh).toHaveBeenCalledTimes(1);
106 expectPrometheusServicesToBeCalledTimes(1);
107 });
108
109 it('should refresh prometheus services every 5s', fakeAsync(() => {
110 fixture.detectChanges();
111
112 expectPrometheusServicesToBeCalledTimes(1);
113 tick(5000);
114 expectPrometheusServicesToBeCalledTimes(2);
115 tick(15000);
116 expectPrometheusServicesToBeCalledTimes(5);
117 component.ngOnDestroy();
118 }));
119 });
120
121 describe('Running Tasks', () => {
122 let summaryService: SummaryService;
123
124 beforeEach(() => {
125 fixture.detectChanges();
126 summaryService = TestBed.inject(SummaryService);
127
128 spyOn(component, '_handleTasks').and.callThrough();
129 });
130
131 it('should handle executing tasks', () => {
132 const running_tasks = new ExecutingTask('rbd/delete', {
133 image_spec: 'somePool/someImage'
134 });
135
136 summaryService['summaryDataSource'].next({ executing_tasks: [running_tasks] });
137
138 expect(component._handleTasks).toHaveBeenCalled();
139 expect(component.executingTasks.length).toBe(1);
140 expect(component.executingTasks[0].description).toBe(`Deleting RBD 'somePool/someImage'`);
141 });
142 });
143
144 describe('Notifications', () => {
145 it('should fetch latest notifications', fakeAsync(() => {
146 const notificationService: NotificationService = TestBed.inject(NotificationService);
147 fixture.detectChanges();
148
149 expect(component.notifications.length).toBe(0);
150
151 notificationService.show(NotificationType.success, 'Sample title', 'Sample message');
152 tick(6000);
153 expect(component.notifications.length).toBe(1);
154 expect(component.notifications[0].title).toBe('Sample title');
155 }));
156 });
157
158 describe('Sidebar', () => {
159 let notificationService: NotificationService;
160
161 beforeEach(() => {
162 notificationService = TestBed.inject(NotificationService);
163 fixture.detectChanges();
164 });
165
166 it('should always close if sidebarSubject value is true', fakeAsync(() => {
167 // Closed before next value
168 expect(component.isSidebarOpened).toBeFalsy();
169 notificationService.sidebarSubject.next(true);
170 tick();
171 expect(component.isSidebarOpened).toBeFalsy();
172
173 // Opened before next value
174 component.isSidebarOpened = true;
175 expect(component.isSidebarOpened).toBeTruthy();
176 notificationService.sidebarSubject.next(true);
177 tick();
178 expect(component.isSidebarOpened).toBeFalsy();
179 }));
180
181 it('should toggle sidebar visibility if sidebarSubject value is false', () => {
182 // Closed before next value
183 expect(component.isSidebarOpened).toBeFalsy();
184 notificationService.sidebarSubject.next(false);
185 expect(component.isSidebarOpened).toBeTruthy();
186
187 // Opened before next value
188 component.isSidebarOpened = true;
189 expect(component.isSidebarOpened).toBeTruthy();
190 notificationService.sidebarSubject.next(false);
191 expect(component.isSidebarOpened).toBeFalsy();
192 });
193 });
194 });