]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
ef55b4808aef739c165f860be09d57ce5e9fe1a4
[ceph-ci.git] /
1 import { EventEmitter } from '@angular/core';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { ReactiveFormsModule } from '@angular/forms';
4 import { By } from '@angular/platform-browser';
5
6 import { DirectivesModule } from '~/app/shared/directives/directives.module';
7 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
8 import { RbdConfigurationSourceField } from '~/app/shared/models/configuration';
9 import { DimlessBinaryPerSecondPipe } from '~/app/shared/pipes/dimless-binary-per-second.pipe';
10 import { FormatterService } from '~/app/shared/services/formatter.service';
11 import { RbdConfigurationService } from '~/app/shared/services/rbd-configuration.service';
12 import { SharedModule } from '~/app/shared/shared.module';
13 import { configureTestBed, FormHelper } from '~/testing/unit-test-helper';
14 import { RbdConfigurationFormComponent } from './rbd-configuration-form.component';
15
16 describe('RbdConfigurationFormComponent', () => {
17   let component: RbdConfigurationFormComponent;
18   let fixture: ComponentFixture<RbdConfigurationFormComponent>;
19   let sections: any[];
20   let fh: FormHelper;
21
22   configureTestBed({
23     imports: [ReactiveFormsModule, DirectivesModule, SharedModule],
24     declarations: [RbdConfigurationFormComponent],
25     providers: [RbdConfigurationService, FormatterService, DimlessBinaryPerSecondPipe]
26   });
27
28   beforeEach(() => {
29     fixture = TestBed.createComponent(RbdConfigurationFormComponent);
30     component = fixture.componentInstance;
31     component.form = new CdFormGroup({}, null);
32     fh = new FormHelper(component.form);
33     fixture.detectChanges();
34     sections = TestBed.inject(RbdConfigurationService).sections;
35   });
36
37   it('should create', () => {
38     expect(component).toBeTruthy();
39   });
40
41   it('should create all form fields mentioned in RbdConfiguration::OPTIONS', () => {
42     /* Test form creation on a TypeScript level */
43     const actual = Object.keys((component.form.get('configuration') as CdFormGroup).controls);
44     const expected = sections
45       .map((section) => section.options)
46       .reduce((a, b) => a.concat(b))
47       .map((option: Record<string, any>) => option.name);
48     expect(actual).toEqual(expected);
49
50     /* Test form creation on a template level */
51     const controlDebugElements = fixture.debugElement.queryAll(By.css('input.form-control'));
52     expect(controlDebugElements.length).toBe(expected.length);
53     controlDebugElements.forEach((element) => expect(element.nativeElement).toBeTruthy());
54   });
55
56   it('should only contain values of changed controls if submitted', () => {
57     let values = {};
58     component.changes.subscribe((getDirtyValues: Function) => {
59       values = getDirtyValues();
60     });
61     fh.setValue('configuration.rbd_qos_bps_limit', 0, true);
62     fixture.detectChanges();
63
64     expect(values).toEqual({ rbd_qos_bps_limit: 0 });
65   });
66
67   describe('test loading of initial data for editing', () => {
68     beforeEach(() => {
69       component.initializeData = new EventEmitter<any>();
70       fixture.detectChanges();
71       component.ngOnInit();
72     });
73
74     it('should return dirty values without any units', () => {
75       let dirtyValues = {};
76       component.changes.subscribe((getDirtyValues: Function) => {
77         dirtyValues = getDirtyValues();
78       });
79
80       fh.setValue('configuration.rbd_qos_bps_limit', 55, true);
81       fh.setValue('configuration.rbd_qos_iops_limit', 22, true);
82
83       expect(dirtyValues['rbd_qos_bps_limit']).toBe(55);
84       expect(dirtyValues['rbd_qos_iops_limit']).toBe(22);
85     });
86
87     it('should load initial data into forms', () => {
88       component.initializeData.emit({
89         initialData: [
90           {
91             name: 'rbd_qos_bps_limit',
92             value: 55,
93             source: 1
94           }
95         ],
96         sourceType: RbdConfigurationSourceField.pool
97       });
98
99       expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('55 B/s');
100     });
101
102     it('should not load initial data if the source is not the pool itself', () => {
103       component.initializeData.emit({
104         initialData: [
105           {
106             name: 'rbd_qos_bps_limit',
107             value: 55,
108             source: RbdConfigurationSourceField.image
109           },
110           {
111             name: 'rbd_qos_iops_limit',
112             value: 22,
113             source: RbdConfigurationSourceField.global
114           }
115         ],
116         sourceType: RbdConfigurationSourceField.pool
117       });
118
119       expect(component.form.getValue('configuration.rbd_qos_iops_limit')).toEqual('0 IOPS');
120       expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('0 B/s');
121     });
122
123     it('should not load initial data if the source is not the image itself', () => {
124       component.initializeData.emit({
125         initialData: [
126           {
127             name: 'rbd_qos_bps_limit',
128             value: 55,
129             source: RbdConfigurationSourceField.pool
130           },
131           {
132             name: 'rbd_qos_iops_limit',
133             value: 22,
134             source: RbdConfigurationSourceField.global
135           }
136         ],
137         sourceType: RbdConfigurationSourceField.image
138       });
139
140       expect(component.form.getValue('configuration.rbd_qos_iops_limit')).toEqual('0 IOPS');
141       expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('0 B/s');
142     });
143
144     it('should always have formatted results', () => {
145       component.initializeData.emit({
146         initialData: [
147           {
148             name: 'rbd_qos_bps_limit',
149             value: 55,
150             source: RbdConfigurationSourceField.image
151           },
152           {
153             name: 'rbd_qos_iops_limit',
154             value: 22,
155             source: RbdConfigurationSourceField.image
156           },
157           {
158             name: 'rbd_qos_read_bps_limit',
159             value: null, // incorrect type
160             source: RbdConfigurationSourceField.image
161           },
162           {
163             name: 'rbd_qos_read_bps_limit',
164             value: undefined, // incorrect type
165             source: RbdConfigurationSourceField.image
166           }
167         ],
168         sourceType: RbdConfigurationSourceField.image
169       });
170
171       expect(component.form.getValue('configuration.rbd_qos_iops_limit')).toEqual('22 IOPS');
172       expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('55 B/s');
173       expect(component.form.getValue('configuration.rbd_qos_read_bps_limit')).toEqual('0 B/s');
174       expect(component.form.getValue('configuration.rbd_qos_read_bps_limit')).toEqual('0 B/s');
175     });
176   });
177
178   it('should reset the corresponding form field correctly', () => {
179     const fieldName = 'rbd_qos_bps_limit';
180     const getValue = () => component.form.get(`configuration.${fieldName}`).value;
181
182     // Initialization
183     fh.setValue(`configuration.${fieldName}`, 418, true);
184     expect(getValue()).toBe(418);
185
186     // Reset
187     component.reset(fieldName);
188     expect(getValue()).toBe(null);
189
190     // Restore
191     component.reset(fieldName);
192     expect(getValue()).toBe(418);
193
194     // Reset
195     component.reset(fieldName);
196     expect(getValue()).toBe(null);
197
198     // Restore
199     component.reset(fieldName);
200     expect(getValue()).toBe(418);
201   });
202
203   describe('should verify that getDirtyValues() returns correctly', () => {
204     let data: any;
205
206     beforeEach(() => {
207       component.initializeData = new EventEmitter<any>();
208       fixture.detectChanges();
209       component.ngOnInit();
210       data = {
211         initialData: [
212           {
213             name: 'rbd_qos_bps_limit',
214             value: 0,
215             source: RbdConfigurationSourceField.image
216           },
217           {
218             name: 'rbd_qos_iops_limit',
219             value: 0,
220             source: RbdConfigurationSourceField.image
221           },
222           {
223             name: 'rbd_qos_read_bps_limit',
224             value: 0,
225             source: RbdConfigurationSourceField.image
226           },
227           {
228             name: 'rbd_qos_read_iops_limit',
229             value: 0,
230             source: RbdConfigurationSourceField.image
231           },
232           {
233             name: 'rbd_qos_read_iops_burst',
234             value: 0,
235             source: RbdConfigurationSourceField.image
236           },
237           {
238             name: 'rbd_qos_write_bps_burst',
239             value: undefined,
240             source: RbdConfigurationSourceField.global
241           },
242           {
243             name: 'rbd_qos_write_iops_burst',
244             value: null,
245             source: RbdConfigurationSourceField.global
246           }
247         ],
248         sourceType: RbdConfigurationSourceField.image
249       };
250       component.initializeData.emit(data);
251     });
252
253     it('should return an empty object', () => {
254       expect(component.getDirtyValues()).toEqual({});
255       expect(component.getDirtyValues(true, RbdConfigurationSourceField.image)).toEqual({});
256     });
257
258     it('should return dirty values', () => {
259       component.form.get('configuration.rbd_qos_write_bps_burst').markAsDirty();
260       expect(component.getDirtyValues()).toEqual({ rbd_qos_write_bps_burst: 0 });
261
262       component.form.get('configuration.rbd_qos_write_iops_burst').markAsDirty();
263       expect(component.getDirtyValues()).toEqual({
264         rbd_qos_write_iops_burst: 0,
265         rbd_qos_write_bps_burst: 0
266       });
267     });
268
269     it('should also return all local values if they do not contain their initial values', () => {
270       // Change value for all options
271       data.initialData = data.initialData.map((o: Record<string, any>) => {
272         o.value = 22;
273         return o;
274       });
275
276       // Mark some dirty
277       ['rbd_qos_read_iops_limit', 'rbd_qos_write_bps_burst'].forEach((option) => {
278         component.form.get(`configuration.${option}`).markAsDirty();
279       });
280
281       expect(component.getDirtyValues(true, RbdConfigurationSourceField.image)).toEqual({
282         rbd_qos_read_iops_limit: 0,
283         rbd_qos_write_bps_burst: 0
284       });
285     });
286
287     it('should throw an error if used incorrectly', () => {
288       expect(() => component.getDirtyValues(true)).toThrowError(
289         /^ProgrammingError: If local values shall be included/
290       );
291     });
292   });
293 });