]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.spec.ts
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / block / iscsi-target-list / iscsi-target-list.component.spec.ts
CommitLineData
11fdf7f2
TL
1import { HttpClientTestingModule } from '@angular/common/http/testing';
2import { ComponentFixture, TestBed } from '@angular/core/testing';
3import { By } from '@angular/platform-browser';
4import { RouterTestingModule } from '@angular/router/testing';
5
11fdf7f2
TL
6import { TreeModule } from 'ng2-tree';
7import { TabsModule } from 'ngx-bootstrap/tabs';
494da23a 8import { ToastrModule } from 'ngx-toastr';
11fdf7f2
TL
9import { BehaviorSubject, of } from 'rxjs';
10
11import {
12 configureTestBed,
13 i18nProviders,
14 PermissionHelper
15} from '../../../../testing/unit-test-helper';
16import { IscsiService } from '../../../shared/api/iscsi.service';
17import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
18import { ExecutingTask } from '../../../shared/models/executing-task';
19import { SummaryService } from '../../../shared/services/summary.service';
20import { TaskListService } from '../../../shared/services/task-list.service';
21import { SharedModule } from '../../../shared/shared.module';
22import { IscsiTabsComponent } from '../iscsi-tabs/iscsi-tabs.component';
23import { IscsiTargetDetailsComponent } from '../iscsi-target-details/iscsi-target-details.component';
24import { IscsiTargetListComponent } from './iscsi-target-list.component';
25
26describe('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,
494da23a 43 ToastrModule.forRoot()
11fdf7f2
TL
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: 'Edit',
193 empty: 'Add'
194 };
195 });
196
197 describe('with all', () => {
198 beforeEach(() => {
199 tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
200 });
201
202 it(`shows 'Edit' for single selection else 'Add' as main action`, () => {
203 permissionHelper.testScenarios(scenario);
204 });
205
206 it('shows all actions', () => {
207 expect(tableActions.tableActions.length).toBe(3);
208 expect(tableActions.tableActions).toEqual(component.tableActions);
209 });
210 });
211
212 describe('with read, create and update', () => {
213 beforeEach(() => {
214 tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
215 scenario.single = 'Edit';
216 });
217
218 it(`should always show 'Edit'`, () => {
219 permissionHelper.testScenarios(scenario);
220 });
221
222 it(`shows all actions except for 'Delete'`, () => {
223 expect(tableActions.tableActions.length).toBe(2);
224 component.tableActions.pop();
225 expect(tableActions.tableActions).toEqual(component.tableActions);
226 });
227 });
228
229 describe('with read, create and delete', () => {
230 beforeEach(() => {
231 tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
232 });
233
234 it(`shows 'Delete' for single selection else 'Add' as main action`, () => {
235 scenario.single = 'Delete';
236 permissionHelper.testScenarios(scenario);
237 });
238
239 it(`shows 'Add' and 'Delete' actions`, () => {
240 expect(tableActions.tableActions.length).toBe(2);
241 expect(tableActions.tableActions).toEqual([
242 component.tableActions[0],
243 component.tableActions[2]
244 ]);
245 });
246 });
247
248 describe('with read, edit and delete', () => {
249 beforeEach(() => {
250 tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
251 });
252
253 it(`shows always 'Edit' as main action`, () => {
254 scenario.empty = 'Edit';
255 permissionHelper.testScenarios(scenario);
256 });
257
258 it(`shows 'Edit' and 'Delete' actions`, () => {
259 expect(tableActions.tableActions.length).toBe(2);
260 expect(tableActions.tableActions).toEqual([
261 component.tableActions[1],
262 component.tableActions[2]
263 ]);
264 });
265 });
266
267 describe('with read and create', () => {
268 beforeEach(() => {
269 tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
270 });
271
272 it(`shows 'Add' for single selection and 'Add' as main action`, () => {
273 scenario.single = 'Add';
274 permissionHelper.testScenarios(scenario);
275 });
276
277 it(`shows 'Add' actions`, () => {
278 expect(tableActions.tableActions.length).toBe(1);
279 expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
280 });
281 });
282
283 describe('with read and edit', () => {
284 beforeEach(() => {
285 tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
286 });
287
288 it(`shows no actions`, () => {
289 expect(tableActions.tableActions.length).toBe(1);
290 expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
291 });
292 });
293
294 describe('with read and delete', () => {
295 beforeEach(() => {
296 tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
297 });
298
299 it(`shows always 'Delete' as main action`, () => {
300 scenario.single = 'Delete';
301 scenario.empty = 'Delete';
302 permissionHelper.testScenarios(scenario);
303 });
304
305 it(`shows 'Delete' actions`, () => {
306 expect(tableActions.tableActions.length).toBe(1);
307 expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
308 });
309 });
310
311 describe('with only read', () => {
312 beforeEach(() => {
313 tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
314 });
315
316 it('shows no main action', () => {
317 permissionHelper.testScenarios({
318 fn: () => tableActions.getCurrentButton(),
319 single: undefined,
320 empty: undefined
321 });
322 });
323
324 it('shows no actions', () => {
325 expect(tableActions.tableActions.length).toBe(0);
326 expect(tableActions.tableActions).toEqual([]);
327 });
328 });
329 });
330});