]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts
import 15.2.4
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / block / rbd-snapshot-list / rbd-snapshot-list.component.spec.ts
CommitLineData
11fdf7f2
TL
1import { HttpClientTestingModule } from '@angular/common/http/testing';
2import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
e306af50 3import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
11fdf7f2
TL
4import { RouterTestingModule } from '@angular/router/testing';
5
6import { I18n } from '@ngx-translate/i18n-polyfill';
11fdf7f2 7import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
9f95a23c 8import { TabsModule } from 'ngx-bootstrap/tabs';
494da23a 9import { ToastrModule } from 'ngx-toastr';
11fdf7f2
TL
10import { Subject, throwError as observableThrowError } from 'rxjs';
11
12import {
13 configureTestBed,
eafe8130 14 expectItemTasks,
11fdf7f2
TL
15 i18nProviders,
16 PermissionHelper
17} from '../../../../testing/unit-test-helper';
18import { ApiModule } from '../../../shared/api/api.module';
19import { RbdService } from '../../../shared/api/rbd.service';
20import { ComponentsModule } from '../../../shared/components/components.module';
eafe8130 21import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
11fdf7f2
TL
22import { DataTableModule } from '../../../shared/datatable/datatable.module';
23import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
24import { ExecutingTask } from '../../../shared/models/executing-task';
25import { Permissions } from '../../../shared/models/permissions';
26import { PipesModule } from '../../../shared/pipes/pipes.module';
27import { AuthStorageService } from '../../../shared/services/auth-storage.service';
28import { NotificationService } from '../../../shared/services/notification.service';
11fdf7f2
TL
29import { SummaryService } from '../../../shared/services/summary.service';
30import { TaskListService } from '../../../shared/services/task-list.service';
9f95a23c
TL
31import { RbdSnapshotFormModalComponent } from '../rbd-snapshot-form/rbd-snapshot-form-modal.component';
32import { RbdTabsComponent } from '../rbd-tabs/rbd-tabs.component';
11fdf7f2
TL
33import { RbdSnapshotListComponent } from './rbd-snapshot-list.component';
34import { RbdSnapshotModel } from './rbd-snapshot.model';
35
36describe('RbdSnapshotListComponent', () => {
37 let component: RbdSnapshotListComponent;
38 let fixture: ComponentFixture<RbdSnapshotListComponent>;
39 let summaryService: SummaryService;
40
41 const fakeAuthStorageService = {
42 isLoggedIn: () => {
43 return true;
44 },
45 getPermissions: () => {
46 return new Permissions({ 'rbd-image': ['read', 'update', 'create', 'delete'] });
47 }
48 };
49
50 configureTestBed({
9f95a23c 51 declarations: [RbdSnapshotListComponent, RbdTabsComponent],
11fdf7f2 52 imports: [
11fdf7f2 53 ApiModule,
e306af50 54 BrowserAnimationsModule,
9f95a23c
TL
55 ComponentsModule,
56 DataTableModule,
11fdf7f2 57 HttpClientTestingModule,
9f95a23c 58 PipesModule,
11fdf7f2 59 RouterTestingModule,
9f95a23c
TL
60 TabsModule.forRoot(),
61 ToastrModule.forRoot()
11fdf7f2
TL
62 ],
63 providers: [
64 { provide: AuthStorageService, useValue: fakeAuthStorageService },
65 TaskListService,
66 i18nProviders
67 ]
68 });
69
70 beforeEach(() => {
71 fixture = TestBed.createComponent(RbdSnapshotListComponent);
72 component = fixture.componentInstance;
9f95a23c 73 component.ngOnChanges();
11fdf7f2
TL
74 summaryService = TestBed.get(SummaryService);
75 });
76
77 it('should create', () => {
78 fixture.detectChanges();
79 expect(component).toBeTruthy();
80 });
81
82 describe('api delete request', () => {
9f95a23c 83 let called: boolean;
11fdf7f2
TL
84 let rbdService: RbdService;
85 let notificationService: NotificationService;
86 let authStorageService: AuthStorageService;
87
88 beforeEach(() => {
89 fixture.detectChanges();
90 const i18n = TestBed.get(I18n);
eafe8130 91 const actionLabelsI18n = TestBed.get(ActionLabelsI18n);
11fdf7f2
TL
92 called = false;
93 rbdService = new RbdService(null, null);
94 notificationService = new NotificationService(null, null, null);
95 authStorageService = new AuthStorageService();
96 authStorageService.set('user', '', { 'rbd-image': ['create', 'read', 'update', 'delete'] });
97 component = new RbdSnapshotListComponent(
98 authStorageService,
99 null,
100 null,
101 null,
102 rbdService,
103 null,
104 notificationService,
105 null,
106 null,
eafe8130
TL
107 i18n,
108 actionLabelsI18n
11fdf7f2
TL
109 );
110 spyOn(rbdService, 'deleteSnapshot').and.returnValue(observableThrowError({ status: 500 }));
111 spyOn(notificationService, 'notifyTask').and.stub();
112 component.modalRef = new BsModalRef();
113 component.modalRef.content = {
114 stopLoadingSpinner: () => (called = true)
115 };
116 });
117
801d1391 118 it('should call stopLoadingSpinner if the request fails', fakeAsync(() => {
11fdf7f2
TL
119 expect(called).toBe(false);
120 component._asyncTask('deleteSnapshot', 'rbd/snap/delete', 'someName');
121 tick(500);
122 expect(called).toBe(true);
123 }));
124 });
125
126 describe('handling of executing tasks', () => {
127 let snapshots: RbdSnapshotModel[];
128
9f95a23c 129 const addSnapshot = (name: string) => {
11fdf7f2
TL
130 const model = new RbdSnapshotModel();
131 model.id = 1;
132 model.name = name;
133 snapshots.push(model);
134 };
135
136 const addTask = (task_name: string, snapshot_name: string) => {
137 const task = new ExecutingTask();
138 task.name = task_name;
139 task.metadata = {
9f95a23c 140 image_spec: 'rbd/foo',
11fdf7f2
TL
141 snapshot_name: snapshot_name
142 };
143 summaryService.addRunningTask(task);
144 };
145
9f95a23c 146 const refresh = (data: any) => {
11fdf7f2
TL
147 summaryService['summaryDataSource'].next(data);
148 };
149
150 beforeEach(() => {
151 fixture.detectChanges();
152 snapshots = [];
153 addSnapshot('a');
154 addSnapshot('b');
155 addSnapshot('c');
156 component.snapshots = snapshots;
157 component.poolName = 'rbd';
158 component.rbdName = 'foo';
159 refresh({ executing_tasks: [], finished_tasks: [] });
160 component.ngOnChanges();
161 fixture.detectChanges();
162 });
163
164 it('should gets all snapshots without tasks', () => {
165 expect(component.snapshots.length).toBe(3);
166 expect(component.snapshots.every((image) => !image.cdExecuting)).toBeTruthy();
167 });
168
169 it('should add a new image from a task', () => {
170 addTask('rbd/snap/create', 'd');
171 expect(component.snapshots.length).toBe(4);
eafe8130
TL
172 expectItemTasks(component.snapshots[0], undefined);
173 expectItemTasks(component.snapshots[1], undefined);
174 expectItemTasks(component.snapshots[2], undefined);
175 expectItemTasks(component.snapshots[3], 'Creating');
11fdf7f2
TL
176 });
177
178 it('should show when an existing image is being modified', () => {
179 addTask('rbd/snap/edit', 'a');
180 addTask('rbd/snap/delete', 'b');
181 addTask('rbd/snap/rollback', 'c');
182 expect(component.snapshots.length).toBe(3);
eafe8130
TL
183 expectItemTasks(component.snapshots[0], 'Updating');
184 expectItemTasks(component.snapshots[1], 'Deleting');
185 expectItemTasks(component.snapshots[2], 'Rolling back');
11fdf7f2
TL
186 });
187 });
188
189 describe('snapshot modal dialog', () => {
190 beforeEach(() => {
191 component.poolName = 'pool01';
192 component.rbdName = 'image01';
92f5a8d4 193 spyOn(TestBed.get(BsModalService), 'show').and.callFake(() => {
11fdf7f2 194 const ref = new BsModalRef();
9f95a23c 195 ref.content = new RbdSnapshotFormModalComponent(
92f5a8d4
TL
196 null,
197 null,
198 null,
199 null,
200 TestBed.get(I18n),
201 TestBed.get(ActionLabelsI18n)
202 );
11fdf7f2
TL
203 ref.content.onSubmit = new Subject();
204 return ref;
205 });
206 });
207
208 it('should display old snapshot name', () => {
209 component.selection.selected = [{ name: 'oldname' }];
11fdf7f2
TL
210 component.openEditSnapshotModal();
211 expect(component.modalRef.content.snapName).toBe('oldname');
212 expect(component.modalRef.content.editing).toBeTruthy();
213 });
214
215 it('should display suggested snapshot name', () => {
216 component.openCreateSnapshotModal();
217 expect(component.modalRef.content.snapName).toMatch(
9f95a23c 218 RegExp(`^${component.rbdName}_[\\d-]+T[\\d.:]+[\\+-][\\d:]+$`)
11fdf7f2
TL
219 );
220 });
221 });
222
9f95a23c
TL
223 it('should test all TableActions combinations', () => {
224 const permissionHelper: PermissionHelper = new PermissionHelper(component.permission);
225 const tableActions: TableActionsComponent = permissionHelper.setPermissionsAndGetActions(
226 component.tableActions
227 );
228
229 expect(tableActions).toEqual({
230 'create,update,delete': {
231 actions: [
232 'Create',
233 'Rename',
234 'Protect',
235 'Unprotect',
236 'Clone',
237 'Copy',
238 'Rollback',
239 'Delete'
240 ],
241 primary: { multiple: 'Create', executing: 'Rename', single: 'Rename', no: 'Create' }
242 },
243 'create,update': {
244 actions: ['Create', 'Rename', 'Protect', 'Unprotect', 'Clone', 'Copy', 'Rollback'],
245 primary: { multiple: 'Create', executing: 'Rename', single: 'Rename', no: 'Create' }
246 },
247 'create,delete': {
248 actions: ['Create', 'Clone', 'Copy', 'Delete'],
249 primary: { multiple: 'Create', executing: 'Clone', single: 'Clone', no: 'Create' }
250 },
251 create: {
252 actions: ['Create', 'Clone', 'Copy'],
253 primary: { multiple: 'Create', executing: 'Clone', single: 'Clone', no: 'Create' }
254 },
255 'update,delete': {
256 actions: ['Rename', 'Protect', 'Unprotect', 'Rollback', 'Delete'],
257 primary: { multiple: 'Rename', executing: 'Rename', single: 'Rename', no: 'Rename' }
258 },
259 update: {
260 actions: ['Rename', 'Protect', 'Unprotect', 'Rollback'],
261 primary: { multiple: 'Rename', executing: 'Rename', single: 'Rename', no: 'Rename' }
262 },
263 delete: {
264 actions: ['Delete'],
265 primary: { multiple: 'Delete', executing: 'Delete', single: 'Delete', no: 'Delete' }
266 },
267 'no-permissions': {
268 actions: [],
269 primary: { multiple: '', executing: '', single: '', no: '' }
270 }
11fdf7f2
TL
271 });
272 });
273});