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