]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.spec.ts
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / block / rbd-configuration-form / rbd-configuration-form.component.spec.ts
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) => 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) => {
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;
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) => {
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 });