]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { HttpClientTestingModule } from '@angular/common/http/testing'; |
2 | import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; | |
11fdf7f2 TL |
3 | import { RouterTestingModule } from '@angular/router/testing'; |
4 | ||
5 | import { I18n } from '@ngx-translate/i18n-polyfill'; | |
11fdf7f2 | 6 | import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; |
9f95a23c | 7 | import { TabsModule } from 'ngx-bootstrap/tabs'; |
494da23a | 8 | import { ToastrModule } from 'ngx-toastr'; |
11fdf7f2 TL |
9 | import { Subject, throwError as observableThrowError } from 'rxjs'; |
10 | ||
11 | import { | |
12 | configureTestBed, | |
eafe8130 | 13 | expectItemTasks, |
11fdf7f2 TL |
14 | i18nProviders, |
15 | PermissionHelper | |
16 | } from '../../../../testing/unit-test-helper'; | |
17 | import { ApiModule } from '../../../shared/api/api.module'; | |
18 | import { RbdService } from '../../../shared/api/rbd.service'; | |
19 | import { ComponentsModule } from '../../../shared/components/components.module'; | |
eafe8130 | 20 | import { ActionLabelsI18n } from '../../../shared/constants/app.constants'; |
11fdf7f2 TL |
21 | import { DataTableModule } from '../../../shared/datatable/datatable.module'; |
22 | import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component'; | |
23 | import { ExecutingTask } from '../../../shared/models/executing-task'; | |
24 | import { Permissions } from '../../../shared/models/permissions'; | |
25 | import { PipesModule } from '../../../shared/pipes/pipes.module'; | |
26 | import { AuthStorageService } from '../../../shared/services/auth-storage.service'; | |
27 | import { NotificationService } from '../../../shared/services/notification.service'; | |
11fdf7f2 TL |
28 | import { SummaryService } from '../../../shared/services/summary.service'; |
29 | import { TaskListService } from '../../../shared/services/task-list.service'; | |
9f95a23c TL |
30 | import { RbdSnapshotFormModalComponent } from '../rbd-snapshot-form/rbd-snapshot-form-modal.component'; |
31 | import { RbdTabsComponent } from '../rbd-tabs/rbd-tabs.component'; | |
11fdf7f2 TL |
32 | import { RbdSnapshotListComponent } from './rbd-snapshot-list.component'; |
33 | import { RbdSnapshotModel } from './rbd-snapshot.model'; | |
34 | ||
35 | describe('RbdSnapshotListComponent', () => { | |
36 | let component: RbdSnapshotListComponent; | |
37 | let fixture: ComponentFixture<RbdSnapshotListComponent>; | |
38 | let summaryService: SummaryService; | |
39 | ||
40 | const fakeAuthStorageService = { | |
41 | isLoggedIn: () => { | |
42 | return true; | |
43 | }, | |
44 | getPermissions: () => { | |
45 | return new Permissions({ 'rbd-image': ['read', 'update', 'create', 'delete'] }); | |
46 | } | |
47 | }; | |
48 | ||
49 | configureTestBed({ | |
9f95a23c | 50 | declarations: [RbdSnapshotListComponent, RbdTabsComponent], |
11fdf7f2 | 51 | imports: [ |
11fdf7f2 | 52 | ApiModule, |
9f95a23c TL |
53 | ComponentsModule, |
54 | DataTableModule, | |
11fdf7f2 | 55 | HttpClientTestingModule, |
9f95a23c | 56 | PipesModule, |
11fdf7f2 | 57 | RouterTestingModule, |
9f95a23c TL |
58 | TabsModule.forRoot(), |
59 | ToastrModule.forRoot() | |
11fdf7f2 TL |
60 | ], |
61 | providers: [ | |
62 | { provide: AuthStorageService, useValue: fakeAuthStorageService }, | |
63 | TaskListService, | |
64 | i18nProviders | |
65 | ] | |
66 | }); | |
67 | ||
68 | beforeEach(() => { | |
69 | fixture = TestBed.createComponent(RbdSnapshotListComponent); | |
70 | component = fixture.componentInstance; | |
9f95a23c | 71 | component.ngOnChanges(); |
11fdf7f2 TL |
72 | summaryService = TestBed.get(SummaryService); |
73 | }); | |
74 | ||
75 | it('should create', () => { | |
76 | fixture.detectChanges(); | |
77 | expect(component).toBeTruthy(); | |
78 | }); | |
79 | ||
80 | describe('api delete request', () => { | |
9f95a23c | 81 | let called: boolean; |
11fdf7f2 TL |
82 | let rbdService: RbdService; |
83 | let notificationService: NotificationService; | |
84 | let authStorageService: AuthStorageService; | |
85 | ||
86 | beforeEach(() => { | |
87 | fixture.detectChanges(); | |
88 | const i18n = TestBed.get(I18n); | |
eafe8130 | 89 | const actionLabelsI18n = TestBed.get(ActionLabelsI18n); |
11fdf7f2 TL |
90 | called = false; |
91 | rbdService = new RbdService(null, null); | |
92 | notificationService = new NotificationService(null, null, null); | |
93 | authStorageService = new AuthStorageService(); | |
94 | authStorageService.set('user', '', { 'rbd-image': ['create', 'read', 'update', 'delete'] }); | |
95 | component = new RbdSnapshotListComponent( | |
96 | authStorageService, | |
97 | null, | |
98 | null, | |
99 | null, | |
100 | rbdService, | |
101 | null, | |
102 | notificationService, | |
103 | null, | |
104 | null, | |
eafe8130 TL |
105 | i18n, |
106 | actionLabelsI18n | |
11fdf7f2 TL |
107 | ); |
108 | spyOn(rbdService, 'deleteSnapshot').and.returnValue(observableThrowError({ status: 500 })); | |
109 | spyOn(notificationService, 'notifyTask').and.stub(); | |
110 | component.modalRef = new BsModalRef(); | |
111 | component.modalRef.content = { | |
112 | stopLoadingSpinner: () => (called = true) | |
113 | }; | |
114 | }); | |
115 | ||
801d1391 | 116 | it('should call stopLoadingSpinner if the request fails', fakeAsync(() => { |
11fdf7f2 TL |
117 | expect(called).toBe(false); |
118 | component._asyncTask('deleteSnapshot', 'rbd/snap/delete', 'someName'); | |
119 | tick(500); | |
120 | expect(called).toBe(true); | |
121 | })); | |
122 | }); | |
123 | ||
124 | describe('handling of executing tasks', () => { | |
125 | let snapshots: RbdSnapshotModel[]; | |
126 | ||
9f95a23c | 127 | const addSnapshot = (name: string) => { |
11fdf7f2 TL |
128 | const model = new RbdSnapshotModel(); |
129 | model.id = 1; | |
130 | model.name = name; | |
131 | snapshots.push(model); | |
132 | }; | |
133 | ||
134 | const addTask = (task_name: string, snapshot_name: string) => { | |
135 | const task = new ExecutingTask(); | |
136 | task.name = task_name; | |
137 | task.metadata = { | |
9f95a23c | 138 | image_spec: 'rbd/foo', |
11fdf7f2 TL |
139 | snapshot_name: snapshot_name |
140 | }; | |
141 | summaryService.addRunningTask(task); | |
142 | }; | |
143 | ||
9f95a23c | 144 | const refresh = (data: any) => { |
11fdf7f2 TL |
145 | summaryService['summaryDataSource'].next(data); |
146 | }; | |
147 | ||
148 | beforeEach(() => { | |
149 | fixture.detectChanges(); | |
150 | snapshots = []; | |
151 | addSnapshot('a'); | |
152 | addSnapshot('b'); | |
153 | addSnapshot('c'); | |
154 | component.snapshots = snapshots; | |
155 | component.poolName = 'rbd'; | |
156 | component.rbdName = 'foo'; | |
157 | refresh({ executing_tasks: [], finished_tasks: [] }); | |
158 | component.ngOnChanges(); | |
159 | fixture.detectChanges(); | |
160 | }); | |
161 | ||
162 | it('should gets all snapshots without tasks', () => { | |
163 | expect(component.snapshots.length).toBe(3); | |
164 | expect(component.snapshots.every((image) => !image.cdExecuting)).toBeTruthy(); | |
165 | }); | |
166 | ||
167 | it('should add a new image from a task', () => { | |
168 | addTask('rbd/snap/create', 'd'); | |
169 | expect(component.snapshots.length).toBe(4); | |
eafe8130 TL |
170 | expectItemTasks(component.snapshots[0], undefined); |
171 | expectItemTasks(component.snapshots[1], undefined); | |
172 | expectItemTasks(component.snapshots[2], undefined); | |
173 | expectItemTasks(component.snapshots[3], 'Creating'); | |
11fdf7f2 TL |
174 | }); |
175 | ||
176 | it('should show when an existing image is being modified', () => { | |
177 | addTask('rbd/snap/edit', 'a'); | |
178 | addTask('rbd/snap/delete', 'b'); | |
179 | addTask('rbd/snap/rollback', 'c'); | |
180 | expect(component.snapshots.length).toBe(3); | |
eafe8130 TL |
181 | expectItemTasks(component.snapshots[0], 'Updating'); |
182 | expectItemTasks(component.snapshots[1], 'Deleting'); | |
183 | expectItemTasks(component.snapshots[2], 'Rolling back'); | |
11fdf7f2 TL |
184 | }); |
185 | }); | |
186 | ||
187 | describe('snapshot modal dialog', () => { | |
188 | beforeEach(() => { | |
189 | component.poolName = 'pool01'; | |
190 | component.rbdName = 'image01'; | |
92f5a8d4 | 191 | spyOn(TestBed.get(BsModalService), 'show').and.callFake(() => { |
11fdf7f2 | 192 | const ref = new BsModalRef(); |
9f95a23c | 193 | ref.content = new RbdSnapshotFormModalComponent( |
92f5a8d4 TL |
194 | null, |
195 | null, | |
196 | null, | |
197 | null, | |
198 | TestBed.get(I18n), | |
199 | TestBed.get(ActionLabelsI18n) | |
200 | ); | |
11fdf7f2 TL |
201 | ref.content.onSubmit = new Subject(); |
202 | return ref; | |
203 | }); | |
204 | }); | |
205 | ||
206 | it('should display old snapshot name', () => { | |
207 | component.selection.selected = [{ name: 'oldname' }]; | |
11fdf7f2 TL |
208 | component.openEditSnapshotModal(); |
209 | expect(component.modalRef.content.snapName).toBe('oldname'); | |
210 | expect(component.modalRef.content.editing).toBeTruthy(); | |
211 | }); | |
212 | ||
213 | it('should display suggested snapshot name', () => { | |
214 | component.openCreateSnapshotModal(); | |
215 | expect(component.modalRef.content.snapName).toMatch( | |
9f95a23c | 216 | RegExp(`^${component.rbdName}_[\\d-]+T[\\d.:]+[\\+-][\\d:]+$`) |
11fdf7f2 TL |
217 | ); |
218 | }); | |
219 | }); | |
220 | ||
9f95a23c TL |
221 | it('should test all TableActions combinations', () => { |
222 | const permissionHelper: PermissionHelper = new PermissionHelper(component.permission); | |
223 | const tableActions: TableActionsComponent = permissionHelper.setPermissionsAndGetActions( | |
224 | component.tableActions | |
225 | ); | |
226 | ||
227 | expect(tableActions).toEqual({ | |
228 | 'create,update,delete': { | |
229 | actions: [ | |
230 | 'Create', | |
231 | 'Rename', | |
232 | 'Protect', | |
233 | 'Unprotect', | |
234 | 'Clone', | |
235 | 'Copy', | |
236 | 'Rollback', | |
237 | 'Delete' | |
238 | ], | |
239 | primary: { multiple: 'Create', executing: 'Rename', single: 'Rename', no: 'Create' } | |
240 | }, | |
241 | 'create,update': { | |
242 | actions: ['Create', 'Rename', 'Protect', 'Unprotect', 'Clone', 'Copy', 'Rollback'], | |
243 | primary: { multiple: 'Create', executing: 'Rename', single: 'Rename', no: 'Create' } | |
244 | }, | |
245 | 'create,delete': { | |
246 | actions: ['Create', 'Clone', 'Copy', 'Delete'], | |
247 | primary: { multiple: 'Create', executing: 'Clone', single: 'Clone', no: 'Create' } | |
248 | }, | |
249 | create: { | |
250 | actions: ['Create', 'Clone', 'Copy'], | |
251 | primary: { multiple: 'Create', executing: 'Clone', single: 'Clone', no: 'Create' } | |
252 | }, | |
253 | 'update,delete': { | |
254 | actions: ['Rename', 'Protect', 'Unprotect', 'Rollback', 'Delete'], | |
255 | primary: { multiple: 'Rename', executing: 'Rename', single: 'Rename', no: 'Rename' } | |
256 | }, | |
257 | update: { | |
258 | actions: ['Rename', 'Protect', 'Unprotect', 'Rollback'], | |
259 | primary: { multiple: 'Rename', executing: 'Rename', single: 'Rename', no: 'Rename' } | |
260 | }, | |
261 | delete: { | |
262 | actions: ['Delete'], | |
263 | primary: { multiple: 'Delete', executing: 'Delete', single: 'Delete', no: 'Delete' } | |
264 | }, | |
265 | 'no-permissions': { | |
266 | actions: [], | |
267 | primary: { multiple: '', executing: '', single: '', no: '' } | |
268 | } | |
11fdf7f2 TL |
269 | }); |
270 | }); | |
271 | }); |