@remoteoss/json-schema-form 0.4.1-dev.20230703195833 → 0.4.2-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 CHANGED
@@ -1,3 +1,16 @@
1
+ #### 0.4.2-beta.0 (2023-07-20)
2
+
3
+ ##### Bug Fixes
4
+
5
+ * **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))
6
+
7
+ #### 0.4.1-beta.0 (2023-07-03)
8
+
9
+ ##### Bug Fixes
10
+
11
+ * **fieldset:** support root conditionals for fieldsets ([#23](https://github.com/remoteoss/json-schema-form/pull/23)) ([65d87b3a](https://github.com/remoteoss/json-schema-form/commit/65d87b3a93018f0729aed565000eb2a2ce1f2ce7))
12
+ * **select/radio:** Accept just the values in options (plus `''` and `null` for backward-compatibility) ([#18](https://github.com/remoteoss/json-schema-form/pull/18)) ([37501d2d](https://github.com/remoteoss/json-schema-form/commit/37501d2ddafdd5e207b34d2ca3f6b7b7a1006e9d))
13
+
1
14
  #### 0.4.0-beta.0 (2023-06-22)
2
15
 
3
16
  ##### New Features
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2023 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.4.1-dev.20230703195833
5
- Generated: Mon, 03 Jul 2023 19:58:43 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.4.2-beta.0
5
+ Generated: Thu, 20 Jul 2023 11:13:46 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -381,15 +381,64 @@ var validateOnlyStrings = (0, import_yup.string)().trim().nullable().test(
381
381
  return true;
382
382
  }
383
383
  );
384
+ var compareDates = (d1, d2) => {
385
+ let date1 = new Date(d1).getTime();
386
+ let date2 = new Date(d2).getTime();
387
+ if (date1 < date2) {
388
+ return "LESSER";
389
+ } else if (date1 > date2) {
390
+ return "GREATER";
391
+ } else {
392
+ return "EQUAL";
393
+ }
394
+ };
395
+ var validateMinDate = (value, minDate) => {
396
+ const compare = compareDates(value, minDate);
397
+ return compare === "GREATER" || compare === "EQUAL" ? true : false;
398
+ };
399
+ var validateMaxDate = (value, minDate) => {
400
+ const compare = compareDates(value, minDate);
401
+ return compare === "LESSER" || compare === "EQUAL" ? true : false;
402
+ };
384
403
  var yupSchemas = {
385
404
  text: validateOnlyStrings,
386
- radioOrSelect: (options) => (0, import_yup.string)().nullable().oneOf(options, ({ value }) => {
405
+ radioOrSelect: (options) => (0, import_yup.string)().nullable().transform((value) => {
406
+ if (value === "") {
407
+ return void 0;
408
+ }
409
+ if (options?.includes(null)) {
410
+ return value;
411
+ }
412
+ return value === null ? void 0 : value;
413
+ }).oneOf(options, ({ value }) => {
387
414
  return `The option ${JSON.stringify(value)} is not valid.`;
388
415
  }),
389
- date: (0, import_yup.string)().nullable().trim().matches(
390
- /(?:\d){4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9]|3[0-1])/,
391
- `Must be a valid date in ${DEFAULT_DATE_FORMAT.toLocaleLowerCase()} format. e.g. ${todayDateHint}`
392
- ),
416
+ date: ({ minDate, maxDate }) => {
417
+ let dateString = (0, import_yup.string)().nullable().transform((value) => {
418
+ if (value === "") {
419
+ return void 0;
420
+ }
421
+ return value === null ? void 0 : value;
422
+ }).trim().matches(
423
+ /(?:\d){4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9]|3[0-1])/,
424
+ `Must be a valid date in ${DEFAULT_DATE_FORMAT.toLocaleLowerCase()} format. e.g. ${todayDateHint}`
425
+ );
426
+ if (minDate) {
427
+ dateString = dateString.test(
428
+ "minDate",
429
+ `The date must be ${minDate} or after.`,
430
+ (value) => validateMinDate(value, minDate)
431
+ );
432
+ }
433
+ if (maxDate) {
434
+ dateString = dateString.test(
435
+ "maxDate",
436
+ `The date must be ${maxDate} or before.`,
437
+ (value) => validateMaxDate(value, maxDate)
438
+ );
439
+ }
440
+ return dateString;
441
+ },
393
442
  number: (0, import_yup.number)().typeError("The value must be a number").nullable(),
394
443
  file: (0, import_yup.array)().nullable(),
395
444
  email: (0, import_yup.string)().trim().email("Please enter a valid email address").nullable(),
@@ -420,38 +469,22 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
420
469
  return "Required field";
421
470
  }
422
471
  var getJsonTypeInArray = (jsonType) => Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
423
- var getOptionsAllowed = (field) => {
424
- const onlyValues = field.options?.map((option) => option.value);
425
- const optionsBroken = [
426
- ...onlyValues,
427
- ""
428
- // [1]
429
- ];
430
- if (field.required) {
431
- return [
432
- ...optionsBroken,
433
- null
434
- // [2]
435
- ];
436
- }
472
+ var getOptions = (field) => {
473
+ const allValues = field.options?.map((option) => option.value);
437
474
  const isOptionalWithNull = Array.isArray(field.jsonType) && // @TODO should also check the "oneOf" directly looking for "null"
438
475
  // option but we don't have direct access at this point.
439
476
  // Otherwise the JSON Schema validator will fail as explained in PR#18
440
477
  field.jsonType.includes("null");
441
- if (isOptionalWithNull) {
442
- return [...optionsBroken, null];
443
- }
444
- return [
445
- ...optionsBroken,
446
- null
447
- // [3]
448
- ];
478
+ return isOptionalWithNull ? [...allValues, null] : allValues;
449
479
  };
450
480
  var getYupSchema = ({ inputType, ...field }) => {
451
481
  const jsonType = getJsonTypeInArray(field.jsonType);
452
482
  if (field.options?.length > 0) {
453
- const optionsAllowed = getOptionsAllowed(field);
454
- return yupSchemas.radioOrSelect(optionsAllowed);
483
+ const optionValues = getOptions(field);
484
+ return yupSchemas.radioOrSelect(optionValues);
485
+ }
486
+ if (field.format === "date") {
487
+ return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
455
488
  }
456
489
  return yupSchemas[inputType] || yupSchemasToJsonTypes[jsonType];
457
490
  };
@@ -912,6 +945,7 @@ function extractParametersFromNode(schemaNode) {
912
945
  maxFileSize: node.maxFileSize,
913
946
  // @deprecated in favor of presentation.maxFileSize
914
947
  default: node.default,
948
+ format: node.format,
915
949
  // Checkboxes conditions
916
950
  // — For checkboxes that only accept one value (string)
917
951
  ...presentation?.inputType === "checkbox" && { checkboxValue: node.const },
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2023 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.4.1-dev.20230703195833
5
- Generated: Mon, 03 Jul 2023 19:58:43 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.4.2-beta.0
5
+ Generated: Thu, 20 Jul 2023 11:13:46 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -345,15 +345,64 @@ var validateOnlyStrings = string().trim().nullable().test(
345
345
  return true;
346
346
  }
347
347
  );
348
+ var compareDates = (d1, d2) => {
349
+ let date1 = new Date(d1).getTime();
350
+ let date2 = new Date(d2).getTime();
351
+ if (date1 < date2) {
352
+ return "LESSER";
353
+ } else if (date1 > date2) {
354
+ return "GREATER";
355
+ } else {
356
+ return "EQUAL";
357
+ }
358
+ };
359
+ var validateMinDate = (value, minDate) => {
360
+ const compare = compareDates(value, minDate);
361
+ return compare === "GREATER" || compare === "EQUAL" ? true : false;
362
+ };
363
+ var validateMaxDate = (value, minDate) => {
364
+ const compare = compareDates(value, minDate);
365
+ return compare === "LESSER" || compare === "EQUAL" ? true : false;
366
+ };
348
367
  var yupSchemas = {
349
368
  text: validateOnlyStrings,
350
- radioOrSelect: (options) => string().nullable().oneOf(options, ({ value }) => {
369
+ radioOrSelect: (options) => string().nullable().transform((value) => {
370
+ if (value === "") {
371
+ return void 0;
372
+ }
373
+ if (options?.includes(null)) {
374
+ return value;
375
+ }
376
+ return value === null ? void 0 : value;
377
+ }).oneOf(options, ({ value }) => {
351
378
  return `The option ${JSON.stringify(value)} is not valid.`;
352
379
  }),
353
- date: string().nullable().trim().matches(
354
- /(?:\d){4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9]|3[0-1])/,
355
- `Must be a valid date in ${DEFAULT_DATE_FORMAT.toLocaleLowerCase()} format. e.g. ${todayDateHint}`
356
- ),
380
+ date: ({ minDate, maxDate }) => {
381
+ let dateString = string().nullable().transform((value) => {
382
+ if (value === "") {
383
+ return void 0;
384
+ }
385
+ return value === null ? void 0 : value;
386
+ }).trim().matches(
387
+ /(?:\d){4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9]|3[0-1])/,
388
+ `Must be a valid date in ${DEFAULT_DATE_FORMAT.toLocaleLowerCase()} format. e.g. ${todayDateHint}`
389
+ );
390
+ if (minDate) {
391
+ dateString = dateString.test(
392
+ "minDate",
393
+ `The date must be ${minDate} or after.`,
394
+ (value) => validateMinDate(value, minDate)
395
+ );
396
+ }
397
+ if (maxDate) {
398
+ dateString = dateString.test(
399
+ "maxDate",
400
+ `The date must be ${maxDate} or before.`,
401
+ (value) => validateMaxDate(value, maxDate)
402
+ );
403
+ }
404
+ return dateString;
405
+ },
357
406
  number: number().typeError("The value must be a number").nullable(),
358
407
  file: array().nullable(),
359
408
  email: string().trim().email("Please enter a valid email address").nullable(),
@@ -384,38 +433,22 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
384
433
  return "Required field";
385
434
  }
386
435
  var getJsonTypeInArray = (jsonType) => Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
387
- var getOptionsAllowed = (field) => {
388
- const onlyValues = field.options?.map((option) => option.value);
389
- const optionsBroken = [
390
- ...onlyValues,
391
- ""
392
- // [1]
393
- ];
394
- if (field.required) {
395
- return [
396
- ...optionsBroken,
397
- null
398
- // [2]
399
- ];
400
- }
436
+ var getOptions = (field) => {
437
+ const allValues = field.options?.map((option) => option.value);
401
438
  const isOptionalWithNull = Array.isArray(field.jsonType) && // @TODO should also check the "oneOf" directly looking for "null"
402
439
  // option but we don't have direct access at this point.
403
440
  // Otherwise the JSON Schema validator will fail as explained in PR#18
404
441
  field.jsonType.includes("null");
405
- if (isOptionalWithNull) {
406
- return [...optionsBroken, null];
407
- }
408
- return [
409
- ...optionsBroken,
410
- null
411
- // [3]
412
- ];
442
+ return isOptionalWithNull ? [...allValues, null] : allValues;
413
443
  };
414
444
  var getYupSchema = ({ inputType, ...field }) => {
415
445
  const jsonType = getJsonTypeInArray(field.jsonType);
416
446
  if (field.options?.length > 0) {
417
- const optionsAllowed = getOptionsAllowed(field);
418
- return yupSchemas.radioOrSelect(optionsAllowed);
447
+ const optionValues = getOptions(field);
448
+ return yupSchemas.radioOrSelect(optionValues);
449
+ }
450
+ if (field.format === "date") {
451
+ return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
419
452
  }
420
453
  return yupSchemas[inputType] || yupSchemasToJsonTypes[jsonType];
421
454
  };
@@ -876,6 +909,7 @@ function extractParametersFromNode(schemaNode) {
876
909
  maxFileSize: node.maxFileSize,
877
910
  // @deprecated in favor of presentation.maxFileSize
878
911
  default: node.default,
912
+ format: node.format,
879
913
  // Checkboxes conditions
880
914
  // — For checkboxes that only accept one value (string)
881
915
  ...presentation?.inputType === "checkbox" && { checkboxValue: node.const },
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2023 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.4.1-dev.20230703195833
5
- Generated: Mon, 03 Jul 2023 19:58:43 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.4.2-beta.0
5
+ Generated: Thu, 20 Jul 2023 11:13:46 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -11321,15 +11321,64 @@ var validateOnlyStrings = StringSchema().trim().nullable().test(
11321
11321
  return true;
11322
11322
  }
11323
11323
  );
11324
+ var compareDates = (d1, d2) => {
11325
+ let date1 = new Date(d1).getTime();
11326
+ let date2 = new Date(d2).getTime();
11327
+ if (date1 < date2) {
11328
+ return "LESSER";
11329
+ } else if (date1 > date2) {
11330
+ return "GREATER";
11331
+ } else {
11332
+ return "EQUAL";
11333
+ }
11334
+ };
11335
+ var validateMinDate = (value, minDate) => {
11336
+ const compare = compareDates(value, minDate);
11337
+ return compare === "GREATER" || compare === "EQUAL" ? true : false;
11338
+ };
11339
+ var validateMaxDate = (value, minDate) => {
11340
+ const compare = compareDates(value, minDate);
11341
+ return compare === "LESSER" || compare === "EQUAL" ? true : false;
11342
+ };
11324
11343
  var yupSchemas = {
11325
11344
  text: validateOnlyStrings,
11326
- radioOrSelect: (options) => StringSchema().nullable().oneOf(options, ({ value }) => {
11345
+ radioOrSelect: (options) => StringSchema().nullable().transform((value) => {
11346
+ if (value === "") {
11347
+ return void 0;
11348
+ }
11349
+ if (options?.includes(null)) {
11350
+ return value;
11351
+ }
11352
+ return value === null ? void 0 : value;
11353
+ }).oneOf(options, ({ value }) => {
11327
11354
  return `The option ${JSON.stringify(value)} is not valid.`;
11328
11355
  }),
11329
- date: StringSchema().nullable().trim().matches(
11330
- /(?:\d){4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9]|3[0-1])/,
11331
- `Must be a valid date in ${DEFAULT_DATE_FORMAT.toLocaleLowerCase()} format. e.g. ${todayDateHint}`
11332
- ),
11356
+ date: ({ minDate, maxDate }) => {
11357
+ let dateString = StringSchema().nullable().transform((value) => {
11358
+ if (value === "") {
11359
+ return void 0;
11360
+ }
11361
+ return value === null ? void 0 : value;
11362
+ }).trim().matches(
11363
+ /(?:\d){4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9]|3[0-1])/,
11364
+ `Must be a valid date in ${DEFAULT_DATE_FORMAT.toLocaleLowerCase()} format. e.g. ${todayDateHint}`
11365
+ );
11366
+ if (minDate) {
11367
+ dateString = dateString.test(
11368
+ "minDate",
11369
+ `The date must be ${minDate} or after.`,
11370
+ (value) => validateMinDate(value, minDate)
11371
+ );
11372
+ }
11373
+ if (maxDate) {
11374
+ dateString = dateString.test(
11375
+ "maxDate",
11376
+ `The date must be ${maxDate} or before.`,
11377
+ (value) => validateMaxDate(value, maxDate)
11378
+ );
11379
+ }
11380
+ return dateString;
11381
+ },
11333
11382
  number: NumberSchema().typeError("The value must be a number").nullable(),
11334
11383
  file: array_default().nullable(),
11335
11384
  email: StringSchema().trim().email("Please enter a valid email address").nullable(),
@@ -11360,38 +11409,22 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
11360
11409
  return "Required field";
11361
11410
  }
11362
11411
  var getJsonTypeInArray = (jsonType) => Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
11363
- var getOptionsAllowed = (field) => {
11364
- const onlyValues = field.options?.map((option) => option.value);
11365
- const optionsBroken = [
11366
- ...onlyValues,
11367
- ""
11368
- // [1]
11369
- ];
11370
- if (field.required) {
11371
- return [
11372
- ...optionsBroken,
11373
- null
11374
- // [2]
11375
- ];
11376
- }
11412
+ var getOptions = (field) => {
11413
+ const allValues = field.options?.map((option) => option.value);
11377
11414
  const isOptionalWithNull = Array.isArray(field.jsonType) && // @TODO should also check the "oneOf" directly looking for "null"
11378
11415
  // option but we don't have direct access at this point.
11379
11416
  // Otherwise the JSON Schema validator will fail as explained in PR#18
11380
11417
  field.jsonType.includes("null");
11381
- if (isOptionalWithNull) {
11382
- return [...optionsBroken, null];
11383
- }
11384
- return [
11385
- ...optionsBroken,
11386
- null
11387
- // [3]
11388
- ];
11418
+ return isOptionalWithNull ? [...allValues, null] : allValues;
11389
11419
  };
11390
11420
  var getYupSchema = ({ inputType, ...field }) => {
11391
11421
  const jsonType = getJsonTypeInArray(field.jsonType);
11392
11422
  if (field.options?.length > 0) {
11393
- const optionsAllowed = getOptionsAllowed(field);
11394
- return yupSchemas.radioOrSelect(optionsAllowed);
11423
+ const optionValues = getOptions(field);
11424
+ return yupSchemas.radioOrSelect(optionValues);
11425
+ }
11426
+ if (field.format === "date") {
11427
+ return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
11395
11428
  }
11396
11429
  return yupSchemas[inputType] || yupSchemasToJsonTypes[jsonType];
11397
11430
  };
@@ -11852,6 +11885,7 @@ function extractParametersFromNode(schemaNode) {
11852
11885
  maxFileSize: node.maxFileSize,
11853
11886
  // @deprecated in favor of presentation.maxFileSize
11854
11887
  default: node.default,
11888
+ format: node.format,
11855
11889
  // Checkboxes conditions
11856
11890
  // — For checkboxes that only accept one value (string)
11857
11891
  ...presentation?.inputType === "checkbox" && { checkboxValue: node.const },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remoteoss/json-schema-form",
3
- "version": "0.4.1-dev.20230703195833",
3
+ "version": "0.4.2-beta.0",
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",
@@ -439,23 +439,15 @@ describe('createHeadlessForm', () => {
439
439
 
440
440
  // All allowed options are valid
441
441
  validOptions.forEach((value) => {
442
- expect(
443
- validateForm({
444
- [fieldName]: value,
445
- })
446
- ).toBeUndefined();
442
+ expect(validateForm({ [fieldName]: value })).toBeUndefined();
447
443
  });
448
444
 
449
445
  // Any other arbitrary value is not valid.
450
- expect(
451
- validateForm({
452
- [fieldName]: 'blah-blah',
453
- })
454
- ).toEqual({
446
+ expect(validateForm({ [fieldName]: 'blah-blah' })).toEqual({
455
447
  [fieldName]: 'The option "blah-blah" is not valid.',
456
448
  });
457
449
 
458
- // This is a required field:
450
+ // Given undefined, it says it's a required field.
459
451
  expect(validateForm({})).toEqual({
460
452
  [fieldName]: 'Required field',
461
453
  });
@@ -831,6 +823,9 @@ describe('createHeadlessForm', () => {
831
823
 
832
824
  describe('support "radio" optional field - more examples @BUG RMT-518', () => {
833
825
  function assertCommonBehavior(validateForm) {
826
+ // Note: Very similar to assertOptionsAllowed()
827
+ // We could reuse it in a next iteration.
828
+
834
829
  // Happy path
835
830
  expect(validateForm({ has_car: 'yes' })).toBeUndefined();
836
831
 
@@ -1014,30 +1009,112 @@ describe('createHeadlessForm', () => {
1014
1009
  });
1015
1010
 
1016
1011
  it('support "date" field type', () => {
1017
- const result = createHeadlessForm(schemaInputTypeDate);
1012
+ const { fields, handleValidation } = createHeadlessForm(schemaInputTypeDate);
1018
1013
 
1019
- expect(result).toMatchObject({
1020
- fields: [
1021
- {
1022
- label: 'Birthdate',
1023
- name: 'birthdate',
1024
- required: true,
1025
- schema: expect.any(Object),
1026
- type: 'date',
1027
- maxLength: 10,
1028
- minDate: '1922-03-01',
1029
- maxDate: '2022-03-01',
1030
- },
1031
- ],
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',
1032
1024
  });
1033
1025
 
1034
- const fieldValidator = result.fields[0].schema;
1035
1026
  const todayDateHint = new Date().toISOString().substring(0, 10);
1036
- expect(fieldValidator.isValidSync('2020-10-10')).toBe(true);
1037
- expect(fieldValidator.isValidSync('2020-13-10')).toBe(false);
1038
- expect(() => fieldValidator.validateSync('')).toThrowError(
1039
- `Must be a valid date in yyyy-mm-dd format. e.g. ${todayDateHint}`
1040
- );
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
+ });
1041
1118
  });
1042
1119
 
1043
1120
  it('supports "file" field type', () => {
@@ -272,18 +272,6 @@ export const mockSelectInputMultipleOptional = {
272
272
  type: ['array', 'null'],
273
273
  };
274
274
 
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
-
287
275
  export const mockFileInput = {
288
276
  description: 'File Input Description',
289
277
  'x-jsf-presentation': {
@@ -998,12 +986,19 @@ export const schemaInputTypeNumberWithPercentage = JSONSchemaBuilder()
998
986
  .setRequiredFields(['shares'])
999
987
  .build();
1000
988
 
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
+ };
1007
1002
 
1008
1003
  export const schemaInputTypeEmail = JSONSchemaBuilder()
1009
1004
  .addInput({