]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / core / navigation / navigation / navigation.component.spec.ts
CommitLineData
522d829b 1import { HttpClientTestingModule } from '@angular/common/http/testing';
11fdf7f2 2import { ComponentFixture, TestBed } from '@angular/core/testing';
9f95a23c 3import { By } from '@angular/platform-browser';
39ae355f 4import { RouterTestingModule } from '@angular/router/testing';
11fdf7f2 5
39ae355f
TL
6import { ToastrModule } from 'ngx-toastr';
7import { SimplebarAngularModule } from 'simplebar-angular';
9f95a23c
TL
8import { of } from 'rxjs';
9
f67539c2
TL
10import { Permission, Permissions } from '~/app/shared/models/permissions';
11import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
9f95a23c
TL
12import {
13 Features,
14 FeatureTogglesMap,
15 FeatureTogglesService
f67539c2
TL
16} from '~/app/shared/services/feature-toggles.service';
17import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
18import { SummaryService } from '~/app/shared/services/summary.service';
39ae355f 19import { SharedModule } from '~/app/shared/shared.module';
f67539c2 20import { configureTestBed } from '~/testing/unit-test-helper';
11fdf7f2 21import { NavigationComponent } from './navigation.component';
39ae355f
TL
22import { NotificationsComponent } from '../notifications/notifications.component';
23import { AdministrationComponent } from '../administration/administration.component';
24import { IdentityComponent } from '../identity/identity.component';
25import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
26import { DashboardHelpComponent } from '../dashboard-help/dashboard-help.component';
11fdf7f2 27
9f95a23c
TL
28function everythingPermittedExcept(disabledPermissions: string[] = []): any {
29 const permissions: Permissions = new Permissions({});
30 Object.keys(permissions).forEach(
31 (key) => (permissions[key] = new Permission(disabledPermissions.includes(key) ? [] : ['read']))
32 );
33 return permissions;
34}
35
36function onlyPermitted(enabledPermissions: string[] = []): any {
37 const permissions: Permissions = new Permissions({});
38 enabledPermissions.forEach((key) => (permissions[key] = new Permission(['read'])));
39 return permissions;
40}
41
42function everythingEnabledExcept(features: Features[] = []): FeatureTogglesMap {
43 const featureTogglesMap: FeatureTogglesMap = new FeatureTogglesMap();
44 features.forEach((key) => (featureTogglesMap[key] = false));
45 return featureTogglesMap;
46}
47
48function onlyEnabled(features: Features[] = []): FeatureTogglesMap {
49 const featureTogglesMap: FeatureTogglesMap = new FeatureTogglesMap();
50 Object.keys(featureTogglesMap).forEach(
51 (key) => (featureTogglesMap[key] = features.includes(<Features>key))
52 );
53 return featureTogglesMap;
54}
55
11fdf7f2
TL
56describe('NavigationComponent', () => {
57 let component: NavigationComponent;
58 let fixture: ComponentFixture<NavigationComponent>;
59
f6b5b4d7 60 configureTestBed({
39ae355f
TL
61 declarations: [
62 NavigationComponent,
63 NotificationsComponent,
64 AdministrationComponent,
65 DashboardHelpComponent,
66 IdentityComponent
67 ],
68 imports: [
69 HttpClientTestingModule,
70 SharedModule,
71 ToastrModule.forRoot(),
72 RouterTestingModule,
73 SimplebarAngularModule,
74 NgbModule
75 ],
76 providers: [AuthStorageService, SummaryService, FeatureTogglesService, PrometheusAlertService]
11fdf7f2
TL
77 });
78
79 beforeEach(() => {
39ae355f
TL
80 spyOn(TestBed.inject(AuthStorageService), 'getPermissions').and.callFake(() =>
81 everythingPermittedExcept()
82 );
83
84 spyOn(TestBed.inject(FeatureTogglesService), 'get').and.callFake(() =>
85 of(everythingEnabledExcept())
86 );
87 spyOn(TestBed.inject(SummaryService), 'subscribe').and.callFake(() =>
88 of({ health: { status: 'HEALTH_OK' } })
89 );
90 spyOn(TestBed.inject(PrometheusAlertService), 'getAlerts').and.callFake(() => of([]));
11fdf7f2
TL
91 fixture = TestBed.createComponent(NavigationComponent);
92 component = fixture.componentInstance;
39ae355f
TL
93 fixture.detectChanges();
94 });
95
96 afterEach(() => {
97 fixture.destroy();
11fdf7f2
TL
98 });
99
9f95a23c
TL
100 describe('Test Permissions', () => {
101 const testCases: [string[], string[]][] = [
102 [
103 ['hosts'],
104 [
105 '.tc_submenuitem_hosts',
106 '.tc_submenuitem_cluster_inventory',
107 '.tc_submenuitem_cluster_services'
108 ]
109 ],
110 [['monitor'], ['.tc_submenuitem_cluster_monitor']],
111 [['osd'], ['.tc_submenuitem_osds', '.tc_submenuitem_crush']],
1e59de90
TL
112 [
113 ['configOpt'],
114 ['.tc_submenuitem_configuration', '.tc_submenuitem_modules', '.tc_submenuitem_users']
115 ],
9f95a23c
TL
116 [['log'], ['.tc_submenuitem_log']],
117 [['prometheus'], ['.tc_submenuitem_monitoring']],
118 [['pool'], ['.tc_menuitem_pool']],
119 [['rbdImage'], ['.tc_submenuitem_block_images']],
120 [['rbdMirroring'], ['.tc_submenuitem_block_mirroring']],
121 [['iscsi'], ['.tc_submenuitem_block_iscsi']],
122 [['rbdImage', 'rbdMirroring', 'iscsi'], ['.tc_menuitem_block']],
123 [['nfs'], ['.tc_menuitem_nfs']],
124 [['cephfs'], ['.tc_menuitem_cephfs']],
125 [
126 ['rgw'],
127 [
128 '.tc_menuitem_rgw',
129 '.tc_submenuitem_rgw_daemons',
130 '.tc_submenuitem_rgw_buckets',
131 '.tc_submenuitem_rgw_users'
132 ]
133 ]
134 ];
135
136 for (const [disabledPermissions, selectors] of testCases) {
137 it(`When disabled permissions: ${JSON.stringify(
138 disabledPermissions
139 )} => hidden: "${selectors}"`, () => {
140 component.permissions = everythingPermittedExcept(disabledPermissions);
141 component.enabledFeature$ = of(everythingEnabledExcept());
142
143 fixture.detectChanges();
144 for (const selector of selectors) {
145 expect(fixture.debugElement.query(By.css(selector))).toBeFalsy();
146 }
147 });
148 }
149
150 for (const [enabledPermissions, selectors] of testCases) {
151 it(`When enabled permissions: ${JSON.stringify(
152 enabledPermissions
153 )} => visible: "${selectors}"`, () => {
154 component.permissions = onlyPermitted(enabledPermissions);
155 component.enabledFeature$ = of(everythingEnabledExcept());
156
157 fixture.detectChanges();
158 for (const selector of selectors) {
159 expect(fixture.debugElement.query(By.css(selector))).toBeTruthy();
160 }
161 });
162 }
92f5a8d4
TL
163 });
164
9f95a23c
TL
165 describe('Test FeatureToggles', () => {
166 const testCases: [Features[], string[]][] = [
167 [['rbd'], ['.tc_submenuitem_block_images']],
168 [['mirroring'], ['.tc_submenuitem_block_mirroring']],
169 [['iscsi'], ['.tc_submenuitem_block_iscsi']],
170 [['rbd', 'mirroring', 'iscsi'], ['.tc_menuitem_block']],
171 [['nfs'], ['.tc_menuitem_nfs']],
172 [['cephfs'], ['.tc_menuitem_cephfs']],
173 [
174 ['rgw'],
175 [
176 '.tc_menuitem_rgw',
177 '.tc_submenuitem_rgw_daemons',
178 '.tc_submenuitem_rgw_buckets',
179 '.tc_submenuitem_rgw_users'
180 ]
181 ]
182 ];
183
184 for (const [disabledFeatures, selectors] of testCases) {
185 it(`When disabled features: ${JSON.stringify(
186 disabledFeatures
187 )} => hidden: "${selectors}"`, () => {
188 component.enabledFeature$ = of(everythingEnabledExcept(disabledFeatures));
189 component.permissions = everythingPermittedExcept();
190
191 fixture.detectChanges();
192 for (const selector of selectors) {
193 expect(fixture.debugElement.query(By.css(selector))).toBeFalsy();
194 }
195 });
196 }
197
198 for (const [enabledFeatures, selectors] of testCases) {
199 it(`When enabled features: ${JSON.stringify(
200 enabledFeatures
201 )} => visible: "${selectors}"`, () => {
202 component.enabledFeature$ = of(onlyEnabled(enabledFeatures));
203 component.permissions = everythingPermittedExcept();
92f5a8d4 204
9f95a23c
TL
205 fixture.detectChanges();
206 for (const selector of selectors) {
207 expect(fixture.debugElement.query(By.css(selector))).toBeTruthy();
208 }
209 });
210 }
11fdf7f2 211 });
f6b5b4d7
TL
212
213 describe('showTopNotification', () => {
214 const notification1 = 'notificationName1';
215 const notification2 = 'notificationName2';
216
217 beforeEach(() => {
218 component.notifications = [];
219 });
220
221 it('should show notification', () => {
222 component.showTopNotification(notification1, true);
223 expect(component.notifications.includes(notification1)).toBeTruthy();
224 expect(component.notifications.length).toBe(1);
225 });
226
227 it('should not add a second notification if it is already shown', () => {
228 component.showTopNotification(notification1, true);
229 component.showTopNotification(notification1, true);
230 expect(component.notifications.includes(notification1)).toBeTruthy();
231 expect(component.notifications.length).toBe(1);
232 });
233
234 it('should add a second notification if the first one is different', () => {
235 component.showTopNotification(notification1, true);
236 component.showTopNotification(notification2, true);
237 expect(component.notifications.includes(notification1)).toBeTruthy();
238 expect(component.notifications.includes(notification2)).toBeTruthy();
239 expect(component.notifications.length).toBe(2);
240 });
241
242 it('should hide an active notification', () => {
243 component.showTopNotification(notification1, true);
244 expect(component.notifications.includes(notification1)).toBeTruthy();
245 expect(component.notifications.length).toBe(1);
246 component.showTopNotification(notification1, false);
247 expect(component.notifications.length).toBe(0);
248 });
249
250 it('should not fail if it tries to hide an inactive notification', () => {
251 expect(() => component.showTopNotification(notification1, false)).not.toThrow();
252 expect(component.notifications.length).toBe(0);
253 });
254
255 it('should keep other notifications if it hides one', () => {
256 component.showTopNotification(notification1, true);
257 component.showTopNotification(notification2, true);
258 expect(component.notifications.length).toBe(2);
259 component.showTopNotification(notification2, false);
260 expect(component.notifications.length).toBe(1);
261 expect(component.notifications.includes(notification1)).toBeTruthy();
262 });
263 });
11fdf7f2 264});