]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts
import ceph 16.2.7
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / rgw / rgw-bucket-form / rgw-bucket-form.component.spec.ts
CommitLineData
11fdf7f2 1import { HttpClientTestingModule } from '@angular/common/http/testing';
a4b75251 2import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
b3b6e05e 3import { ReactiveFormsModule } from '@angular/forms';
11fdf7f2
TL
4import { Router } from '@angular/router';
5import { RouterTestingModule } from '@angular/router/testing';
6
f67539c2 7import _ from 'lodash';
494da23a 8import { ToastrModule } from 'ngx-toastr';
a4b75251 9import { of as observableOf } from 'rxjs';
11fdf7f2 10
f67539c2
TL
11import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service';
12import { RgwSiteService } from '~/app/shared/api/rgw-site.service';
13import { RgwUserService } from '~/app/shared/api/rgw-user.service';
14import { NotificationType } from '~/app/shared/enum/notification-type.enum';
15import { NotificationService } from '~/app/shared/services/notification.service';
16import { SharedModule } from '~/app/shared/shared.module';
17import { configureTestBed, FormHelper } from '~/testing/unit-test-helper';
9f95a23c
TL
18import { RgwBucketMfaDelete } from '../models/rgw-bucket-mfa-delete';
19import { RgwBucketVersioning } from '../models/rgw-bucket-versioning';
11fdf7f2
TL
20import { RgwBucketFormComponent } from './rgw-bucket-form.component';
21
22describe('RgwBucketFormComponent', () => {
23 let component: RgwBucketFormComponent;
24 let fixture: ComponentFixture<RgwBucketFormComponent>;
9f95a23c
TL
25 let rgwBucketService: RgwBucketService;
26 let getPlacementTargetsSpy: jasmine.Spy;
27 let rgwBucketServiceGetSpy: jasmine.Spy;
f67539c2 28 let enumerateSpy: jasmine.Spy;
9f95a23c 29 let formHelper: FormHelper;
11fdf7f2
TL
30
31 configureTestBed({
32 declarations: [RgwBucketFormComponent],
33 imports: [
34 HttpClientTestingModule,
35 ReactiveFormsModule,
36 RouterTestingModule,
37 SharedModule,
494da23a 38 ToastrModule.forRoot()
f67539c2 39 ]
11fdf7f2
TL
40 });
41
42 beforeEach(() => {
43 fixture = TestBed.createComponent(RgwBucketFormComponent);
44 component = fixture.componentInstance;
f67539c2 45 rgwBucketService = TestBed.inject(RgwBucketService);
9f95a23c 46 rgwBucketServiceGetSpy = spyOn(rgwBucketService, 'get');
f67539c2
TL
47 getPlacementTargetsSpy = spyOn(TestBed.inject(RgwSiteService), 'get');
48 enumerateSpy = spyOn(TestBed.inject(RgwUserService), 'enumerate');
9f95a23c 49 formHelper = new FormHelper(component.bucketForm);
11fdf7f2
TL
50 });
51
52 it('should create', () => {
53 expect(component).toBeTruthy();
54 });
55
56 describe('bucketNameValidator', () => {
b3b6e05e
TL
57 it('should validate empty name', fakeAsync(() => {
58 formHelper.expectErrorChange('bid', '', 'required', true);
59 }));
a4b75251 60 });
11fdf7f2 61
a4b75251 62 describe('zonegroup and placement targets', () => {
9f95a23c
TL
63 it('should get zonegroup and placement targets', () => {
64 const payload: Record<string, any> = {
65 zonegroup: 'default',
66 placement_targets: [
67 {
68 name: 'default-placement',
69 data_pool: 'default.rgw.buckets.data'
70 },
71 {
72 name: 'placement-target2',
73 data_pool: 'placement-target2.rgw.buckets.data'
74 }
75 ]
76 };
77 getPlacementTargetsSpy.and.returnValue(observableOf(payload));
f67539c2 78 enumerateSpy.and.returnValue(observableOf([]));
9f95a23c
TL
79 fixture.detectChanges();
80
81 expect(component.zonegroup).toBe(payload.zonegroup);
82 const placementTargets = [];
83 for (const placementTarget of payload['placement_targets']) {
84 placementTarget[
85 'description'
86 ] = `${placementTarget['name']} (pool: ${placementTarget['data_pool']})`;
87 placementTargets.push(placementTarget);
88 }
89 expect(component.placementTargets).toEqual(placementTargets);
90 });
11fdf7f2
TL
91 });
92
93 describe('submit form', () => {
94 let notificationService: NotificationService;
95
96 beforeEach(() => {
f67539c2
TL
97 spyOn(TestBed.inject(Router), 'navigate').and.stub();
98 notificationService = TestBed.inject(NotificationService);
11fdf7f2
TL
99 spyOn(notificationService, 'show');
100 });
101
9f95a23c
TL
102 it('should validate name', () => {
103 component.editing = false;
104 component.createForm();
105 const control = component.bucketForm.get('bid');
106 expect(_.isFunction(control.asyncValidator)).toBeTruthy();
107 });
108
109 it('should not validate name', () => {
110 component.editing = true;
111 component.createForm();
112 const control = component.bucketForm.get('bid');
113 expect(control.asyncValidator).toBeNull();
114 });
115
11fdf7f2 116 it('tests create success notification', () => {
9f95a23c 117 spyOn(rgwBucketService, 'create').and.returnValue(observableOf([]));
11fdf7f2
TL
118 component.editing = false;
119 component.bucketForm.markAsDirty();
120 component.submit();
121 expect(notificationService.show).toHaveBeenCalledWith(
122 NotificationType.success,
f67539c2 123 `Created Object Gateway bucket 'null'`
11fdf7f2
TL
124 );
125 });
126
127 it('tests update success notification', () => {
9f95a23c 128 spyOn(rgwBucketService, 'update').and.returnValue(observableOf([]));
11fdf7f2
TL
129 component.editing = true;
130 component.bucketForm.markAsDirty();
131 component.submit();
132 expect(notificationService.show).toHaveBeenCalledWith(
133 NotificationType.success,
f67539c2 134 `Updated Object Gateway bucket 'null'.`
9f95a23c
TL
135 );
136 });
137 });
138
139 describe('mfa credentials', () => {
140 const checkMfaCredentialsVisibility = (
141 fakeResponse: object,
142 versioningChecked: boolean,
143 mfaDeleteChecked: boolean,
144 expectedVisibility: boolean
145 ) => {
146 component['route'].params = observableOf({ bid: 'bid' });
147 component.editing = true;
148 rgwBucketServiceGetSpy.and.returnValue(observableOf(fakeResponse));
f67539c2 149 enumerateSpy.and.returnValue(observableOf([]));
9f95a23c 150 component.ngOnInit();
f67539c2
TL
151 component.bucketForm.patchValue({
152 versioning: versioningChecked,
153 'mfa-delete': mfaDeleteChecked
154 });
9f95a23c
TL
155 fixture.detectChanges();
156
157 const mfaTokenSerial = fixture.debugElement.nativeElement.querySelector('#mfa-token-serial');
158 const mfaTokenPin = fixture.debugElement.nativeElement.querySelector('#mfa-token-pin');
159 if (expectedVisibility) {
160 expect(mfaTokenSerial).toBeTruthy();
161 expect(mfaTokenPin).toBeTruthy();
162 } else {
163 expect(mfaTokenSerial).toBeFalsy();
164 expect(mfaTokenPin).toBeFalsy();
165 }
166 };
167
168 it('inputs should be visible when required', () => {
169 checkMfaCredentialsVisibility(
170 {
171 versioning: RgwBucketVersioning.SUSPENDED,
172 mfa_delete: RgwBucketMfaDelete.DISABLED
173 },
174 false,
175 false,
176 false
177 );
178 checkMfaCredentialsVisibility(
179 {
180 versioning: RgwBucketVersioning.SUSPENDED,
181 mfa_delete: RgwBucketMfaDelete.DISABLED
182 },
183 true,
184 false,
185 false
186 );
187 checkMfaCredentialsVisibility(
188 {
189 versioning: RgwBucketVersioning.ENABLED,
190 mfa_delete: RgwBucketMfaDelete.DISABLED
191 },
192 false,
193 false,
194 false
195 );
196 checkMfaCredentialsVisibility(
197 {
198 versioning: RgwBucketVersioning.ENABLED,
199 mfa_delete: RgwBucketMfaDelete.ENABLED
200 },
201 true,
202 true,
203 false
204 );
205 checkMfaCredentialsVisibility(
206 {
207 versioning: RgwBucketVersioning.SUSPENDED,
208 mfa_delete: RgwBucketMfaDelete.DISABLED
209 },
210 false,
211 true,
212 true
213 );
214 checkMfaCredentialsVisibility(
215 {
216 versioning: RgwBucketVersioning.SUSPENDED,
217 mfa_delete: RgwBucketMfaDelete.ENABLED
218 },
219 false,
220 false,
221 true
11fdf7f2 222 );
9f95a23c
TL
223 checkMfaCredentialsVisibility(
224 {
225 versioning: RgwBucketVersioning.SUSPENDED,
226 mfa_delete: RgwBucketMfaDelete.ENABLED
227 },
228 true,
229 true,
230 true
231 );
232 checkMfaCredentialsVisibility(
233 {
234 versioning: RgwBucketVersioning.ENABLED,
235 mfa_delete: RgwBucketMfaDelete.ENABLED
236 },
237 false,
238 true,
239 true
240 );
241 });
242 });
243
244 describe('object locking', () => {
9f95a23c
TL
245 const expectPatternLockError = (value: string) => {
246 formHelper.setValue('lock_enabled', true, true);
b3b6e05e
TL
247 formHelper.setValue('lock_retention_period_days', value);
248 formHelper.expectError('lock_retention_period_days', 'pattern');
9f95a23c
TL
249 };
250
b3b6e05e 251 const expectValidLockInputs = (enabled: boolean, mode: string, days: string) => {
9f95a23c
TL
252 formHelper.setValue('lock_enabled', enabled);
253 formHelper.setValue('lock_mode', mode);
254 formHelper.setValue('lock_retention_period_days', days);
b3b6e05e 255 ['lock_enabled', 'lock_mode', 'lock_retention_period_days'].forEach((name) => {
9f95a23c
TL
256 const control = component.bucketForm.get(name);
257 expect(control.valid).toBeTruthy();
258 expect(control.errors).toBeNull();
259 });
260 };
261
262 it('should check lock enabled checkbox [mode=create]', () => {
263 component.createForm();
264 const control = component.bucketForm.get('lock_enabled');
265 expect(control.disabled).toBeFalsy();
266 });
267
268 it('should check lock enabled checkbox [mode=edit]', () => {
269 component.editing = true;
270 component.createForm();
271 const control = component.bucketForm.get('lock_enabled');
272 expect(control.disabled).toBeTruthy();
273 });
274
b3b6e05e 275 it('should have the "lockDays" error', () => {
9f95a23c 276 formHelper.setValue('lock_enabled', true);
b3b6e05e
TL
277 const control = component.bucketForm.get('lock_retention_period_days');
278 control.updateValueAndValidity();
279 expect(control.value).toBe(0);
280 expect(control.invalid).toBeTruthy();
281 formHelper.expectError(control, 'lockDays');
9f95a23c
TL
282 });
283
284 it('should have the "pattern" error [1]', () => {
285 expectPatternLockError('-1');
286 });
287
288 it('should have the "pattern" error [2]', () => {
289 expectPatternLockError('1.2');
290 });
291
292 it('should have valid values [1]', () => {
b3b6e05e 293 expectValidLockInputs(true, 'Governance', '1');
9f95a23c
TL
294 });
295
296 it('should have valid values [2]', () => {
b3b6e05e 297 expectValidLockInputs(false, 'Compliance', '2');
11fdf7f2
TL
298 });
299 });
300});