1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3 import { RouterTestingModule } from '@angular/router/testing';
5 import { I18n } from '@ngx-translate/i18n-polyfill';
6 import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
7 import { ToastrModule } from 'ngx-toastr';
8 import { Subject, throwError as observableThrowError } from 'rxjs';
15 } from '../../../../testing/unit-test-helper';
16 import { ApiModule } from '../../../shared/api/api.module';
17 import { RbdService } from '../../../shared/api/rbd.service';
18 import { ComponentsModule } from '../../../shared/components/components.module';
19 import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
20 import { DataTableModule } from '../../../shared/datatable/datatable.module';
21 import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
22 import { ExecutingTask } from '../../../shared/models/executing-task';
23 import { Permissions } from '../../../shared/models/permissions';
24 import { PipesModule } from '../../../shared/pipes/pipes.module';
25 import { AuthStorageService } from '../../../shared/services/auth-storage.service';
26 import { NotificationService } from '../../../shared/services/notification.service';
27 import { SummaryService } from '../../../shared/services/summary.service';
28 import { TaskListService } from '../../../shared/services/task-list.service';
29 import { RbdSnapshotFormComponent } from '../rbd-snapshot-form/rbd-snapshot-form.component';
30 import { RbdSnapshotListComponent } from './rbd-snapshot-list.component';
31 import { RbdSnapshotModel } from './rbd-snapshot.model';
33 describe('RbdSnapshotListComponent', () => {
34 let component: RbdSnapshotListComponent;
35 let fixture: ComponentFixture<RbdSnapshotListComponent>;
36 let summaryService: SummaryService;
38 const fakeAuthStorageService = {
42 getPermissions: () => {
43 return new Permissions({ 'rbd-image': ['read', 'update', 'create', 'delete'] });
48 declarations: [RbdSnapshotListComponent],
52 ToastrModule.forRoot(),
54 HttpClientTestingModule,
59 { provide: AuthStorageService, useValue: fakeAuthStorageService },
66 fixture = TestBed.createComponent(RbdSnapshotListComponent);
67 component = fixture.componentInstance;
68 component.ngOnChanges();
69 summaryService = TestBed.get(SummaryService);
72 it('should create', () => {
73 fixture.detectChanges();
74 expect(component).toBeTruthy();
77 describe('api delete request', () => {
79 let rbdService: RbdService;
80 let notificationService: NotificationService;
81 let authStorageService: AuthStorageService;
84 fixture.detectChanges();
85 const i18n = TestBed.get(I18n);
86 const actionLabelsI18n = TestBed.get(ActionLabelsI18n);
88 rbdService = new RbdService(null, null);
89 notificationService = new NotificationService(null, null, null);
90 authStorageService = new AuthStorageService();
91 authStorageService.set('user', '', { 'rbd-image': ['create', 'read', 'update', 'delete'] });
92 component = new RbdSnapshotListComponent(
105 spyOn(rbdService, 'deleteSnapshot').and.returnValue(observableThrowError({ status: 500 }));
106 spyOn(notificationService, 'notifyTask').and.stub();
107 component.modalRef = new BsModalRef();
108 component.modalRef.content = {
109 stopLoadingSpinner: () => (called = true)
113 it('should call stopLoadingSpinner if the request fails', <any>fakeAsync(() => {
114 expect(called).toBe(false);
115 component._asyncTask('deleteSnapshot', 'rbd/snap/delete', 'someName');
117 expect(called).toBe(true);
121 describe('handling of executing tasks', () => {
122 let snapshots: RbdSnapshotModel[];
124 const addSnapshot = (name: string) => {
125 const model = new RbdSnapshotModel();
128 snapshots.push(model);
131 const addTask = (task_name: string, snapshot_name: string) => {
132 const task = new ExecutingTask();
133 task.name = task_name;
135 image_spec: 'rbd/foo',
136 snapshot_name: snapshot_name
138 summaryService.addRunningTask(task);
141 const refresh = (data: any) => {
142 summaryService['summaryDataSource'].next(data);
146 fixture.detectChanges();
151 component.snapshots = snapshots;
152 component.poolName = 'rbd';
153 component.rbdName = 'foo';
154 refresh({ executing_tasks: [], finished_tasks: [] });
155 component.ngOnChanges();
156 fixture.detectChanges();
159 it('should gets all snapshots without tasks', () => {
160 expect(component.snapshots.length).toBe(3);
161 expect(component.snapshots.every((image) => !image.cdExecuting)).toBeTruthy();
164 it('should add a new image from a task', () => {
165 addTask('rbd/snap/create', 'd');
166 expect(component.snapshots.length).toBe(4);
167 expectItemTasks(component.snapshots[0], undefined);
168 expectItemTasks(component.snapshots[1], undefined);
169 expectItemTasks(component.snapshots[2], undefined);
170 expectItemTasks(component.snapshots[3], 'Creating');
173 it('should show when an existing image is being modified', () => {
174 addTask('rbd/snap/edit', 'a');
175 addTask('rbd/snap/delete', 'b');
176 addTask('rbd/snap/rollback', 'c');
177 expect(component.snapshots.length).toBe(3);
178 expectItemTasks(component.snapshots[0], 'Updating');
179 expectItemTasks(component.snapshots[1], 'Deleting');
180 expectItemTasks(component.snapshots[2], 'Rolling back');
184 describe('snapshot modal dialog', () => {
186 component.poolName = 'pool01';
187 component.rbdName = 'image01';
188 spyOn(TestBed.get(BsModalService), 'show').and.callFake(() => {
189 const ref = new BsModalRef();
190 ref.content = new RbdSnapshotFormComponent(
196 TestBed.get(ActionLabelsI18n)
198 ref.content.onSubmit = new Subject();
203 it('should display old snapshot name', () => {
204 component.selection.selected = [{ name: 'oldname' }];
205 component.openEditSnapshotModal();
206 expect(component.modalRef.content.snapName).toBe('oldname');
207 expect(component.modalRef.content.editing).toBeTruthy();
210 it('should display suggested snapshot name', () => {
211 component.openCreateSnapshotModal();
212 expect(component.modalRef.content.snapName).toMatch(
213 RegExp(`^${component.rbdName}_[\\d-]+T[\\d.:]+[\\+-][\\d:]+$`)
218 it('should test all TableActions combinations', () => {
219 const permissionHelper: PermissionHelper = new PermissionHelper(component.permission);
220 const tableActions: TableActionsComponent = permissionHelper.setPermissionsAndGetActions(
221 component.tableActions
224 expect(tableActions).toEqual({
225 'create,update,delete': {
236 primary: { multiple: 'Create', executing: 'Rename', single: 'Rename', no: 'Create' }
239 actions: ['Create', 'Rename', 'Protect', 'Unprotect', 'Clone', 'Copy', 'Rollback'],
240 primary: { multiple: 'Create', executing: 'Rename', single: 'Rename', no: 'Create' }
243 actions: ['Create', 'Clone', 'Copy', 'Delete'],
244 primary: { multiple: 'Create', executing: 'Clone', single: 'Clone', no: 'Create' }
247 actions: ['Create', 'Clone', 'Copy'],
248 primary: { multiple: 'Create', executing: 'Clone', single: 'Clone', no: 'Create' }
251 actions: ['Rename', 'Protect', 'Unprotect', 'Rollback', 'Delete'],
252 primary: { multiple: 'Rename', executing: 'Rename', single: 'Rename', no: 'Rename' }
255 actions: ['Rename', 'Protect', 'Unprotect', 'Rollback'],
256 primary: { multiple: 'Rename', executing: 'Rename', single: 'Rename', no: 'Rename' }
260 primary: { multiple: 'Delete', executing: 'Delete', single: 'Delete', no: 'Delete' }
264 primary: { multiple: '', executing: '', single: '', no: '' }