@remoteoss/json-schema-form 0.4.4-dev.20230830125207 → 0.4.6-dev.20230911130751
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 +12 -0
- package/dist/index.cjs +208 -33
- package/dist/index.js +208 -33
- package/dist/standalone.js +586 -33
- package/package.json +2 -1
- package/src/tests/const.test.js +98 -0
- package/src/tests/helpers.custom.js +0 -1
- package/src/tests/jsonLogic.fixtures.js +162 -0
- package/src/tests/jsonLogic.test.js +230 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remoteoss/json-schema-form",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6-dev.20230911130751",
|
|
4
4
|
"description": "Headless UI form powered by JSON Schemas",
|
|
5
5
|
"author": "Remote.com <engineering@remote.com> (https://remote.com/)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
]
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
+
"json-logic-js": "^2.0.2",
|
|
50
51
|
"lodash": "^4.17.21",
|
|
51
52
|
"randexp": "^0.5.3",
|
|
52
53
|
"yup": "^0.30.0"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createHeadlessForm } from '../createHeadlessForm';
|
|
2
|
+
|
|
3
|
+
describe('validations: const', () => {
|
|
4
|
+
it('Should work for number', () => {
|
|
5
|
+
const { handleValidation } = createHeadlessForm(
|
|
6
|
+
{
|
|
7
|
+
properties: {
|
|
8
|
+
ten_only: { type: 'number', const: 10 },
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
{ strictInputType: false }
|
|
12
|
+
);
|
|
13
|
+
expect(handleValidation({}).formErrors).toEqual(undefined);
|
|
14
|
+
expect(handleValidation({ ten_only: 1 }).formErrors).toEqual({
|
|
15
|
+
ten_only: 'The only accepted value is 10.',
|
|
16
|
+
});
|
|
17
|
+
expect(handleValidation({ ten_only: 10 }).formErrors).toBeUndefined();
|
|
18
|
+
// null is also considered valid until we fix @BUG RMT-518
|
|
19
|
+
// Expectation: To fail with error "The only accepted value is 10."
|
|
20
|
+
expect(handleValidation({ ten_only: null }).formErrors).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('Should work for text', () => {
|
|
24
|
+
const { handleValidation } = createHeadlessForm(
|
|
25
|
+
{
|
|
26
|
+
properties: {
|
|
27
|
+
hello_only: { type: 'string', const: 'hello' },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{ strictInputType: false }
|
|
31
|
+
);
|
|
32
|
+
expect(handleValidation({}).formErrors).toEqual(undefined);
|
|
33
|
+
expect(handleValidation({ hello_only: 'what' }).formErrors).toEqual({
|
|
34
|
+
hello_only: 'The only accepted value is hello.',
|
|
35
|
+
});
|
|
36
|
+
expect(handleValidation({ hello_only: 'hello' }).formErrors).toEqual(undefined);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('Should work for a conditionally applied const', () => {
|
|
40
|
+
const { handleValidation } = createHeadlessForm(
|
|
41
|
+
{
|
|
42
|
+
properties: {
|
|
43
|
+
answer: { type: 'string', oneOf: [{ const: 'yes' }, { const: 'no' }] },
|
|
44
|
+
amount: {
|
|
45
|
+
description: 'If you select yes, this needs to be exactly 10.',
|
|
46
|
+
type: 'number',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
allOf: [
|
|
50
|
+
{
|
|
51
|
+
if: { properties: { answer: { const: 'yes' } }, required: ['answer'] },
|
|
52
|
+
then: { properties: { amount: { const: 10 } }, required: ['amount'] },
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{ strictInputType: false }
|
|
57
|
+
);
|
|
58
|
+
expect(handleValidation({}).formErrors).toEqual(undefined);
|
|
59
|
+
expect(handleValidation({ answer: 'no' }).formErrors).toEqual(undefined);
|
|
60
|
+
expect(handleValidation({ answer: 'yes' }).formErrors).toEqual({ amount: 'Required field' });
|
|
61
|
+
expect(handleValidation({ answer: 'yes', amount: 1 }).formErrors).toEqual({
|
|
62
|
+
amount: 'The only accepted value is 10.',
|
|
63
|
+
});
|
|
64
|
+
expect(handleValidation({ answer: 'yes', amount: 10 }).formErrors).toEqual(undefined);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('Should show the custom error message', () => {
|
|
68
|
+
const { handleValidation } = createHeadlessForm(
|
|
69
|
+
{
|
|
70
|
+
properties: {
|
|
71
|
+
string: {
|
|
72
|
+
type: 'string',
|
|
73
|
+
const: 'hello',
|
|
74
|
+
'x-jsf-errorMessage': { const: 'You must say hello!!!' },
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{ strictInputType: false }
|
|
79
|
+
);
|
|
80
|
+
expect(handleValidation({}).formErrors).toEqual(undefined);
|
|
81
|
+
expect(handleValidation({ string: 'hi' }).formErrors).toEqual({
|
|
82
|
+
string: 'You must say hello!!!',
|
|
83
|
+
});
|
|
84
|
+
expect(handleValidation({ string: 'hello' }).formErrors).toEqual(undefined);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('Should have value attribute for when const & default is present', () => {
|
|
88
|
+
const { fields } = createHeadlessForm(
|
|
89
|
+
{
|
|
90
|
+
properties: {
|
|
91
|
+
ten_only: { type: 'number', const: 10, default: 10 },
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{ strictInputType: false }
|
|
95
|
+
);
|
|
96
|
+
expect(fields[0]).toMatchObject({ value: 10, const: 10, default: 10 });
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
export function createSchemaWithRulesOnFieldA(rules) {
|
|
2
|
+
return {
|
|
3
|
+
properties: {
|
|
4
|
+
field_a: {
|
|
5
|
+
type: 'number',
|
|
6
|
+
'x-jsf-logic-validations': Object.keys(rules),
|
|
7
|
+
},
|
|
8
|
+
field_b: {
|
|
9
|
+
type: 'number',
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
required: ['field_a', 'field_b'],
|
|
13
|
+
'x-jsf-logic': { validations: rules },
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createSchemaWithThreePropertiesWithRuleOnFieldA(rules) {
|
|
18
|
+
return {
|
|
19
|
+
properties: {
|
|
20
|
+
field_a: {
|
|
21
|
+
type: 'number',
|
|
22
|
+
'x-jsf-logic-validations': Object.keys(rules),
|
|
23
|
+
},
|
|
24
|
+
field_b: {
|
|
25
|
+
type: 'number',
|
|
26
|
+
},
|
|
27
|
+
field_c: {
|
|
28
|
+
type: 'number',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
'x-jsf-logic': { validations: rules },
|
|
32
|
+
required: ['field_a', 'field_b', 'field_c'],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const schemaWithNonRequiredField = {
|
|
37
|
+
properties: {
|
|
38
|
+
field_a: {
|
|
39
|
+
type: 'number',
|
|
40
|
+
},
|
|
41
|
+
field_b: {
|
|
42
|
+
type: 'number',
|
|
43
|
+
'x-jsf-logic-validations': ['a_greater_than_field_b'],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
'x-jsf-logic': {
|
|
47
|
+
validations: {
|
|
48
|
+
a_greater_than_field_b: {
|
|
49
|
+
errorMessage: 'Must be greater than field_a',
|
|
50
|
+
rule: {
|
|
51
|
+
'>': [{ var: 'field_a' }, { var: 'field_b' }],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: [],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const schemaWithNativeAndJSONLogicChecks = {
|
|
60
|
+
properties: {
|
|
61
|
+
field_a: {
|
|
62
|
+
type: 'number',
|
|
63
|
+
minimum: 100,
|
|
64
|
+
'x-jsf-logic-validations': ['a_multiple_of_ten'],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
'x-jsf-logic': {
|
|
68
|
+
validations: {
|
|
69
|
+
a_multiple_of_ten: {
|
|
70
|
+
errorMessage: 'Must be a multiple of 10',
|
|
71
|
+
rule: {
|
|
72
|
+
'===': [{ '%': [{ var: 'field_a' }, 10] }, 0],
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
required: ['field_a'],
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const multiRuleSchema = {
|
|
81
|
+
properties: {
|
|
82
|
+
field_a: {
|
|
83
|
+
type: 'number',
|
|
84
|
+
'x-jsf-logic-validations': ['a_bigger_than_b', 'is_even_number'],
|
|
85
|
+
},
|
|
86
|
+
field_b: {
|
|
87
|
+
type: 'number',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
required: ['field_a', 'field_b'],
|
|
91
|
+
'x-jsf-logic': {
|
|
92
|
+
validations: {
|
|
93
|
+
a_bigger_than_b: {
|
|
94
|
+
errorMessage: 'A must be bigger than B',
|
|
95
|
+
rule: {
|
|
96
|
+
'>': [{ var: 'field_a' }, { var: 'field_b' }],
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
is_even_number: {
|
|
100
|
+
errorMessage: 'A must be even',
|
|
101
|
+
rule: {
|
|
102
|
+
'===': [{ '%': [{ var: 'field_a' }, 2] }, 0],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const schemaWithTwoRules = {
|
|
110
|
+
properties: {
|
|
111
|
+
field_a: {
|
|
112
|
+
type: 'number',
|
|
113
|
+
'x-jsf-logic-validations': ['a_bigger_than_b'],
|
|
114
|
+
},
|
|
115
|
+
field_b: {
|
|
116
|
+
type: 'number',
|
|
117
|
+
'x-jsf-logic-validations': ['is_even_number'],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
required: ['field_a', 'field_b'],
|
|
121
|
+
'x-jsf-logic': {
|
|
122
|
+
validations: {
|
|
123
|
+
a_bigger_than_b: {
|
|
124
|
+
errorMessage: 'A must be bigger than B',
|
|
125
|
+
rule: {
|
|
126
|
+
'>': [{ var: 'field_a' }, { var: 'field_b' }],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
is_even_number: {
|
|
130
|
+
errorMessage: 'B must be even',
|
|
131
|
+
rule: {
|
|
132
|
+
'===': [{ '%': [{ var: 'field_b' }, 2] }, 0],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const schemaWithComputedAttributes = {
|
|
140
|
+
properties: {
|
|
141
|
+
field_a: {
|
|
142
|
+
type: 'number',
|
|
143
|
+
},
|
|
144
|
+
field_b: {
|
|
145
|
+
type: 'number',
|
|
146
|
+
'x-jsf-logic-computedAttrs': {
|
|
147
|
+
const: 'a_times_two',
|
|
148
|
+
default: 'a_times_two',
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
required: ['field_a', 'field_b'],
|
|
153
|
+
'x-jsf-logic': {
|
|
154
|
+
computedValues: {
|
|
155
|
+
a_times_two: {
|
|
156
|
+
rule: {
|
|
157
|
+
'*': [{ var: 'field_a' }, 2],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { createHeadlessForm } from '../createHeadlessForm';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createSchemaWithRulesOnFieldA,
|
|
5
|
+
createSchemaWithThreePropertiesWithRuleOnFieldA,
|
|
6
|
+
multiRuleSchema,
|
|
7
|
+
schemaWithComputedAttributes,
|
|
8
|
+
schemaWithNativeAndJSONLogicChecks,
|
|
9
|
+
schemaWithNonRequiredField,
|
|
10
|
+
schemaWithTwoRules,
|
|
11
|
+
} from './jsonLogic.fixtures';
|
|
12
|
+
|
|
13
|
+
describe('jsonLogic: cross-values validations', () => {
|
|
14
|
+
describe('Does not conflict with native JSON schema', () => {
|
|
15
|
+
it('Given an optional field and empty value, jsonLogic validations are ignored', () => {
|
|
16
|
+
const { handleValidation } = createHeadlessForm(schemaWithNonRequiredField, {
|
|
17
|
+
strictInputType: false,
|
|
18
|
+
});
|
|
19
|
+
expect(handleValidation({}).formErrors).toBeUndefined();
|
|
20
|
+
expect(handleValidation({ field_a: 0, field_b: 10 }).formErrors).toEqual({
|
|
21
|
+
field_b: 'Must be greater than field_a',
|
|
22
|
+
});
|
|
23
|
+
expect(handleValidation({ field_a: 'incorrect value' }).formErrors).toEqual({
|
|
24
|
+
field_a: 'The value must be a number',
|
|
25
|
+
});
|
|
26
|
+
expect(handleValidation({ field_a: 11 }).formErrors).toBeUndefined();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('Native validations have higher precedence than jsonLogic validations', () => {
|
|
30
|
+
const { handleValidation } = createHeadlessForm(schemaWithNativeAndJSONLogicChecks, {
|
|
31
|
+
strictInputType: false,
|
|
32
|
+
});
|
|
33
|
+
expect(handleValidation({}).formErrors).toEqual({ field_a: 'Required field' });
|
|
34
|
+
expect(handleValidation({ field_a: 0 }).formErrors).toEqual({
|
|
35
|
+
field_a: 'Must be greater or equal to 100',
|
|
36
|
+
});
|
|
37
|
+
expect(handleValidation({ field_a: 101 }).formErrors).toEqual({
|
|
38
|
+
field_a: 'Must be a multiple of 10',
|
|
39
|
+
});
|
|
40
|
+
expect(handleValidation({ field_a: 110 }).formErrors).toBeUndefined();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('Relative: <, >, =', () => {
|
|
45
|
+
it('bigger: field_a > field_b', () => {
|
|
46
|
+
const schema = createSchemaWithRulesOnFieldA({
|
|
47
|
+
a_greater_than_b: {
|
|
48
|
+
errorMessage: 'Field A must be bigger than field B',
|
|
49
|
+
rule: { '>': [{ var: 'field_a' }, { var: 'field_b' }] },
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const { handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
53
|
+
const { formErrors } = handleValidation({ field_a: 1, field_b: 2 });
|
|
54
|
+
expect(formErrors.field_a).toEqual('Field A must be bigger than field B');
|
|
55
|
+
expect(handleValidation({ field_a: 2, field_b: 0 }).formErrors).toEqual(undefined);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('smaller: field_a < field_b', () => {
|
|
59
|
+
const schema = createSchemaWithRulesOnFieldA({
|
|
60
|
+
a_less_than_b: {
|
|
61
|
+
errorMessage: 'Field A must be smaller than field B',
|
|
62
|
+
rule: { '<': [{ var: 'field_a' }, { var: 'field_b' }] },
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
const { handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
66
|
+
const { formErrors } = handleValidation({ field_a: 2, field_b: 2 });
|
|
67
|
+
expect(formErrors.field_a).toEqual('Field A must be smaller than field B');
|
|
68
|
+
expect(handleValidation({ field_a: 0, field_b: 2 }).formErrors).toEqual(undefined);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('equal: field_a = field_b', () => {
|
|
72
|
+
const schema = createSchemaWithRulesOnFieldA({
|
|
73
|
+
a_equals_b: {
|
|
74
|
+
errorMessage: 'Field A must equal field B',
|
|
75
|
+
rule: { '==': [{ var: 'field_a' }, { var: 'field_b' }] },
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
const { handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
79
|
+
const { formErrors } = handleValidation({ field_a: 3, field_b: 2 });
|
|
80
|
+
expect(formErrors.field_a).toEqual('Field A must equal field B');
|
|
81
|
+
expect(handleValidation({ field_a: 2, field_b: 2 }).formErrors).toEqual(undefined);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('Arithmetic: +, -, *, /', () => {
|
|
86
|
+
it('multiple: field_a > field_b * 2', () => {
|
|
87
|
+
const schema = createSchemaWithRulesOnFieldA({
|
|
88
|
+
a_greater_than_b_multiplied_by_2: {
|
|
89
|
+
errorMessage: 'Field A must be at least twice as big as field b',
|
|
90
|
+
rule: { '>': [{ var: 'field_a' }, { '*': [{ var: 'field_b' }, 2] }] },
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const { handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
94
|
+
|
|
95
|
+
const { formErrors } = handleValidation({ field_a: 1, field_b: 4 });
|
|
96
|
+
expect(formErrors.field_a).toEqual('Field A must be at least twice as big as field b');
|
|
97
|
+
expect(handleValidation({ field_a: 3, field_b: 1 }).formErrors).toEqual(undefined);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('divide: field_a > field_b / 2', () => {
|
|
101
|
+
const { handleValidation } = createHeadlessForm(
|
|
102
|
+
createSchemaWithRulesOnFieldA({
|
|
103
|
+
a_greater_than_b_divided_by_2: {
|
|
104
|
+
errorMessage: 'Field A must be greater than field_b / 2',
|
|
105
|
+
rule: { '>': [{ var: 'field_a' }, { '/': [{ var: 'field_b' }, 2] }] },
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
{ strictInputType: false }
|
|
109
|
+
);
|
|
110
|
+
expect(handleValidation({ field_a: 2, field_b: 4 }).formErrors).toEqual({
|
|
111
|
+
field_a: 'Field A must be greater than field_b / 2',
|
|
112
|
+
});
|
|
113
|
+
expect(handleValidation({ field_a: 3, field_b: 5 }).formErrors).toEqual(undefined);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('sum: field_a > field_b + field_c', () => {
|
|
117
|
+
const schema = createSchemaWithThreePropertiesWithRuleOnFieldA({
|
|
118
|
+
a_is_greater_than_b_plus_c: {
|
|
119
|
+
errorMessage: 'Field A must be greater than field_b and field_b added together',
|
|
120
|
+
rule: {
|
|
121
|
+
'>': [{ var: 'field_a' }, { '+': [{ var: 'field_b' }, { var: 'field_c' }] }],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
const { handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
126
|
+
const { formErrors } = handleValidation({ field_a: 0, field_b: 1, field_c: 2 });
|
|
127
|
+
expect(formErrors.field_a).toEqual(
|
|
128
|
+
'Field A must be greater than field_b and field_b added together'
|
|
129
|
+
);
|
|
130
|
+
expect(handleValidation({ field_a: 4, field_b: 1, field_c: 2 }).formErrors).toEqual(
|
|
131
|
+
undefined
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('Logical: ||, &&', () => {
|
|
137
|
+
it('AND: field_a > field_b && field_a > field_c (implicit with multiple rules in a single field)', () => {
|
|
138
|
+
const schema = createSchemaWithThreePropertiesWithRuleOnFieldA({
|
|
139
|
+
a_is_greater_than_b: {
|
|
140
|
+
errorMessage: 'Field A must be greater than field_b',
|
|
141
|
+
rule: {
|
|
142
|
+
'>': [{ var: 'field_a' }, { var: 'field_b' }],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
a_is_greater_than_c: {
|
|
146
|
+
errorMessage: 'Field A must be greater than field_c',
|
|
147
|
+
rule: {
|
|
148
|
+
'>': [{ var: 'field_a' }, { var: 'field_c' }],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
const { handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
153
|
+
expect(handleValidation({ field_a: 1, field_b: 10, field_c: 0 }).formErrors.field_a).toEqual(
|
|
154
|
+
'Field A must be greater than field_b'
|
|
155
|
+
);
|
|
156
|
+
expect(handleValidation({ field_a: 1, field_b: 0, field_c: 10 }).formErrors.field_a).toEqual(
|
|
157
|
+
'Field A must be greater than field_c'
|
|
158
|
+
);
|
|
159
|
+
expect(handleValidation({ field_a: 10, field_b: 5, field_c: 5 }).formErrors).toEqual(
|
|
160
|
+
undefined
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('OR: field_a > field_b or field_a > field_c', () => {
|
|
165
|
+
const schema = createSchemaWithThreePropertiesWithRuleOnFieldA({
|
|
166
|
+
field_a_is_greater_than_b_or_c: {
|
|
167
|
+
errorMessage: 'Field A must be greater than field_b or field_c',
|
|
168
|
+
rule: {
|
|
169
|
+
or: [
|
|
170
|
+
{ '>': [{ var: 'field_a' }, { var: 'field_b' }] },
|
|
171
|
+
{ '>': [{ var: 'field_a' }, { var: 'field_c' }] },
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
const { handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
177
|
+
expect(handleValidation({ field_a: 0, field_b: 10, field_c: 10 }).formErrors.field_a).toEqual(
|
|
178
|
+
'Field A must be greater than field_b or field_c'
|
|
179
|
+
);
|
|
180
|
+
expect(handleValidation({ field_a: 1, field_b: 0, field_c: 10 }).formErrors).toEqual(
|
|
181
|
+
undefined
|
|
182
|
+
);
|
|
183
|
+
expect(handleValidation({ field_a: 10, field_b: 5, field_c: 5 }).formErrors).toEqual(
|
|
184
|
+
undefined
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('Multiple validations', () => {
|
|
190
|
+
it('two rules: A > B; A is even', () => {
|
|
191
|
+
const { handleValidation } = createHeadlessForm(multiRuleSchema, { strictInputType: false });
|
|
192
|
+
expect(handleValidation({ field_a: 1 }).formErrors).toEqual({
|
|
193
|
+
field_a: 'A must be even',
|
|
194
|
+
field_b: 'Required field',
|
|
195
|
+
});
|
|
196
|
+
expect(handleValidation({ field_a: 1, field_b: 2 }).formErrors).toEqual({
|
|
197
|
+
field_a: 'A must be bigger than B',
|
|
198
|
+
});
|
|
199
|
+
expect(handleValidation({ field_a: 3, field_b: 2 }).formErrors).toEqual({
|
|
200
|
+
field_a: 'A must be even',
|
|
201
|
+
});
|
|
202
|
+
expect(handleValidation({ field_a: 4, field_b: 2 }).formErrors).toEqual(undefined);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('2 seperate fields with rules failing', () => {
|
|
206
|
+
const { handleValidation } = createHeadlessForm(schemaWithTwoRules, {
|
|
207
|
+
strictInputType: false,
|
|
208
|
+
});
|
|
209
|
+
expect(handleValidation({ field_a: 1, field_b: 3 }).formErrors).toEqual({
|
|
210
|
+
field_a: 'A must be bigger than B',
|
|
211
|
+
field_b: 'B must be even',
|
|
212
|
+
});
|
|
213
|
+
expect(handleValidation({ field_a: 4, field_b: 2 }).formErrors).toEqual(undefined);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('Derive values', () => {
|
|
218
|
+
it('field_b is field_a * 2', () => {
|
|
219
|
+
const { fields, handleValidation } = createHeadlessForm(schemaWithComputedAttributes, {
|
|
220
|
+
strictInputType: false,
|
|
221
|
+
initialValues: { field_a: 2 },
|
|
222
|
+
});
|
|
223
|
+
const fieldB = fields.find((i) => i.name === 'field_b');
|
|
224
|
+
expect(fieldB.default).toEqual(4);
|
|
225
|
+
expect(fieldB.value).toEqual(4);
|
|
226
|
+
handleValidation({ field_a: 4 });
|
|
227
|
+
expect(fieldB.default).toEqual(8);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});
|