]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/blob
16ff57abd2319d381a0a06540ee5bb33b9e3cceb
[ceph.git] /
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
4 import { RouterTestingModule } from '@angular/router/testing';
5
6 import { TreeModule } from 'angular-tree-component';
7 import { TabsModule } from 'ngx-bootstrap/tabs';
8 import { ToastrModule } from 'ngx-toastr';
9 import { BehaviorSubject, of } from 'rxjs';
10
11 import {
12   configureTestBed,
13   expectItemTasks,
14   i18nProviders,
15   PermissionHelper
16 } from '../../../../testing/unit-test-helper';
17 import { IscsiService } from '../../../shared/api/iscsi.service';
18 import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
19 import { CdTableAction } from '../../../shared/models/cd-table-action';
20 import { ExecutingTask } from '../../../shared/models/executing-task';
21 import { SummaryService } from '../../../shared/services/summary.service';
22 import { TaskListService } from '../../../shared/services/task-list.service';
23 import { SharedModule } from '../../../shared/shared.module';
24 import { IscsiTabsComponent } from '../iscsi-tabs/iscsi-tabs.component';
25 import { IscsiTargetDetailsComponent } from '../iscsi-target-details/iscsi-target-details.component';
26 import { IscsiTargetListComponent } from './iscsi-target-list.component';
27
28 describe('IscsiTargetListComponent', () => {
29   let component: IscsiTargetListComponent;
30   let fixture: ComponentFixture<IscsiTargetListComponent>;
31   let summaryService: SummaryService;
32   let iscsiService: IscsiService;
33
34   const refresh = (data: any) => {
35     summaryService['summaryDataSource'].next(data);
36   };
37
38   configureTestBed({
39     imports: [
40       BrowserAnimationsModule,
41       HttpClientTestingModule,
42       RouterTestingModule,
43       SharedModule,
44       TabsModule.forRoot(),
45       TreeModule,
46       ToastrModule.forRoot()
47     ],
48     declarations: [IscsiTargetListComponent, IscsiTabsComponent, IscsiTargetDetailsComponent],
49     providers: [TaskListService, i18nProviders]
50   });
51
52   beforeEach(() => {
53     fixture = TestBed.createComponent(IscsiTargetListComponent);
54     component = fixture.componentInstance;
55     summaryService = TestBed.get(SummaryService);
56     iscsiService = TestBed.get(IscsiService);
57
58     // this is needed because summaryService isn't being reset after each test.
59     summaryService['summaryDataSource'] = new BehaviorSubject(null);
60     summaryService['summaryData$'] = summaryService['summaryDataSource'].asObservable();
61
62     spyOn(iscsiService, 'status').and.returnValue(of({ available: true }));
63     spyOn(iscsiService, 'version').and.returnValue(of({ ceph_iscsi_config_version: 11 }));
64   });
65
66   it('should create', () => {
67     expect(component).toBeTruthy();
68   });
69
70   describe('after ngOnInit', () => {
71     beforeEach(() => {
72       spyOn(iscsiService, 'listTargets').and.callThrough();
73       fixture.detectChanges();
74     });
75
76     it('should load targets on init', () => {
77       refresh({});
78       expect(iscsiService.status).toHaveBeenCalled();
79       expect(iscsiService.listTargets).toHaveBeenCalled();
80     });
81
82     it('should not load targets on init because no data', () => {
83       refresh(undefined);
84       expect(iscsiService.listTargets).not.toHaveBeenCalled();
85     });
86
87     it('should call error function on init when summary service fails', () => {
88       spyOn(component.table, 'reset');
89       summaryService['summaryDataSource'].error(undefined);
90       expect(component.table.reset).toHaveBeenCalled();
91     });
92   });
93
94   describe('handling of executing tasks', () => {
95     let targets: any[];
96
97     const addTarget = (name: string) => {
98       const model: any = {
99         target_iqn: name,
100         portals: [{ host: 'node1', ip: '192.168.100.201' }],
101         disks: [{ pool: 'rbd', image: 'disk_1', controls: {} }],
102         clients: [
103           {
104             client_iqn: 'iqn.1994-05.com.redhat:rh7-client',
105             luns: [{ pool: 'rbd', image: 'disk_1' }],
106             auth: {
107               user: 'myiscsiusername',
108               password: 'myiscsipassword',
109               mutual_user: null,
110               mutual_password: null
111             }
112           }
113         ],
114         groups: [],
115         target_controls: {}
116       };
117       targets.push(model);
118     };
119
120     const addTask = (name: string, target_iqn: string) => {
121       const task = new ExecutingTask();
122       task.name = name;
123       switch (task.name) {
124         case 'iscsi/target/create':
125           task.metadata = {
126             target_iqn: target_iqn
127           };
128           break;
129         case 'iscsi/target/delete':
130           task.metadata = {
131             target_iqn: target_iqn
132           };
133           break;
134         default:
135           task.metadata = {
136             target_iqn: target_iqn
137           };
138           break;
139       }
140       summaryService.addRunningTask(task);
141     };
142
143     beforeEach(() => {
144       targets = [];
145       addTarget('iqn.a');
146       addTarget('iqn.b');
147       addTarget('iqn.c');
148
149       component.targets = targets;
150       refresh({ executing_tasks: [], finished_tasks: [] });
151       spyOn(iscsiService, 'listTargets').and.callFake(() => of(targets));
152       fixture.detectChanges();
153     });
154
155     it('should gets all targets without tasks', () => {
156       expect(component.targets.length).toBe(3);
157       expect(component.targets.every((target) => !target.cdExecuting)).toBeTruthy();
158     });
159
160     it('should add a new target from a task', () => {
161       addTask('iscsi/target/create', 'iqn.d');
162       expect(component.targets.length).toBe(4);
163       expectItemTasks(component.targets[0], undefined);
164       expectItemTasks(component.targets[1], undefined);
165       expectItemTasks(component.targets[2], undefined);
166       expectItemTasks(component.targets[3], 'Creating');
167     });
168
169     it('should show when an existing target is being modified', () => {
170       addTask('iscsi/target/delete', 'iqn.b');
171       expect(component.targets.length).toBe(3);
172       expectItemTasks(component.targets[1], 'Deleting');
173     });
174   });
175
176   describe('handling of actions', () => {
177     beforeEach(() => {
178       fixture.detectChanges();
179     });
180
181     let action: CdTableAction;
182
183     const getAction = (name: string): CdTableAction => {
184       return component.tableActions.find((tableAction) => tableAction.name === name);
185     };
186
187     describe('edit', () => {
188       beforeEach(() => {
189         action = getAction('Edit');
190       });
191
192       it('should be disabled if no gateways', () => {
193         component.selection.selected = [
194           {
195             id: '-1'
196           }
197         ];
198         expect(action.disable(undefined)).toBeTruthy();
199         expect(action.disableDesc(undefined)).toBe('Unavailable gateway(s)');
200       });
201
202       it('should be enabled if active sessions', () => {
203         component.selection.selected = [
204           {
205             id: '-1',
206             info: {
207               num_sessions: 1
208             }
209           }
210         ];
211         expect(action.disable(undefined)).toBeFalsy();
212         expect(action.disableDesc(undefined)).toBeUndefined();
213       });
214
215       it('should be enabled if no active sessions', () => {
216         component.selection.selected = [
217           {
218             id: '-1',
219             info: {
220               num_sessions: 0
221             }
222           }
223         ];
224         expect(action.disable(undefined)).toBeFalsy();
225         expect(action.disableDesc(undefined)).toBeUndefined();
226       });
227     });
228
229     describe('delete', () => {
230       beforeEach(() => {
231         action = getAction('Delete');
232       });
233
234       it('should be disabled if no gateways', () => {
235         component.selection.selected = [
236           {
237             id: '-1'
238           }
239         ];
240         expect(action.disable(undefined)).toBeTruthy();
241         expect(action.disableDesc(undefined)).toBe('Unavailable gateway(s)');
242       });
243
244       it('should be disabled if active sessions', () => {
245         component.selection.selected = [
246           {
247             id: '-1',
248             info: {
249               num_sessions: 1
250             }
251           }
252         ];
253         expect(action.disable(undefined)).toBeTruthy();
254         expect(action.disableDesc(undefined)).toBe('Target has active sessions');
255       });
256
257       it('should be enabled if no active sessions', () => {
258         component.selection.selected = [
259           {
260             id: '-1',
261             info: {
262               num_sessions: 0
263             }
264           }
265         ];
266         expect(action.disable(undefined)).toBeFalsy();
267         expect(action.disableDesc(undefined)).toBeUndefined();
268       });
269     });
270   });
271
272   it('should test all TableActions combinations', () => {
273     const permissionHelper: PermissionHelper = new PermissionHelper(component.permission);
274     const tableActions: TableActionsComponent = permissionHelper.setPermissionsAndGetActions(
275       component.tableActions
276     );
277
278     expect(tableActions).toEqual({
279       'create,update,delete': {
280         actions: ['Create', 'Edit', 'Delete'],
281         primary: { multiple: 'Create', executing: 'Edit', single: 'Edit', no: 'Create' }
282       },
283       'create,update': {
284         actions: ['Create', 'Edit'],
285         primary: { multiple: 'Create', executing: 'Edit', single: 'Edit', no: 'Create' }
286       },
287       'create,delete': {
288         actions: ['Create', 'Delete'],
289         primary: { multiple: 'Create', executing: 'Delete', single: 'Delete', no: 'Create' }
290       },
291       create: {
292         actions: ['Create'],
293         primary: { multiple: 'Create', executing: 'Create', single: 'Create', no: 'Create' }
294       },
295       'update,delete': {
296         actions: ['Edit', 'Delete'],
297         primary: { multiple: 'Edit', executing: 'Edit', single: 'Edit', no: 'Edit' }
298       },
299       update: {
300         actions: ['Edit'],
301         primary: { multiple: 'Edit', executing: 'Edit', single: 'Edit', no: 'Edit' }
302       },
303       delete: {
304         actions: ['Delete'],
305         primary: { multiple: 'Delete', executing: 'Delete', single: 'Delete', no: 'Delete' }
306       },
307       'no-permissions': {
308         actions: [],
309         primary: { multiple: '', executing: '', single: '', no: '' }
310       }
311     });
312   });
313 });