]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
299ef33deaa84d119e2f84f9a46cec10e8b7657c
[ceph-ci.git] /
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { By } from '@angular/platform-browser';
4 import { RouterTestingModule } from '@angular/router/testing';
5
6 import { ToastModule } from 'ng2-toastr';
7 import { TreeModule } from 'ng2-tree';
8 import { TabsModule } from 'ngx-bootstrap/tabs';
9 import { BehaviorSubject, of } from 'rxjs';
10
11 import {
12   configureTestBed,
13   i18nProviders,
14   PermissionHelper
15 } from '../../../../testing/unit-test-helper';
16 import { IscsiService } from '../../../shared/api/iscsi.service';
17 import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
18 import { ExecutingTask } from '../../../shared/models/executing-task';
19 import { SummaryService } from '../../../shared/services/summary.service';
20 import { TaskListService } from '../../../shared/services/task-list.service';
21 import { SharedModule } from '../../../shared/shared.module';
22 import { IscsiTabsComponent } from '../iscsi-tabs/iscsi-tabs.component';
23 import { IscsiTargetDetailsComponent } from '../iscsi-target-details/iscsi-target-details.component';
24 import { IscsiTargetListComponent } from './iscsi-target-list.component';
25
26 describe('IscsiTargetListComponent', () => {
27   let component: IscsiTargetListComponent;
28   let fixture: ComponentFixture<IscsiTargetListComponent>;
29   let summaryService: SummaryService;
30   let iscsiService: IscsiService;
31
32   const refresh = (data) => {
33     summaryService['summaryDataSource'].next(data);
34   };
35
36   configureTestBed({
37     imports: [
38       HttpClientTestingModule,
39       RouterTestingModule,
40       SharedModule,
41       TabsModule.forRoot(),
42       TreeModule,
43       ToastModule.forRoot()
44     ],
45     declarations: [IscsiTargetListComponent, IscsiTabsComponent, IscsiTargetDetailsComponent],
46     providers: [TaskListService, i18nProviders]
47   });
48
49   beforeEach(() => {
50     fixture = TestBed.createComponent(IscsiTargetListComponent);
51     component = fixture.componentInstance;
52     summaryService = TestBed.get(SummaryService);
53     iscsiService = TestBed.get(IscsiService);
54
55     // this is needed because summaryService isn't being reset after each test.
56     summaryService['summaryDataSource'] = new BehaviorSubject(null);
57     summaryService['summaryData$'] = summaryService['summaryDataSource'].asObservable();
58
59     spyOn(iscsiService, 'status').and.returnValue(of({ available: true }));
60   });
61
62   it('should create', () => {
63     expect(component).toBeTruthy();
64   });
65
66   describe('after ngOnInit', () => {
67     beforeEach(() => {
68       spyOn(iscsiService, 'listTargets').and.callThrough();
69       fixture.detectChanges();
70     });
71
72     it('should load targets on init', () => {
73       refresh({});
74       expect(iscsiService.status).toHaveBeenCalled();
75       expect(iscsiService.listTargets).toHaveBeenCalled();
76     });
77
78     it('should not load targets on init because no data', () => {
79       refresh(undefined);
80       expect(iscsiService.listTargets).not.toHaveBeenCalled();
81     });
82
83     it('should call error function on init when summary service fails', () => {
84       spyOn(component.table, 'reset');
85       summaryService['summaryDataSource'].error(undefined);
86       expect(component.table.reset).toHaveBeenCalled();
87     });
88   });
89
90   describe('handling of executing tasks', () => {
91     let targets: any[];
92
93     const addTarget = (name) => {
94       const model: any = {
95         target_iqn: name,
96         portals: [{ host: 'node1', ip: '192.168.100.201' }],
97         disks: [{ pool: 'rbd', image: 'disk_1', controls: {} }],
98         clients: [
99           {
100             client_iqn: 'iqn.1994-05.com.redhat:rh7-client',
101             luns: [{ pool: 'rbd', image: 'disk_1' }],
102             auth: {
103               user: 'myiscsiusername',
104               password: 'myiscsipassword',
105               mutual_user: null,
106               mutual_password: null
107             }
108           }
109         ],
110         groups: [],
111         target_controls: {}
112       };
113       targets.push(model);
114     };
115
116     const addTask = (name: string, target_iqn: string) => {
117       const task = new ExecutingTask();
118       task.name = name;
119       switch (task.name) {
120         case 'iscsi/target/create':
121           task.metadata = {
122             target_iqn: target_iqn
123           };
124           break;
125         case 'iscsi/target/delete':
126           task.metadata = {
127             target_iqn: target_iqn
128           };
129           break;
130         default:
131           task.metadata = {
132             target_iqn: target_iqn
133           };
134           break;
135       }
136       summaryService.addRunningTask(task);
137     };
138
139     const expectTargetTasks = (target: any, executing: string) => {
140       expect(target.cdExecuting).toEqual(executing);
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       expectTargetTasks(component.targets[0], undefined);
164       expectTargetTasks(component.targets[1], undefined);
165       expectTargetTasks(component.targets[2], undefined);
166       expectTargetTasks(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       expectTargetTasks(component.targets[1], 'Deleting');
173     });
174   });
175
176   describe('show action buttons and drop down actions depending on permissions', () => {
177     let tableActions: TableActionsComponent;
178     let scenario: { fn; empty; single };
179     let permissionHelper: PermissionHelper;
180
181     const getTableActionComponent = (): TableActionsComponent => {
182       fixture.detectChanges();
183       return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
184     };
185
186     beforeEach(() => {
187       permissionHelper = new PermissionHelper(component.permissions.iscsi, () =>
188         getTableActionComponent()
189       );
190       scenario = {
191         fn: () => tableActions.getCurrentButton().name,
192         single: 'Delete',
193         empty: 'Add'
194       };
195     });
196
197     describe('with all', () => {
198       beforeEach(() => {
199         tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
200       });
201
202       it(`shows 'Delete' for single selection else 'Add' as main action`, () =>
203         permissionHelper.testScenarios(scenario));
204
205       it('shows all actions', () => {
206         expect(tableActions.tableActions.length).toBe(2);
207         expect(tableActions.tableActions).toEqual(component.tableActions);
208       });
209     });
210
211     describe('with read, create and update', () => {
212       beforeEach(() => {
213         tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
214         scenario.single = 'Add';
215       });
216
217       it(`should always show 'Add'`, () => {
218         permissionHelper.testScenarios(scenario);
219       });
220
221       it(`shows all actions except for 'Delete'`, () => {
222         expect(tableActions.tableActions.length).toBe(1);
223         component.tableActions.pop();
224         expect(tableActions.tableActions).toEqual(component.tableActions);
225       });
226     });
227
228     describe('with read, create and delete', () => {
229       beforeEach(() => {
230         tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
231       });
232
233       it(`shows 'Delete' for single selection else 'Add' as main action`, () => {
234         scenario.single = 'Delete';
235         permissionHelper.testScenarios(scenario);
236       });
237
238       it(`shows 'Add' and 'Delete' actions`, () => {
239         expect(tableActions.tableActions.length).toBe(2);
240         expect(tableActions.tableActions).toEqual([
241           component.tableActions[0],
242           component.tableActions[1]
243         ]);
244       });
245     });
246
247     describe('with read, edit and delete', () => {
248       beforeEach(() => {
249         tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
250       });
251
252       it(`shows always 'Delete' as main action`, () => {
253         scenario.empty = 'Delete';
254         permissionHelper.testScenarios(scenario);
255       });
256
257       it(`shows 'Delete' action`, () => {
258         expect(tableActions.tableActions.length).toBe(1);
259         expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
260       });
261     });
262
263     describe('with read and create', () => {
264       beforeEach(() => {
265         tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
266       });
267
268       it(`shows 'Add' for single selection and 'Add' as main action`, () => {
269         scenario.single = 'Add';
270         permissionHelper.testScenarios(scenario);
271       });
272
273       it(`shows 'Add' actions`, () => {
274         expect(tableActions.tableActions.length).toBe(1);
275         expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
276       });
277     });
278
279     describe('with read and edit', () => {
280       beforeEach(() => {
281         tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
282       });
283
284       it(`shows no actions`, () => {
285         expect(tableActions.tableActions.length).toBe(0);
286         expect(tableActions.tableActions).toEqual([]);
287       });
288     });
289
290     describe('with read and delete', () => {
291       beforeEach(() => {
292         tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
293       });
294
295       it(`shows always 'Delete' as main action`, () => {
296         scenario.single = 'Delete';
297         scenario.empty = 'Delete';
298         permissionHelper.testScenarios(scenario);
299       });
300
301       it(`shows 'Delete' actions`, () => {
302         expect(tableActions.tableActions.length).toBe(1);
303         expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
304       });
305     });
306
307     describe('with only read', () => {
308       beforeEach(() => {
309         tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
310       });
311
312       it('shows no main action', () => {
313         permissionHelper.testScenarios({
314           fn: () => tableActions.getCurrentButton(),
315           single: undefined,
316           empty: undefined
317         });
318       });
319
320       it('shows no actions', () => {
321         expect(tableActions.tableActions.length).toBe(0);
322         expect(tableActions.tableActions).toEqual([]);
323       });
324     });
325   });
326 });