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