@remoteoss/json-schema-form 0.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/index.cjs +1207 -0
- package/dist/index.js +1176 -0
- package/dist/standalone.js +12580 -0
- package/package.json +79 -0
- package/src/tests/createHeadlessForm.customValidations.test.jsx +799 -0
- package/src/tests/createHeadlessForm.test.js +3343 -0
- package/src/tests/helpers.custom.js +223 -0
- package/src/tests/helpers.js +1983 -0
- package/src/tests/internals.helpers.test.js +175 -0
- package/src/tests/utils.test.jsx +32 -0
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
import merge from 'lodash/fp/merge';
|
|
2
|
+
|
|
3
|
+
import { createHeadlessForm } from '../createHeadlessForm';
|
|
4
|
+
|
|
5
|
+
import { JSONSchemaBuilder, mockFieldset, mockRadioInput } from './helpers';
|
|
6
|
+
import { mockMoneyInput } from './helpers.custom';
|
|
7
|
+
|
|
8
|
+
function friendlyError({ formErrors }) {
|
|
9
|
+
// destruct the formErrors directly
|
|
10
|
+
return formErrors;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const mockNumberInput = {
|
|
14
|
+
title: 'Tabs',
|
|
15
|
+
description: 'How many open tabs do you have?',
|
|
16
|
+
'x-jsf-presentation': {
|
|
17
|
+
inputType: 'number',
|
|
18
|
+
},
|
|
19
|
+
minimum: 5,
|
|
20
|
+
maximum: 30,
|
|
21
|
+
type: 'number',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const mockNumberInputDeprecatedPresentation = {
|
|
25
|
+
title: 'Tabs',
|
|
26
|
+
description: 'How many open tabs do you have?',
|
|
27
|
+
presentation: {
|
|
28
|
+
inputType: 'number',
|
|
29
|
+
},
|
|
30
|
+
minimum: 5,
|
|
31
|
+
maximum: 30,
|
|
32
|
+
type: 'number',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const schemaBasic = ({ newProperties, allOf } = {}) =>
|
|
36
|
+
JSONSchemaBuilder()
|
|
37
|
+
.addInput(
|
|
38
|
+
merge(
|
|
39
|
+
{
|
|
40
|
+
parent_age: { ...mockNumberInput, maximum: 100 },
|
|
41
|
+
child_age: mockNumberInput,
|
|
42
|
+
},
|
|
43
|
+
newProperties
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
.setRequiredFields(['parent_age'])
|
|
47
|
+
.addAllOf(allOf || [])
|
|
48
|
+
.build();
|
|
49
|
+
|
|
50
|
+
const schemaWithConditional = ({ newProperties } = {}) =>
|
|
51
|
+
JSONSchemaBuilder()
|
|
52
|
+
.addInput(
|
|
53
|
+
merge(
|
|
54
|
+
{
|
|
55
|
+
is_employee: mockRadioInput,
|
|
56
|
+
salary: { ...mockMoneyInput, minimum: 0 },
|
|
57
|
+
bonus: { ...mockMoneyInput, minimum: 0 },
|
|
58
|
+
},
|
|
59
|
+
newProperties
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
.setRequiredFields(['is_employee', 'salary'])
|
|
63
|
+
.addAllOf([
|
|
64
|
+
{
|
|
65
|
+
if: {
|
|
66
|
+
properties: {
|
|
67
|
+
is_employee: {
|
|
68
|
+
const: 'yes',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
required: ['is_employee'],
|
|
72
|
+
},
|
|
73
|
+
then: {
|
|
74
|
+
properties: {
|
|
75
|
+
salary: {
|
|
76
|
+
minimum: 100000, // 1000.00€
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
required: ['bonus'],
|
|
80
|
+
},
|
|
81
|
+
else: {
|
|
82
|
+
properties: {
|
|
83
|
+
salary: {
|
|
84
|
+
minimum: 0, // 0.00€
|
|
85
|
+
},
|
|
86
|
+
bonus: false,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
])
|
|
91
|
+
.build();
|
|
92
|
+
|
|
93
|
+
function validateFieldParams(fieldParams, newFieldParams) {
|
|
94
|
+
expect(newFieldParams).toHaveProperty('name', fieldParams.name);
|
|
95
|
+
expect(newFieldParams).toHaveProperty('label', fieldParams.title);
|
|
96
|
+
expect(newFieldParams).toHaveProperty('description', fieldParams.description);
|
|
97
|
+
|
|
98
|
+
if (fieldParams.minimum) {
|
|
99
|
+
expect(newFieldParams).toHaveProperty('minimum', fieldParams.minimum);
|
|
100
|
+
}
|
|
101
|
+
if (fieldParams.maximum) {
|
|
102
|
+
expect(newFieldParams).toHaveProperty('maximum', fieldParams.maximum);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function validateNumberParams(fieldParams, newFieldParams) {
|
|
107
|
+
validateFieldParams(fieldParams, newFieldParams);
|
|
108
|
+
expect(newFieldParams).toHaveProperty('inputType', 'number');
|
|
109
|
+
expect(newFieldParams).toHaveProperty('jsonType', 'number');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function validateMoneyParams(fieldParams, newFieldParams) {
|
|
113
|
+
validateFieldParams(fieldParams, newFieldParams);
|
|
114
|
+
expect(newFieldParams).toHaveProperty('inputType', 'money');
|
|
115
|
+
expect(newFieldParams).toHaveProperty('jsonType', 'integer');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function createScenario({ schema, config }) {
|
|
119
|
+
const form = createHeadlessForm(schema, config);
|
|
120
|
+
const validateForm = (vals) => friendlyError(form.handleValidation(vals));
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
...form,
|
|
124
|
+
validateForm,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
beforeAll(() => {
|
|
129
|
+
jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
afterEach(() => {
|
|
133
|
+
// safety-check that every mocked validation is within the range
|
|
134
|
+
// eslint-disable-next-line no-console
|
|
135
|
+
expect(console.warn).not.toHaveBeenCalled();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
afterAll(() => {
|
|
139
|
+
// eslint-disable-next-line no-console
|
|
140
|
+
console.warn.mockRestore();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe('createHeadlessForm() - custom validations', () => {
|
|
144
|
+
describe('simple validation (eg maximum)', () => {
|
|
145
|
+
it('works as a number', () => {
|
|
146
|
+
const { fields, validateForm } = createScenario({
|
|
147
|
+
schema: schemaBasic(),
|
|
148
|
+
config: {
|
|
149
|
+
customProperties: {
|
|
150
|
+
child_age: {
|
|
151
|
+
maximum: 14,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
validateNumberParams({ ...mockNumberInput, name: 'child_age', maximum: 14 }, fields[1]);
|
|
158
|
+
|
|
159
|
+
expect(validateForm({})).toEqual({
|
|
160
|
+
parent_age: 'Required field',
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(validateForm({ parent_age: 30, child_age: 15 })).toEqual({
|
|
164
|
+
child_age: 'Must be smaller or equal to 14',
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
expect(validateForm({ parent_age: 30, child_age: 10 })).toBeUndefined();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('works as a function', () => {
|
|
171
|
+
// Friendly Scenario: child_age must be smaller than parent_age.
|
|
172
|
+
const { fields, validateForm } = createScenario({
|
|
173
|
+
schema: schemaBasic(),
|
|
174
|
+
config: {
|
|
175
|
+
customProperties: {
|
|
176
|
+
child_age: {
|
|
177
|
+
maximum: (values, { maximum }) => values.parent_age || maximum,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
validateNumberParams(
|
|
184
|
+
{ ...mockNumberInput, name: 'child_age', maximum: undefined },
|
|
185
|
+
fields[1]
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
expect(validateForm({})).toEqual({
|
|
189
|
+
parent_age: 'Required field',
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
expect(validateForm({ parent_age: 25, child_age: 26 })).toEqual({
|
|
193
|
+
child_age: 'Must be smaller or equal to 25',
|
|
194
|
+
});
|
|
195
|
+
expect(validateForm({ parent_age: 25, child_age: 20 })).toBeUndefined();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('works with minimum and maximum together', () => {
|
|
199
|
+
const { fields, validateForm } = createScenario({
|
|
200
|
+
schema: schemaBasic(),
|
|
201
|
+
config: {
|
|
202
|
+
customProperties: {
|
|
203
|
+
child_age: {
|
|
204
|
+
// dumb example: parents that are less than double the child age,
|
|
205
|
+
// the child must be between 20 and 29yo.
|
|
206
|
+
minimum: (values, { minimum }) =>
|
|
207
|
+
values.parent_age < values.child_age * 3 ? 20 : minimum,
|
|
208
|
+
maximum: (values, { maximum }) =>
|
|
209
|
+
values.parent_age < values.child_age * 3 ? 29 : maximum,
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
validateNumberParams(
|
|
216
|
+
{ ...mockNumberInput, name: 'child_age', minimum: 5, maximum: 30 },
|
|
217
|
+
fields[1]
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Test the default validations
|
|
221
|
+
expect(validateForm({ parent_age: 50, child_age: 1 })).toEqual({
|
|
222
|
+
child_age: 'Must be greater or equal to 5',
|
|
223
|
+
});
|
|
224
|
+
expect(validateForm({ parent_age: 100, child_age: 31 })).toEqual({
|
|
225
|
+
child_age: 'Must be smaller or equal to 30',
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Test the custom validations
|
|
229
|
+
expect(validateForm({ parent_age: 35, child_age: 19 })).toEqual({
|
|
230
|
+
child_age: 'Must be greater or equal to 20',
|
|
231
|
+
});
|
|
232
|
+
expect(validateForm({ parent_age: 40, child_age: 31 })).toEqual({
|
|
233
|
+
child_age: 'Must be smaller or equal to 29',
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('works with negative values', () => {
|
|
238
|
+
const { fields, validateForm } = createScenario({
|
|
239
|
+
schema: schemaBasic({
|
|
240
|
+
newProperties: {
|
|
241
|
+
parent_age: {
|
|
242
|
+
minimum: -20,
|
|
243
|
+
maximum: -1,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
}),
|
|
247
|
+
config: {
|
|
248
|
+
customProperties: {
|
|
249
|
+
parent_age: {
|
|
250
|
+
minimum: -15,
|
|
251
|
+
maximum: -5,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
validateNumberParams(
|
|
258
|
+
{ ...mockNumberInput, name: 'parent_age', minimum: -15, maximum: -5 },
|
|
259
|
+
fields[0]
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
expect(validateForm({})).toEqual({
|
|
263
|
+
parent_age: 'Required field',
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
expect(validateForm({ parent_age: -20 })).toEqual({
|
|
267
|
+
parent_age: 'Must be greater or equal to -15',
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
expect(validateForm({ parent_age: -4 })).toEqual({
|
|
271
|
+
parent_age: 'Must be smaller or equal to -5',
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
expect(validateForm({ parent_age: -10 })).toBeUndefined();
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('keeps original validation, given an empty validation', () => {
|
|
278
|
+
const { fields, validateForm } = createScenario({
|
|
279
|
+
schema: schemaBasic(),
|
|
280
|
+
config: {
|
|
281
|
+
customProperties: {
|
|
282
|
+
parent_age: {},
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
validateNumberParams({ ...mockNumberInput, name: 'parent_age', maximum: 100 }, fields[0]);
|
|
288
|
+
|
|
289
|
+
expect(validateForm({})).toEqual({
|
|
290
|
+
parent_age: 'Required field',
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
expect(validateForm({ parent_age: 0 })).toEqual({
|
|
294
|
+
parent_age: 'Must be greater or equal to 5',
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('applies validation, when original does not exist', () => {
|
|
299
|
+
const { fields, validateForm } = createScenario({
|
|
300
|
+
schema: schemaBasic({
|
|
301
|
+
newProperties: {
|
|
302
|
+
parent_age: { minimum: null, maximum: null },
|
|
303
|
+
},
|
|
304
|
+
}),
|
|
305
|
+
config: {
|
|
306
|
+
customProperties: {
|
|
307
|
+
parent_age: {
|
|
308
|
+
minimum: 1,
|
|
309
|
+
maximum: 20,
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
validateNumberParams(
|
|
316
|
+
{ ...mockNumberInput, minimum: 1, maximum: 20, name: 'parent_age' },
|
|
317
|
+
fields[0]
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
expect(validateForm({})).toEqual({
|
|
321
|
+
parent_age: 'Required field',
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
expect(validateForm({ parent_age: 0 })).toEqual({
|
|
325
|
+
parent_age: 'Must be greater or equal to 1',
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
expect(validateForm({ parent_age: 21 })).toEqual({
|
|
329
|
+
parent_age: 'Must be smaller or equal to 20',
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
describe('in fieldsets', () => {
|
|
335
|
+
it('applies custom validation in nested fields', () => {
|
|
336
|
+
const { fields, validateForm } = createScenario({
|
|
337
|
+
schema: JSONSchemaBuilder()
|
|
338
|
+
.addInput({
|
|
339
|
+
animal_age: mockNumberInput,
|
|
340
|
+
second_gen: {
|
|
341
|
+
...mockFieldset,
|
|
342
|
+
properties: {
|
|
343
|
+
cub_age: mockNumberInput,
|
|
344
|
+
third_gen: {
|
|
345
|
+
...mockFieldset,
|
|
346
|
+
properties: {
|
|
347
|
+
grandcub_age: mockNumberInput,
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
})
|
|
353
|
+
.build(),
|
|
354
|
+
config: {
|
|
355
|
+
customProperties: {
|
|
356
|
+
animal_age: {
|
|
357
|
+
minimum: 24,
|
|
358
|
+
maximum: 28,
|
|
359
|
+
},
|
|
360
|
+
second_gen: {
|
|
361
|
+
cub_age: {
|
|
362
|
+
minimum: 18,
|
|
363
|
+
maximum: 21,
|
|
364
|
+
},
|
|
365
|
+
third_gen: {
|
|
366
|
+
grandcub_age: {
|
|
367
|
+
minimum: 10,
|
|
368
|
+
maximum: 15,
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
const [animalField, secondGenField] = fields;
|
|
377
|
+
|
|
378
|
+
// Assert custom validations
|
|
379
|
+
validateNumberParams(
|
|
380
|
+
{
|
|
381
|
+
...mockNumberInput,
|
|
382
|
+
name: 'animal_age',
|
|
383
|
+
minimum: 24,
|
|
384
|
+
maximum: 28,
|
|
385
|
+
required: false,
|
|
386
|
+
},
|
|
387
|
+
animalField
|
|
388
|
+
);
|
|
389
|
+
validateNumberParams(
|
|
390
|
+
{
|
|
391
|
+
...mockNumberInput,
|
|
392
|
+
name: 'cub_age',
|
|
393
|
+
minimum: 18,
|
|
394
|
+
maximum: 21,
|
|
395
|
+
required: false,
|
|
396
|
+
},
|
|
397
|
+
secondGenField.fields[0]
|
|
398
|
+
);
|
|
399
|
+
validateNumberParams(
|
|
400
|
+
{
|
|
401
|
+
...mockNumberInput,
|
|
402
|
+
name: 'grandcub_age',
|
|
403
|
+
minimum: 10,
|
|
404
|
+
maximum: 15,
|
|
405
|
+
required: false,
|
|
406
|
+
},
|
|
407
|
+
secondGenField.fields[1].fields[0]
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
// Assert minimum values
|
|
411
|
+
expect(
|
|
412
|
+
validateForm({
|
|
413
|
+
animal_age: 1,
|
|
414
|
+
second_gen: {
|
|
415
|
+
cub_age: 1,
|
|
416
|
+
third_gen: {
|
|
417
|
+
grandcub_age: 1,
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
})
|
|
421
|
+
).toEqual({
|
|
422
|
+
animal_age: 'Must be greater or equal to 24',
|
|
423
|
+
second_gen: {
|
|
424
|
+
cub_age: 'Must be greater or equal to 18',
|
|
425
|
+
third_gen: {
|
|
426
|
+
grandcub_age: 'Must be greater or equal to 10',
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
// Assert maximum values
|
|
432
|
+
expect(
|
|
433
|
+
validateForm({
|
|
434
|
+
animal_age: 100,
|
|
435
|
+
second_gen: {
|
|
436
|
+
cub_age: 100,
|
|
437
|
+
third_gen: {
|
|
438
|
+
grandcub_age: 100,
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
})
|
|
442
|
+
).toEqual({
|
|
443
|
+
animal_age: 'Must be smaller or equal to 28',
|
|
444
|
+
second_gen: {
|
|
445
|
+
cub_age: 'Must be smaller or equal to 21',
|
|
446
|
+
third_gen: {
|
|
447
|
+
grandcub_age: 'Must be smaller or equal to 15',
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
describe('in conditional fields', () => {
|
|
455
|
+
const { fields, validateForm } = createScenario({
|
|
456
|
+
schema: schemaWithConditional(),
|
|
457
|
+
config: {
|
|
458
|
+
customProperties: {
|
|
459
|
+
bonus: {
|
|
460
|
+
maximum: (values, { maximum }) => ({
|
|
461
|
+
maximum: values.salary ? values.salary * 2 : maximum,
|
|
462
|
+
'x-jsf-errorMessage': {
|
|
463
|
+
maximum: `The bonus cannot be twice of the salary ${values.salary}.`,
|
|
464
|
+
},
|
|
465
|
+
}),
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it('validates conditional visible field', () => {
|
|
472
|
+
// bonus fieldResult
|
|
473
|
+
validateMoneyParams(
|
|
474
|
+
{
|
|
475
|
+
...mockMoneyInput,
|
|
476
|
+
name: 'bonus',
|
|
477
|
+
minimum: 0,
|
|
478
|
+
maximum: 500000,
|
|
479
|
+
required: false,
|
|
480
|
+
},
|
|
481
|
+
fields[2]
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
// Basic path — the custom validation is triggered
|
|
485
|
+
expect(
|
|
486
|
+
validateForm({
|
|
487
|
+
is_employee: 'yes',
|
|
488
|
+
salary: 150000,
|
|
489
|
+
bonus: 310000,
|
|
490
|
+
})
|
|
491
|
+
).toEqual({ bonus: 'The bonus cannot be twice of the salary 150000.' });
|
|
492
|
+
|
|
493
|
+
// The values are valid:
|
|
494
|
+
expect(
|
|
495
|
+
validateForm({
|
|
496
|
+
is_employee: 'yes',
|
|
497
|
+
salary: 150000,
|
|
498
|
+
bonus: 20000,
|
|
499
|
+
})
|
|
500
|
+
).toBeUndefined();
|
|
501
|
+
|
|
502
|
+
expect(validateForm({ is_employee: 'yes', salary: 150000 })).toEqual({
|
|
503
|
+
bonus: 'Required field',
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
it('ignores validation to conditional hidden field', () => {
|
|
508
|
+
expect(
|
|
509
|
+
validateForm({
|
|
510
|
+
is_employee: 'no',
|
|
511
|
+
salary: 150000,
|
|
512
|
+
bonus: 310000,
|
|
513
|
+
// NOTE/Unrelated-bug: Should it throw an error saying this
|
|
514
|
+
// "bonus" value is not expected? the native json schema spec throw an error...
|
|
515
|
+
})
|
|
516
|
+
).toBeUndefined();
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it('given an out-of-range validation, logs warning', () => {
|
|
520
|
+
expect(
|
|
521
|
+
validateForm({
|
|
522
|
+
is_employee: 'yes',
|
|
523
|
+
salary: 300000,
|
|
524
|
+
bonus: 500100,
|
|
525
|
+
})
|
|
526
|
+
).toEqual({
|
|
527
|
+
bonus: 'No more than €5000.00',
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// eslint-disable-next-line no-console
|
|
531
|
+
expect(console.warn).toHaveBeenNthCalledWith(
|
|
532
|
+
1,
|
|
533
|
+
'Custom validation for bonus is not allowed because maximum:600000 is less strict than the original range: 0 to 500000'
|
|
534
|
+
);
|
|
535
|
+
// eslint-disable-next-line no-console
|
|
536
|
+
console.warn.mockClear();
|
|
537
|
+
});
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// TODO: delete after migration to x-jsf-errorMessage is completed
|
|
541
|
+
describe('with errorMessage (deprecated)', () => {
|
|
542
|
+
/* NOTE: We have 3 type of errors:
|
|
543
|
+
- original error: (created by json-schema-form)
|
|
544
|
+
- errorMessage: (declared on JSON Schema)
|
|
545
|
+
- customValidation.errorMessage: (declared on config)
|
|
546
|
+
*/
|
|
547
|
+
it('overrides original error conditionally', () => {
|
|
548
|
+
const { fields, validateForm } = createScenario({
|
|
549
|
+
schema: schemaBasic(),
|
|
550
|
+
config: {
|
|
551
|
+
customProperties: {
|
|
552
|
+
child_age: {
|
|
553
|
+
maximum: (values, { maximum }) => ({
|
|
554
|
+
maximum: values.parent_age || maximum,
|
|
555
|
+
errorMessage: {
|
|
556
|
+
maximum: `The child cannot be older than the parent of ${values.parent_age} yo.`,
|
|
557
|
+
},
|
|
558
|
+
}),
|
|
559
|
+
},
|
|
560
|
+
},
|
|
561
|
+
},
|
|
562
|
+
});
|
|
563
|
+
validateNumberParams(
|
|
564
|
+
{
|
|
565
|
+
...mockNumberInput,
|
|
566
|
+
name: 'child_age',
|
|
567
|
+
minimum: 5,
|
|
568
|
+
maximum: 30,
|
|
569
|
+
},
|
|
570
|
+
fields[1]
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
expect(validateForm({ parent_age: 18, child_age: 4 })).toEqual({
|
|
574
|
+
child_age: 'Must be greater or equal to 5', // applies the original error message
|
|
575
|
+
});
|
|
576
|
+
expect(validateForm({ parent_age: 18, child_age: 19 })).toEqual({
|
|
577
|
+
child_age: 'The child cannot be older than the parent of 18 yo.', // applies the config.errorMessage
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it('overrides errorMessage conditionally', () => {
|
|
582
|
+
const { fields, validateForm } = createScenario({
|
|
583
|
+
schema: schemaBasic({
|
|
584
|
+
newProperties: {
|
|
585
|
+
parent_age: {
|
|
586
|
+
maximum: 100,
|
|
587
|
+
},
|
|
588
|
+
child_age: {
|
|
589
|
+
maximum: 40,
|
|
590
|
+
errorMessage: {
|
|
591
|
+
maximum: 'The child cannot be older than 40yo.',
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
}),
|
|
596
|
+
config: {
|
|
597
|
+
customProperties: {
|
|
598
|
+
child_age: {
|
|
599
|
+
minimum: (values, { maximum }) => {
|
|
600
|
+
const minimumAge = values.parent_age / 2;
|
|
601
|
+
if (
|
|
602
|
+
maximum > minimumAge && // prevent invalid out-of-range maximum
|
|
603
|
+
values.parent_age > values.child_age * 2 // parent is 2x as big as child age
|
|
604
|
+
) {
|
|
605
|
+
return {
|
|
606
|
+
minimum: minimumAge,
|
|
607
|
+
errorMessage: {
|
|
608
|
+
minimum: `The child cannot be younger than half of the parent. Must be at least ${minimumAge}yo.`,
|
|
609
|
+
},
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return null;
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
});
|
|
619
|
+
validateNumberParams(
|
|
620
|
+
{
|
|
621
|
+
...mockNumberInput,
|
|
622
|
+
name: 'child_age',
|
|
623
|
+
minimum: 5,
|
|
624
|
+
maximum: 40,
|
|
625
|
+
},
|
|
626
|
+
fields[1]
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
// applies the errorMessage by default
|
|
630
|
+
expect(validateForm({ parent_age: 50, child_age: 45 })).toEqual({
|
|
631
|
+
child_age: 'The child cannot be older than 40yo.',
|
|
632
|
+
});
|
|
633
|
+
// applies the config.errorMessage if it's triggered
|
|
634
|
+
expect(validateForm({ parent_age: 50, child_age: 10 })).toEqual({
|
|
635
|
+
child_age: `The child cannot be younger than half of the parent. Must be at least 25yo.`,
|
|
636
|
+
});
|
|
637
|
+
});
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
describe('with x-jsf-errorMessage', () => {
|
|
641
|
+
/* NOTE: We have 3 type of errors:
|
|
642
|
+
- original error: (created by json-schema-form)
|
|
643
|
+
- x-jsf-errorMessage: (declared on JSON Schema)
|
|
644
|
+
- customValidation['x-jsf-errorMessage']: (declared on options)
|
|
645
|
+
*/
|
|
646
|
+
it('overrides original error conditionally', () => {
|
|
647
|
+
const { fields, validateForm } = createScenario({
|
|
648
|
+
schema: schemaBasic(),
|
|
649
|
+
config: {
|
|
650
|
+
customProperties: {
|
|
651
|
+
child_age: {
|
|
652
|
+
maximum: (values, { maximum }) => ({
|
|
653
|
+
maximum: values.parent_age || maximum,
|
|
654
|
+
'x-jsf-errorMessage': {
|
|
655
|
+
maximum: `The child cannot be older than the parent of ${values.parent_age} yo.`,
|
|
656
|
+
},
|
|
657
|
+
}),
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
});
|
|
662
|
+
validateNumberParams(
|
|
663
|
+
{
|
|
664
|
+
...mockNumberInput,
|
|
665
|
+
name: 'child_age',
|
|
666
|
+
minimum: 5,
|
|
667
|
+
maximum: 30,
|
|
668
|
+
},
|
|
669
|
+
fields[1]
|
|
670
|
+
);
|
|
671
|
+
|
|
672
|
+
expect(validateForm({ parent_age: 18, child_age: 4 })).toEqual({
|
|
673
|
+
child_age: 'Must be greater or equal to 5', // applies the original error message
|
|
674
|
+
});
|
|
675
|
+
expect(validateForm({ parent_age: 18, child_age: 19 })).toEqual({
|
|
676
|
+
child_age: 'The child cannot be older than the parent of 18 yo.', // applies the config.errorMessage
|
|
677
|
+
});
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it('overrides errorMessage conditionally', () => {
|
|
681
|
+
const { fields, validateForm } = createScenario({
|
|
682
|
+
schema: schemaBasic({
|
|
683
|
+
newProperties: {
|
|
684
|
+
parent_age: {
|
|
685
|
+
maximum: 100,
|
|
686
|
+
},
|
|
687
|
+
child_age: {
|
|
688
|
+
maximum: 40,
|
|
689
|
+
'x-jsf-errorMessage': {
|
|
690
|
+
maximum: 'The child cannot be older than 40yo.',
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
},
|
|
694
|
+
}),
|
|
695
|
+
config: {
|
|
696
|
+
customProperties: {
|
|
697
|
+
child_age: {
|
|
698
|
+
minimum: (values, { maximum }) => {
|
|
699
|
+
const minimumAge = values.parent_age / 2;
|
|
700
|
+
if (
|
|
701
|
+
maximum > minimumAge && // prevent invalid out-of-range maximum
|
|
702
|
+
values.parent_age > values.child_age * 2 // parent is 2x as big as child age
|
|
703
|
+
) {
|
|
704
|
+
return {
|
|
705
|
+
minimum: minimumAge,
|
|
706
|
+
'x-jsf-errorMessage': {
|
|
707
|
+
minimum: `The child cannot be younger than half of the parent. Must be at least ${minimumAge}yo.`,
|
|
708
|
+
},
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
return null;
|
|
713
|
+
},
|
|
714
|
+
},
|
|
715
|
+
},
|
|
716
|
+
},
|
|
717
|
+
});
|
|
718
|
+
validateNumberParams(
|
|
719
|
+
{
|
|
720
|
+
...mockNumberInput,
|
|
721
|
+
name: 'child_age',
|
|
722
|
+
minimum: 5,
|
|
723
|
+
maximum: 40,
|
|
724
|
+
},
|
|
725
|
+
fields[1]
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
// applies the errorMessage by default
|
|
729
|
+
expect(validateForm({ parent_age: 50, child_age: 45 })).toEqual({
|
|
730
|
+
child_age: 'The child cannot be older than 40yo.',
|
|
731
|
+
});
|
|
732
|
+
// applies the config.errorMessage if it's triggered
|
|
733
|
+
expect(validateForm({ parent_age: 50, child_age: 10 })).toEqual({
|
|
734
|
+
child_age: `The child cannot be younger than half of the parent. Must be at least 25yo.`,
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
describe('invalid validations', () => {
|
|
740
|
+
it('outside the schema range logs warning', () => {
|
|
741
|
+
const { fields, validateForm } = createScenario({
|
|
742
|
+
schema: schemaBasic(),
|
|
743
|
+
config: {
|
|
744
|
+
customProperties: {
|
|
745
|
+
parent_age: {
|
|
746
|
+
minimum: 0,
|
|
747
|
+
},
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
validateNumberParams(
|
|
753
|
+
{ ...mockNumberInput, minimum: 5, maximum: 100, name: 'parent_age' },
|
|
754
|
+
fields[0]
|
|
755
|
+
);
|
|
756
|
+
|
|
757
|
+
// Keeps the default validation
|
|
758
|
+
expect(validateForm({ parent_age: 0 })).toEqual({
|
|
759
|
+
parent_age: 'Must be greater or equal to 5',
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
// eslint-disable-next-line no-console
|
|
763
|
+
expect(console.warn).toHaveBeenNthCalledWith(
|
|
764
|
+
1,
|
|
765
|
+
'Custom validation for parent_age is not allowed because minimum:0 is less strict than the original range: 5 to 100'
|
|
766
|
+
);
|
|
767
|
+
// eslint-disable-next-line no-console
|
|
768
|
+
console.warn.mockClear();
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it('null or undefined ignores validation', () => {
|
|
772
|
+
const { fields, validateForm } = createScenario({
|
|
773
|
+
schema: schemaBasic(),
|
|
774
|
+
config: {
|
|
775
|
+
customProperties: {
|
|
776
|
+
parent_age: {
|
|
777
|
+
minimum: undefined,
|
|
778
|
+
maximum: null,
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
},
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
// The original validation is kept
|
|
785
|
+
validateNumberParams(
|
|
786
|
+
{ ...mockNumberInput, minimum: 5, maximum: 100, name: 'parent_age' },
|
|
787
|
+
fields[0]
|
|
788
|
+
);
|
|
789
|
+
|
|
790
|
+
expect(validateForm({ parent_age: 0 })).toEqual({
|
|
791
|
+
parent_age: 'Must be greater or equal to 5',
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
expect(validateForm({ parent_age: 200 })).toEqual({
|
|
795
|
+
parent_age: 'Must be smaller or equal to 100',
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
});
|