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