@remoteoss/json-schema-form 0.7.1-dev.20231026204916 → 0.7.2-dev.20231106093837

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.
@@ -15,6 +15,7 @@ import {
15
15
  schemaInputTypeRadioOptionsWithDetails,
16
16
  schemaInputTypeSelectSoloDeprecated,
17
17
  schemaInputTypeSelectSolo,
18
+ schemaInputTypeSelectString,
18
19
  schemaInputTypeSelectMultipleDeprecated,
19
20
  schemaInputTypeSelectMultiple,
20
21
  schemaInputTypeSelectMultipleOptional,
@@ -38,7 +39,6 @@ import {
38
39
  mockFileInput,
39
40
  mockRadioCardInput,
40
41
  mockRadioCardExpandableInput,
41
- mockTelWithPattern,
42
42
  mockTextInput,
43
43
  mockTextInputDeprecated,
44
44
  mockNumberInput,
@@ -431,7 +431,7 @@ describe('createHeadlessForm', () => {
431
431
  });
432
432
 
433
433
  describe('field support', () => {
434
- function assertOptionsAllowed({ handleValidation, fieldName, validOptions }) {
434
+ function assertOptionsAllowed({ handleValidation, fieldName, validOptions, isString = false }) {
435
435
  const validateForm = (vals) => friendlyError(handleValidation(vals));
436
436
 
437
437
  // All allowed options are valid
@@ -439,27 +439,34 @@ describe('createHeadlessForm', () => {
439
439
  expect(validateForm({ [fieldName]: value })).toBeUndefined();
440
440
  });
441
441
 
442
- // Any other arbitrary value is not valid.
443
- expect(validateForm({ [fieldName]: 'blah-blah' })).toEqual({
444
- [fieldName]: 'The option "blah-blah" is not valid.',
445
- });
442
+ if (!isString) {
443
+ // Any other arbitrary value is not valid.
444
+ expect(validateForm({ [fieldName]: 'blah-blah' })).toEqual({
445
+ [fieldName]: 'The option "blah-blah" is not valid.',
446
+ });
446
447
 
447
- // Given undefined, it says it's a required field.
448
- expect(validateForm({})).toEqual({
449
- [fieldName]: 'Required field',
450
- });
448
+ // Given undefined, it says it's a required field.
449
+ expect(validateForm({})).toEqual({
450
+ [fieldName]: 'Required field',
451
+ });
451
452
 
452
- // As required field, empty string ("") is also considered empty. @BUG RMT-518
453
- // Expectation: The error to be "The option '' is not valid."
454
- expect(validateForm({ [fieldName]: '' })).toEqual({
455
- [fieldName]: 'Required field',
456
- });
453
+ // As required field, empty string ("") is also considered empty. @BUG RMT-518
454
+ // Expectation: The error to be "The option '' is not valid."
455
+ expect(validateForm({ [fieldName]: '' })).toEqual({
456
+ [fieldName]: 'Required field',
457
+ });
457
458
 
458
- // As required field, null is also considered empty @BUG RMT-518
459
- // Expectation: The error to be "The option null is not valid."
460
- expect(validateForm({ [fieldName]: null })).toEqual({
461
- [fieldName]: 'Required field',
462
- });
459
+ // As required field, null is also considered empty @BUG RMT-518
460
+ // Expectation: The error to be "The option null is not valid."
461
+ expect(validateForm({ [fieldName]: null })).toEqual({
462
+ [fieldName]: 'Required field',
463
+ });
464
+ }
465
+
466
+ if (isString) {
467
+ // Any other arbitrary value is valid.
468
+ expect(validateForm({ [fieldName]: 'blah-blah' })).toBeUndefined();
469
+ }
463
470
  }
464
471
 
465
472
  it('support "text" field type', () => {
@@ -631,6 +638,41 @@ describe('createHeadlessForm', () => {
631
638
  });
632
639
  });
633
640
 
641
+ it('supports "select" field type with string option', () => {
642
+ const { fields, handleValidation } = createHeadlessForm(schemaInputTypeSelectString);
643
+ const fieldSelect = fields[0];
644
+ expect(fieldSelect).toMatchObject({
645
+ name: 'browsers',
646
+ label: 'Browsers (solo)',
647
+ description: 'This solo select also includes a disabled option.',
648
+ options: [
649
+ {
650
+ value: 'chr',
651
+ label: 'Chrome',
652
+ },
653
+ {
654
+ value: 'ff',
655
+ label: 'Firefox',
656
+ },
657
+ {
658
+ value: 'ie',
659
+ label: 'Internet Explorer',
660
+ disabled: true,
661
+ },
662
+ { value: undefined, type: 'string', label: '{Create another}' },
663
+ ],
664
+ });
665
+
666
+ expect(fieldSelect).not.toHaveProperty('multiple');
667
+
668
+ assertOptionsAllowed({
669
+ handleValidation,
670
+ fieldName: 'browsers',
671
+ validOptions: ['chr', 'ff', 'ie'],
672
+ isString: true,
673
+ });
674
+ });
675
+
634
676
  it('supports "select" field type with multiple options @deprecated', () => {
635
677
  const result = createHeadlessForm(schemaInputTypeSelectMultipleDeprecated);
636
678
  expect(result).toMatchObject({
@@ -813,6 +855,7 @@ describe('createHeadlessForm', () => {
813
855
  has_car: 'yes',
814
856
  })
815
857
  ).toBeUndefined();
858
+
816
859
  expect(validateForm({})).toEqual({
817
860
  has_siblings: 'Required field',
818
861
  });
@@ -1376,6 +1419,50 @@ describe('createHeadlessForm', () => {
1376
1419
  ],
1377
1420
  });
1378
1421
  });
1422
+
1423
+ it('can be a conditional field', () => {
1424
+ const { fields, handleValidation } = createHeadlessForm({
1425
+ properties: {
1426
+ yes_or_no: {
1427
+ title: 'Show the dependents or not?',
1428
+ oneOf: [{ const: 'yes' }, { const: 'no' }],
1429
+ 'x-jsf-presentation': { inputType: 'radio' },
1430
+ },
1431
+ dependent_details: mockGroupArrayInput,
1432
+ },
1433
+ allOf: [
1434
+ {
1435
+ if: {
1436
+ properties: {
1437
+ yes_or_no: { const: 'yes' },
1438
+ },
1439
+ required: ['yes_or_no'],
1440
+ },
1441
+ then: {
1442
+ required: ['dependent_details'],
1443
+ },
1444
+ else: {
1445
+ properties: {
1446
+ dependent_details: false,
1447
+ },
1448
+ },
1449
+ },
1450
+ ],
1451
+ });
1452
+
1453
+ // By default is hidden but the fields are accessible
1454
+ expect(getField(fields, 'dependent_details').isVisible).toBe(false);
1455
+ expect(getField(fields, 'dependent_details').fields).toEqual(expect.any(Function));
1456
+
1457
+ // When the condition matches...
1458
+ const { formErrors } = handleValidation({ yes_or_no: 'yes' });
1459
+ expect(formErrors).toEqual({
1460
+ dependent_details: 'Required field',
1461
+ });
1462
+ // it gets visible with its inner fields.
1463
+ expect(getField(fields, 'dependent_details').isVisible).toBe(true);
1464
+ expect(getField(fields, 'dependent_details').fields).toEqual(expect.any(Function));
1465
+ });
1379
1466
  });
1380
1467
 
1381
1468
  it('supports "radio" field type with its "card" and "card-expandable" variants', () => {
@@ -1443,51 +1530,6 @@ describe('createHeadlessForm', () => {
1443
1530
  });
1444
1531
  });
1445
1532
 
1446
- it('supports oneOf pattern validation', () => {
1447
- const result = createHeadlessForm(mockTelWithPattern);
1448
-
1449
- expect(result).toMatchObject({
1450
- fields: [
1451
- {
1452
- label: 'Phone number',
1453
- name: 'phone_number',
1454
- type: 'tel',
1455
- required: false,
1456
- options: [
1457
- {
1458
- label: 'Portugal',
1459
- pattern: '^(\\+351)[0-9]{9,}$',
1460
- },
1461
- {
1462
- label: 'United Kingdom (UK)',
1463
- pattern: '^(\\+44)[0-9]{1,}$',
1464
- },
1465
- {
1466
- label: 'Bolivia',
1467
- pattern: '^(\\+591)[0-9]{9,}$',
1468
- },
1469
- {
1470
- label: 'Canada',
1471
- pattern: '^(\\+1)(206|224)[0-9]{1,}$',
1472
- },
1473
- {
1474
- label: 'United States',
1475
- pattern: '^(\\+1)[0-9]{1,}$',
1476
- },
1477
- ],
1478
- },
1479
- ],
1480
- });
1481
-
1482
- const fieldValidator = result.fields[0].schema;
1483
-
1484
- expect(fieldValidator.isValidSync('+351123123123')).toBe(true);
1485
- expect(() => fieldValidator.validateSync('+35100')).toThrowError(
1486
- 'The option "+35100" is not valid.'
1487
- );
1488
- expect(fieldValidator.isValidSync(undefined)).toBe(true);
1489
- });
1490
-
1491
1533
  describe('supports "fieldset" field type', () => {
1492
1534
  it('supports basic case', () => {
1493
1535
  const result = createHeadlessForm({
@@ -1765,11 +1807,8 @@ describe('createHeadlessForm', () => {
1765
1807
  expect(foodField.options).toHaveLength(4);
1766
1808
  // ...Food description was back to the original
1767
1809
  expect(foodField.description).toBeUndefined();
1768
-
1769
- // @BUG RMT-58 PTO description should disappear, but it didn't.
1770
- expect(getField(fields, 'pto').description).toBe(
1771
- 'Above 30 hours, the PTO needs to be at least 20 days.'
1772
- );
1810
+ // ...PTO Description is removed too.
1811
+ expect(getField(fields, 'pto').description).toBeUndefined();
1773
1812
 
1774
1813
  // Given again "low perks", the form valid.
1775
1814
  expect(
@@ -238,6 +238,11 @@ export const mockSelectInputSolo = {
238
238
  },
239
239
  };
240
240
 
241
+ export const mockSelectInputSoloCreatable = {
242
+ ...mockSelectInputSolo,
243
+ oneOf: [...mockSelectInputSolo.oneOf, { type: 'string', title: '{Create another}' }],
244
+ };
245
+
241
246
  export const mockSelectInputMultiple = {
242
247
  title: 'Browsers (multiple)',
243
248
  description: 'This multi-select also includes a disabled option.',
@@ -453,46 +458,6 @@ export const mockCheckboxInput = {
453
458
  type: 'string',
454
459
  };
455
460
 
456
- export const mockTelWithPattern = {
457
- properties: {
458
- phone_number: {
459
- title: 'Phone number',
460
- description: 'Enter your telephone number',
461
- type: 'string',
462
- 'x-jsf-presentation': {
463
- inputType: 'tel',
464
- },
465
- oneOf: [
466
- {
467
- title: 'Portugal',
468
- pattern: '^(\\+351)[0-9]{9,}$',
469
- 'x-jsf-presentation': { meta: { countryCode: '351' } },
470
- },
471
- {
472
- title: 'United Kingdom (UK)',
473
- pattern: '^(\\+44)[0-9]{1,}$',
474
- 'x-jsf-presentation': { meta: { countryCode: '44' } },
475
- },
476
- {
477
- title: 'Bolivia',
478
- pattern: '^(\\+591)[0-9]{9,}$',
479
- 'x-jsf-presentation': { meta: { countryCode: '591' } },
480
- },
481
- {
482
- title: 'Canada',
483
- pattern: '^(\\+1)(206|224)[0-9]{1,}$',
484
- 'x-jsf-presentation': { meta: { countryCode: '1' } },
485
- },
486
- {
487
- title: 'United States',
488
- pattern: '^(\\+1)[0-9]{1,}$',
489
- 'x-jsf-presentation': { meta: { countryCode: '1' } },
490
- },
491
- ],
492
- },
493
- },
494
- };
495
-
496
461
  /**
497
462
  * Compose a schema with lower chance of human error
498
463
  * @param {Object} schema version
@@ -937,6 +902,10 @@ export const schemaInputTypeSelectSolo = JSONSchemaBuilder()
937
902
  .setRequiredFields(['browsers'])
938
903
  .build();
939
904
 
905
+ export const schemaInputTypeSelectString = JSONSchemaBuilder().addInput({
906
+ browsers: mockSelectInputSoloCreatable,
907
+ });
908
+
940
909
  /** @deprecated */
941
910
  export const schemaInputTypeSelectMultipleDeprecated = JSONSchemaBuilder()
942
911
  .addInput({