Skip to content

Commit bb83706

Browse files
committed
chore: integrate with latest main
2 parents 5baaff9 + 3888952 commit bb83706

File tree

11 files changed

+316
-55
lines changed

11 files changed

+316
-55
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
#### 0.4.3-beta.0 (2023-08-09)
2+
3+
##### Bug fixes
4+
5+
* **conditions:** Validate a deeply nested if (e.g. checking an object with a number property) in an if property now doesn't break the form. ([#33](https://github.com/remoteoss/json-schema-form/pull/33)) ([e34cfcc](https://github.com/remoteoss/json-schema-form/commit/e34cfccaf45f1460b346f3cff0c797b3d11259e3))
6+
7+
#### 0.4.2-beta.0 (2023-07-20)
8+
9+
##### Bug Fixes
10+
11+
* **date:** Validate based on minDate and maxDate ([#30](https://github.com/remoteoss/json-schema-form/pull/30)) ([01c0143e](https://github.com/remoteoss/json-schema-form/commit/01c0143ea4a3775f9489ae6cb8fd99a90b3f1394))
12+
113
#### 0.4.1-beta.0 (2023-07-03)
214

315
##### Bug Fixes

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@remoteoss/json-schema-form",
3-
"version": "0.4.1-beta.0",
3+
"version": "0.4.3-beta.0",
44
"description": "Headless UI form powered by JSON Schemas",
55
"author": "Remote.com <[email protected]> (https://remote.com/)",
66
"license": "MIT",

src/nodeProcessing/checkIfConditionMatches.js renamed to src/checkIfConditionMatches.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { compareFormValueWithSchemaValue, getField, validateFieldSchema } from '../helpers';
2-
import { hasProperty } from '../utils';
1+
import { compareFormValueWithSchemaValue, getField, validateFieldSchema } from './helpers';
2+
import { hasProperty } from './utils';
33

44
/**
55
* Checks if a "IF" condition matches given the current form state
@@ -46,6 +46,15 @@ export function checkIfConditionMatches(node, formValues, formFields, validation
4646
return currentProperty.enum.includes(value);
4747
}
4848

49+
if (currentProperty.properties) {
50+
return checkIfConditionMatches(
51+
{ if: currentProperty },
52+
formValues[name],
53+
getField(name, formFields).fields,
54+
validations
55+
);
56+
}
57+
4958
const field = getField(name, formFields);
5059

5160
return validateFieldSchema(
@@ -56,8 +65,7 @@ export function checkIfConditionMatches(node, formValues, formFields, validation
5665
inputType: field.inputType,
5766
required: true,
5867
},
59-
value,
60-
validations
68+
value
6169
);
6270
});
6371
}

src/helpers.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import omitBy from 'lodash/omitBy';
55
import set from 'lodash/set';
66
import { lazy } from 'yup';
77

8+
import { checkIfConditionMatches } from './checkIfConditionMatches';
89
import { supportedTypes, getInputType } from './internals/fields';
910
import { pickXKey } from './internals/helpers';
1011
import { processJSONLogicNode } from './jsonLogic';
11-
import { checkIfConditionMatches } from './nodeProcessing/checkIfConditionMatches';
1212
import { containsHTML, hasProperty, wrapWithSpan } from './utils';
1313
import { buildCompleteYupSchema, buildYupSchema } from './yupSchema';
1414

@@ -504,6 +504,7 @@ export function extractParametersFromNode(schemaNode) {
504504
maximum: node.maximum,
505505
maxFileSize: node.maxFileSize, // @deprecated in favor of presentation.maxFileSize
506506
default: node.default,
507+
format: node.format,
507508
// Checkboxes conditions
508509
// — For checkboxes that only accept one value (string)
509510
...(presentation?.inputType === 'checkbox' && { checkboxValue: node.const }),

src/jsonLogic.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import jsonLogic from 'json-logic-js';
22

3-
import { processNode } from './helpers';
43
import {
54
checkIfConditionMatches,
65
checkIfMatchesValidationsAndComputedValues,
7-
} from './nodeProcessing/checkIfConditionMatches';
6+
} from './checkIfConditionMatches';
7+
import { processNode } from './helpers';
88

99
jsonLogic.add_operation('Number.toFixed', (a, b) => {
1010
if (typeof a === 'number') return a.toFixed(b);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { checkIfConditionMatches } from '../checkIfConditionMatches';
2+
3+
it('Empty if is always going to be true', () => {
4+
expect(checkIfConditionMatches({ if: { properties: {} } })).toBe(true);
5+
});
6+
7+
it('Basic if check passes with correct value', () => {
8+
expect(
9+
checkIfConditionMatches(
10+
{ if: { properties: { a: { const: 'hello' } } } },
11+
{
12+
a: 'hello',
13+
}
14+
)
15+
).toBe(true);
16+
});
17+
18+
it('Basic if check fails with incorrect value', () => {
19+
expect(
20+
checkIfConditionMatches(
21+
{ if: { properties: { a: { const: 'hello' } } } },
22+
{
23+
a: 'goodbye',
24+
}
25+
)
26+
).toBe(false);
27+
});
28+
29+
it('Nested properties check passes with correct value', () => {
30+
expect(
31+
checkIfConditionMatches(
32+
{ if: { properties: { parent: { properties: { child: { const: 'hello from child' } } } } } },
33+
{
34+
parent: { child: 'hello from child' },
35+
},
36+
[{ name: 'parent', fields: [] }]
37+
)
38+
).toBe(true);
39+
});
40+
41+
it('Nested properties check passes with correct value', () => {
42+
expect(
43+
checkIfConditionMatches(
44+
{ if: { properties: { parent: { properties: { child: { const: 'hello from child' } } } } } },
45+
{
46+
parent: { child: 'goodbye from child' },
47+
},
48+
[{ name: 'parent', fields: [] }]
49+
)
50+
).toBe(false);
51+
});

src/tests/conditions.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { createHeadlessForm } from '../createHeadlessForm';
2+
3+
it('Should allow check of a nested property in a conditional', () => {
4+
const { handleValidation } = createHeadlessForm(
5+
{
6+
additionalProperties: false,
7+
allOf: [
8+
{
9+
if: {
10+
properties: {
11+
parent: {
12+
properties: {
13+
child: {
14+
const: 'yes',
15+
},
16+
},
17+
required: ['child'],
18+
},
19+
},
20+
required: ['parent'],
21+
},
22+
then: { required: ['parent_sibling'] },
23+
},
24+
],
25+
properties: {
26+
parent: {
27+
additionalProperties: false,
28+
properties: {
29+
child: {
30+
oneOf: [
31+
{
32+
const: 'yes',
33+
},
34+
{ const: 'no' },
35+
],
36+
type: 'string',
37+
},
38+
},
39+
required: ['child'],
40+
type: 'object',
41+
},
42+
parent_sibling: {
43+
type: 'integer',
44+
},
45+
},
46+
required: ['parent'],
47+
type: 'object',
48+
},
49+
{ strictInputType: false }
50+
);
51+
expect(handleValidation({ parent: { child: 'no' } }).formErrors).toEqual(undefined);
52+
expect(handleValidation({ parent: { child: 'yes' } }).formErrors).toEqual({
53+
parent_sibling: 'Required field',
54+
});
55+
expect(handleValidation({ parent: { child: 'yes' }, parent_sibling: 1 }).formErrors).toEqual(
56+
undefined
57+
);
58+
});

src/tests/createHeadlessForm.test.js

Lines changed: 102 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,30 +1009,112 @@ describe('createHeadlessForm', () => {
10091009
});
10101010

10111011
it('support "date" field type', () => {
1012-
const result = createHeadlessForm(schemaInputTypeDate);
1012+
const { fields, handleValidation } = createHeadlessForm(schemaInputTypeDate);
10131013

1014-
expect(result).toMatchObject({
1015-
fields: [
1016-
{
1017-
label: 'Birthdate',
1018-
name: 'birthdate',
1019-
required: true,
1020-
schema: expect.any(Object),
1021-
type: 'date',
1022-
maxLength: 10,
1023-
minDate: '1922-03-01',
1024-
maxDate: '2022-03-01',
1025-
},
1026-
],
1014+
const validateForm = (vals) => friendlyError(handleValidation(vals));
1015+
1016+
expect(fields[0]).toMatchObject({
1017+
label: 'Birthdate',
1018+
name: 'birthdate',
1019+
required: true,
1020+
schema: expect.any(Object),
1021+
type: 'date',
1022+
minDate: '1922-03-01',
1023+
maxDate: '2022-03-17',
10271024
});
10281025

1029-
const fieldValidator = result.fields[0].schema;
10301026
const todayDateHint = new Date().toISOString().substring(0, 10);
1031-
expect(fieldValidator.isValidSync('2020-10-10')).toBe(true);
1032-
expect(fieldValidator.isValidSync('2020-13-10')).toBe(false);
1033-
expect(() => fieldValidator.validateSync('')).toThrowError(
1034-
`Must be a valid date in yyyy-mm-dd format. e.g. ${todayDateHint}`
1035-
);
1027+
1028+
expect(validateForm({})).toEqual({
1029+
birthdate: 'Required field',
1030+
});
1031+
1032+
expect(validateForm({ birthdate: '2020-10-10' })).toBeUndefined();
1033+
expect(validateForm({ birthdate: '2020-13-10' })).toEqual({
1034+
birthdate: `Must be a valid date in yyyy-mm-dd format. e.g. ${todayDateHint}`,
1035+
});
1036+
});
1037+
1038+
it('support "date" field type with a minDate', () => {
1039+
const { fields, handleValidation } = createHeadlessForm(schemaInputTypeDate);
1040+
1041+
const validateForm = (vals) => friendlyError(handleValidation(vals));
1042+
1043+
expect(fields[0]).toMatchObject({
1044+
label: 'Birthdate',
1045+
name: 'birthdate',
1046+
required: true,
1047+
schema: expect.any(Object),
1048+
type: 'date',
1049+
minDate: '1922-03-01',
1050+
maxDate: '2022-03-17',
1051+
});
1052+
1053+
expect(validateForm({})).toEqual({
1054+
birthdate: 'Required field',
1055+
});
1056+
1057+
expect(validateForm({ birthdate: '' })).toEqual({
1058+
birthdate: `Required field`,
1059+
});
1060+
1061+
expect(validateForm({ birthdate: '1922-02-01' })).toEqual({
1062+
birthdate: 'The date must be 1922-03-01 or after.',
1063+
});
1064+
1065+
expect(validateForm({ birthdate: '1922-03-01' })).toBeUndefined();
1066+
1067+
expect(validateForm({ birthdate: '2021-03-01' })).toBeUndefined();
1068+
});
1069+
1070+
it('support "date" field type with a maxDate', () => {
1071+
const { fields, handleValidation } = createHeadlessForm(schemaInputTypeDate);
1072+
1073+
const validateForm = (vals) => friendlyError(handleValidation(vals));
1074+
1075+
expect(fields[0]).toMatchObject({
1076+
label: 'Birthdate',
1077+
name: 'birthdate',
1078+
required: true,
1079+
schema: expect.any(Object),
1080+
type: 'date',
1081+
minDate: '1922-03-01',
1082+
maxDate: '2022-03-17',
1083+
});
1084+
1085+
expect(validateForm({ birthdate: '' })).toEqual({
1086+
birthdate: `Required field`,
1087+
});
1088+
1089+
expect(validateForm({ birthdate: '2022-02-01' })).toBeUndefined();
1090+
expect(validateForm({ birthdate: '2022-03-01' })).toBeUndefined();
1091+
expect(validateForm({ birthdate: '2022-04-01' })).toEqual({
1092+
birthdate: 'The date must be 2022-03-17 or before.',
1093+
});
1094+
});
1095+
1096+
it('support format date with minDate and maxDate', () => {
1097+
const schemaFormatDate = {
1098+
properties: {
1099+
birthdate: {
1100+
title: 'Birthdate',
1101+
type: 'string',
1102+
format: 'date',
1103+
'x-jsf-presentation': {
1104+
inputType: 'myDateType',
1105+
maxDate: '2022-03-01',
1106+
minDate: '1922-03-01',
1107+
},
1108+
},
1109+
},
1110+
};
1111+
1112+
const { handleValidation } = createHeadlessForm(schemaFormatDate);
1113+
const validateForm = (vals) => friendlyError(handleValidation(vals));
1114+
1115+
expect(validateForm({ birthdate: '1922-02-01' })).toEqual({
1116+
birthdate: 'The date must be 1922-03-01 or after.',
1117+
});
10361118
});
10371119

10381120
it('supports "file" field type', () => {

src/tests/helpers.js

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -272,18 +272,6 @@ export const mockSelectInputMultipleOptional = {
272272
type: ['array', 'null'],
273273
};
274274

275-
export const mockDateInput = {
276-
'x-jsf-presentation': {
277-
inputType: 'date',
278-
maxDate: '2022-03-01',
279-
minDate: '1922-03-01',
280-
},
281-
title: 'Birthdate',
282-
type: 'string',
283-
format: 'date',
284-
maxLength: 10,
285-
};
286-
287275
export const mockFileInput = {
288276
description: 'File Input Description',
289277
'x-jsf-presentation': {
@@ -998,12 +986,19 @@ export const schemaInputTypeNumberWithPercentage = JSONSchemaBuilder()
998986
.setRequiredFields(['shares'])
999987
.build();
1000988

1001-
export const schemaInputTypeDate = JSONSchemaBuilder()
1002-
.addInput({
1003-
birthdate: mockDateInput,
1004-
})
1005-
.setRequiredFields(['birthdate'])
1006-
.build();
989+
export const schemaInputTypeDate = {
990+
type: 'object',
991+
additionalProperties: false,
992+
properties: {
993+
birthdate: {
994+
'x-jsf-presentation': { inputType: 'date', maxDate: '2022-03-17', minDate: '1922-03-01' },
995+
title: 'Birthdate',
996+
type: 'string',
997+
format: 'date',
998+
},
999+
},
1000+
required: ['birthdate'],
1001+
};
10071002

10081003
export const schemaInputTypeEmail = JSONSchemaBuilder()
10091004
.addInput({

0 commit comments

Comments
 (0)