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