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