@remoteoss/json-schema-form 0.9.2-dev.20240518112325 → 0.10.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 CHANGED
@@ -1,32 +1,36 @@
1
+ #### 0.10.0-beta.0 (2024-06-20)
2
+
3
+ Adds `modify` utility for better customizations ([#75](https://github.com/remoteoss/json-schema-form/pull/75))
4
+
1
5
  #### 0.9.1-beta.0 (2024-03-26)
2
6
 
3
7
  ##### Bug Fixes
4
8
 
5
- * **select/radio:** Allow numbers in oneOf ([#49](https://github.com/remoteoss/json-schema-form/pull/49)) ([04c2598a](https://github.com/remoteoss/json-schema-form/commit/04c2598a3f4e31d8a9495e0d69c0427b6b8c9f56))
9
+ - **select/radio:** Allow numbers in oneOf ([#49](https://github.com/remoteoss/json-schema-form/pull/49)) ([04c2598a](https://github.com/remoteoss/json-schema-form/commit/04c2598a3f4e31d8a9495e0d69c0427b6b8c9f56))
6
10
 
7
11
  #### 0.9.0-beta.0 (2024-03-11)
8
12
 
9
13
  ##### Breaking changes
10
14
 
11
- * Rename `value` -> `forcedValue`. This is in regards to the `json-logic`, where a "forced value" will now be returned in each relevant field (i.e. fields where the schema `const` and `default` are the same) with `forcedValue` over `value`. ([#66](https://github.com/remoteoss/json-schema-form/pull/66)) ([77c445a9](https://github.com/remoteoss/json-schema-form/commit/77c445a9dce657a7648642312f22c18f972187c7))
15
+ - Rename `value` -> `forcedValue`. This is in regards to the `json-logic`, where a "forced value" will now be returned in each relevant field (i.e. fields where the schema `const` and `default` are the same) with `forcedValue` over `value`. ([#66](https://github.com/remoteoss/json-schema-form/pull/66)) ([77c445a9](https://github.com/remoteoss/json-schema-form/commit/77c445a9dce657a7648642312f22c18f972187c7))
12
16
 
13
17
  #### 0.8.2-beta.0 (2024-02-13)
14
18
 
15
19
  ##### Bug Fixes
16
20
 
17
- * **helpers:** getFieldOptions - return empty array if oneOf missing in radio ([#67](https://github.com/remoteoss/json-schema-form/pull/67)) ([6511330f](https://github.com/remoteoss/json-schema-form/commit/6511330f55a2accedb1c58a61ff915a3a0186dbb))
21
+ - **helpers:** getFieldOptions - return empty array if oneOf missing in radio ([#67](https://github.com/remoteoss/json-schema-form/pull/67)) ([6511330f](https://github.com/remoteoss/json-schema-form/commit/6511330f55a2accedb1c58a61ff915a3a0186dbb))
18
22
 
19
23
  #### 0.8.1-beta.0 (2024-02-12)
20
24
 
21
25
  ##### Bug Fixes
22
26
 
23
- * **conditionals:** Certain conditions in a JSON schema were failing. This bugfix adds missing field context to the evaluation to prevent the error. ([#65](https://github.com/remoteoss/json-schema-form/pull/65)) ([6755a2fd](https://github.com/remoteoss/json-schema-form/commit/6755a2fd29f3f806a57ba19e29ad7e21daf9e51b))
27
+ - **conditionals:** Certain conditions in a JSON schema were failing. This bugfix adds missing field context to the evaluation to prevent the error. ([#65](https://github.com/remoteoss/json-schema-form/pull/65)) ([6755a2fd](https://github.com/remoteoss/json-schema-form/commit/6755a2fd29f3f806a57ba19e29ad7e21daf9e51b))
24
28
 
25
29
  #### 0.8.0-beta.0 (2024-02-01)
26
30
 
27
31
  ##### Bug Fixes
28
32
 
29
- * **fieldset:** Support customProperties with sub-fields clashing with reserved words. ([#64](https://github.com/remoteoss/json-schema-form/pull/64)) ([8340cdea](https://github.com/remoteoss/json-schema-form/commit/8340cdea27b711064079055af939a595d1c38031))
33
+ - **fieldset:** Support customProperties with sub-fields clashing with reserved words. ([#64](https://github.com/remoteoss/json-schema-form/pull/64)) ([8340cdea](https://github.com/remoteoss/json-schema-form/commit/8340cdea27b711064079055af939a595d1c38031))
30
34
 
31
35
  #### 0.7.6-beta.0 (2024-01-23)
32
36
 
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2024 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.9.2-dev.20240518112325
5
- Generated: Sat, 18 May 2024 11:23:50 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.10.0-beta.0
5
+ Generated: Thu, 20 Jun 2024 10:37:49 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -60,6 +60,7 @@ var src_exports = {};
60
60
  __export(src_exports, {
61
61
  buildCompleteYupSchema: () => buildCompleteYupSchema,
62
62
  createHeadlessForm: () => createHeadlessForm,
63
+ modify: () => modify,
63
64
  pickXKey: () => pickXKey
64
65
  });
65
66
  module.exports = __toCommonJS(src_exports);
@@ -1831,3 +1832,60 @@ function createHeadlessForm(jsonSchema, customConfig = {}) {
1831
1832
  };
1832
1833
  }
1833
1834
  }
1835
+
1836
+ // src/modify.js
1837
+ var import_get4 = __toESM(require("lodash/get"));
1838
+ var import_merge3 = __toESM(require("lodash/merge"));
1839
+ function shortToFullPath(path) {
1840
+ return path.replace(".", ".properties.");
1841
+ }
1842
+ function standardizeAttrs(attrs) {
1843
+ const { errorMessage, properties, ...rest } = attrs;
1844
+ return {
1845
+ ...rest,
1846
+ ...errorMessage ? { "x-jsf-errorMessage": errorMessage } : {}
1847
+ };
1848
+ }
1849
+ function rewriteFields(schema, fieldsConfig) {
1850
+ if (!fieldsConfig)
1851
+ return null;
1852
+ const fieldsToModify = Object.entries(fieldsConfig);
1853
+ fieldsToModify.forEach(([shortPath, mutation]) => {
1854
+ const fieldPath = shortToFullPath(shortPath);
1855
+ if (!(0, import_get4.default)(schema.properties, fieldPath)) {
1856
+ return;
1857
+ }
1858
+ const fieldAttrs = (0, import_get4.default)(schema.properties, fieldPath);
1859
+ const fieldChanges = typeof mutation === "function" ? mutation(fieldAttrs) : mutation;
1860
+ (0, import_merge3.default)((0, import_get4.default)(schema.properties, fieldPath), {
1861
+ ...fieldAttrs,
1862
+ ...standardizeAttrs(fieldChanges)
1863
+ });
1864
+ if (fieldChanges.properties) {
1865
+ rewriteFields((0, import_get4.default)(schema.properties, fieldPath), fieldChanges.properties);
1866
+ }
1867
+ });
1868
+ }
1869
+ function rewriteAllFields(schema, configCallback, context) {
1870
+ if (!configCallback)
1871
+ return null;
1872
+ const parentName = context?.parent;
1873
+ Object.entries(schema.properties).forEach(([fieldName, fieldAttrs]) => {
1874
+ const fullName = parentName ? `${parentName}.${fieldName}` : fieldName;
1875
+ (0, import_merge3.default)((0, import_get4.default)(schema.properties, fieldName), {
1876
+ ...fieldAttrs,
1877
+ ...configCallback(fullName, fieldAttrs)
1878
+ });
1879
+ if (fieldAttrs.properties) {
1880
+ rewriteAllFields(fieldAttrs, configCallback, {
1881
+ parent: fieldName
1882
+ });
1883
+ }
1884
+ });
1885
+ }
1886
+ function modify(originalSchema, config) {
1887
+ const schema = JSON.parse(JSON.stringify(originalSchema));
1888
+ rewriteFields(schema, config.fields);
1889
+ rewriteAllFields(schema, config.allFields);
1890
+ return schema;
1891
+ }
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2024 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.9.2-dev.20240518112325
5
- Generated: Sat, 18 May 2024 11:23:50 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.10.0-beta.0
5
+ Generated: Thu, 20 Jun 2024 10:37:49 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -1795,8 +1795,66 @@ function createHeadlessForm(jsonSchema, customConfig = {}) {
1795
1795
  };
1796
1796
  }
1797
1797
  }
1798
+
1799
+ // src/modify.js
1800
+ import get4 from "lodash/get";
1801
+ import merge3 from "lodash/merge";
1802
+ function shortToFullPath(path) {
1803
+ return path.replace(".", ".properties.");
1804
+ }
1805
+ function standardizeAttrs(attrs) {
1806
+ const { errorMessage, properties, ...rest } = attrs;
1807
+ return {
1808
+ ...rest,
1809
+ ...errorMessage ? { "x-jsf-errorMessage": errorMessage } : {}
1810
+ };
1811
+ }
1812
+ function rewriteFields(schema, fieldsConfig) {
1813
+ if (!fieldsConfig)
1814
+ return null;
1815
+ const fieldsToModify = Object.entries(fieldsConfig);
1816
+ fieldsToModify.forEach(([shortPath, mutation]) => {
1817
+ const fieldPath = shortToFullPath(shortPath);
1818
+ if (!get4(schema.properties, fieldPath)) {
1819
+ return;
1820
+ }
1821
+ const fieldAttrs = get4(schema.properties, fieldPath);
1822
+ const fieldChanges = typeof mutation === "function" ? mutation(fieldAttrs) : mutation;
1823
+ merge3(get4(schema.properties, fieldPath), {
1824
+ ...fieldAttrs,
1825
+ ...standardizeAttrs(fieldChanges)
1826
+ });
1827
+ if (fieldChanges.properties) {
1828
+ rewriteFields(get4(schema.properties, fieldPath), fieldChanges.properties);
1829
+ }
1830
+ });
1831
+ }
1832
+ function rewriteAllFields(schema, configCallback, context) {
1833
+ if (!configCallback)
1834
+ return null;
1835
+ const parentName = context?.parent;
1836
+ Object.entries(schema.properties).forEach(([fieldName, fieldAttrs]) => {
1837
+ const fullName = parentName ? `${parentName}.${fieldName}` : fieldName;
1838
+ merge3(get4(schema.properties, fieldName), {
1839
+ ...fieldAttrs,
1840
+ ...configCallback(fullName, fieldAttrs)
1841
+ });
1842
+ if (fieldAttrs.properties) {
1843
+ rewriteAllFields(fieldAttrs, configCallback, {
1844
+ parent: fieldName
1845
+ });
1846
+ }
1847
+ });
1848
+ }
1849
+ function modify(originalSchema, config) {
1850
+ const schema = JSON.parse(JSON.stringify(originalSchema));
1851
+ rewriteFields(schema, config.fields);
1852
+ rewriteAllFields(schema, config.allFields);
1853
+ return schema;
1854
+ }
1798
1855
  export {
1799
1856
  buildCompleteYupSchema,
1800
1857
  createHeadlessForm,
1858
+ modify,
1801
1859
  pickXKey
1802
1860
  };
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2024 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.9.2-dev.20240518112325
5
- Generated: Sat, 18 May 2024 11:23:50 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.10.0-beta.0
5
+ Generated: Thu, 20 Jun 2024 10:37:49 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -849,11 +849,11 @@ var require_baseGet = __commonJS({
849
849
  var require_get = __commonJS({
850
850
  "node_modules/lodash/get.js"(exports2, module2) {
851
851
  var baseGet2 = require_baseGet();
852
- function get5(object2, path, defaultValue) {
852
+ function get6(object2, path, defaultValue) {
853
853
  var result = object2 == null ? void 0 : baseGet2(object2, path);
854
854
  return result === void 0 ? defaultValue : result;
855
855
  }
856
- module2.exports = get5;
856
+ module2.exports = get6;
857
857
  }
858
858
  });
859
859
 
@@ -2891,7 +2891,7 @@ var require_hasIn = __commonJS({
2891
2891
  var require_baseMatchesProperty = __commonJS({
2892
2892
  "node_modules/lodash/_baseMatchesProperty.js"(exports2, module2) {
2893
2893
  var baseIsEqual2 = require_baseIsEqual();
2894
- var get5 = require_get();
2894
+ var get6 = require_get();
2895
2895
  var hasIn2 = require_hasIn();
2896
2896
  var isKey2 = require_isKey();
2897
2897
  var isStrictComparable2 = require_isStrictComparable();
@@ -2904,7 +2904,7 @@ var require_baseMatchesProperty = __commonJS({
2904
2904
  return matchesStrictComparable2(toKey2(path), srcValue);
2905
2905
  }
2906
2906
  return function(object2) {
2907
- var objValue = get5(object2, path);
2907
+ var objValue = get6(object2, path);
2908
2908
  return objValue === void 0 && objValue === srcValue ? hasIn2(object2, path) : baseIsEqual2(srcValue, objValue, COMPARE_PARTIAL_FLAG7 | COMPARE_UNORDERED_FLAG5);
2909
2909
  };
2910
2910
  }
@@ -3478,10 +3478,10 @@ var require_merge = __commonJS({
3478
3478
  "node_modules/lodash/merge.js"(exports2, module2) {
3479
3479
  var baseMerge = require_baseMerge();
3480
3480
  var createAssigner = require_createAssigner();
3481
- var merge3 = createAssigner(function(object2, source, srcIndex) {
3481
+ var merge4 = createAssigner(function(object2, source, srcIndex) {
3482
3482
  baseMerge(object2, source, srcIndex);
3483
3483
  });
3484
- module2.exports = merge3;
3484
+ module2.exports = merge4;
3485
3485
  }
3486
3486
  });
3487
3487
 
@@ -9418,7 +9418,7 @@ var RefSet = /* @__PURE__ */ function() {
9418
9418
  next.refs = new Map(this.refs);
9419
9419
  return next;
9420
9420
  };
9421
- _proto.merge = function merge3(newItems, removeItems) {
9421
+ _proto.merge = function merge4(newItems, removeItems) {
9422
9422
  var next = this.clone();
9423
9423
  newItems.list.forEach(function(value) {
9424
9424
  return next.add(value);
@@ -9436,7 +9436,7 @@ var RefSet = /* @__PURE__ */ function() {
9436
9436
  };
9437
9437
  _createClass(RefSet2, [{
9438
9438
  key: "size",
9439
- get: function get5() {
9439
+ get: function get6() {
9440
9440
  return this.list.size + this.refs.size;
9441
9441
  }
9442
9442
  }]);
@@ -13149,8 +13149,66 @@ function createHeadlessForm(jsonSchema, customConfig = {}) {
13149
13149
  };
13150
13150
  }
13151
13151
  }
13152
+
13153
+ // src/modify.js
13154
+ var import_get5 = __toESM(require_get());
13155
+ var import_merge3 = __toESM(require_merge());
13156
+ function shortToFullPath(path) {
13157
+ return path.replace(".", ".properties.");
13158
+ }
13159
+ function standardizeAttrs(attrs) {
13160
+ const { errorMessage, properties, ...rest } = attrs;
13161
+ return {
13162
+ ...rest,
13163
+ ...errorMessage ? { "x-jsf-errorMessage": errorMessage } : {}
13164
+ };
13165
+ }
13166
+ function rewriteFields(schema, fieldsConfig) {
13167
+ if (!fieldsConfig)
13168
+ return null;
13169
+ const fieldsToModify = Object.entries(fieldsConfig);
13170
+ fieldsToModify.forEach(([shortPath, mutation]) => {
13171
+ const fieldPath = shortToFullPath(shortPath);
13172
+ if (!(0, import_get5.default)(schema.properties, fieldPath)) {
13173
+ return;
13174
+ }
13175
+ const fieldAttrs = (0, import_get5.default)(schema.properties, fieldPath);
13176
+ const fieldChanges = typeof mutation === "function" ? mutation(fieldAttrs) : mutation;
13177
+ (0, import_merge3.default)((0, import_get5.default)(schema.properties, fieldPath), {
13178
+ ...fieldAttrs,
13179
+ ...standardizeAttrs(fieldChanges)
13180
+ });
13181
+ if (fieldChanges.properties) {
13182
+ rewriteFields((0, import_get5.default)(schema.properties, fieldPath), fieldChanges.properties);
13183
+ }
13184
+ });
13185
+ }
13186
+ function rewriteAllFields(schema, configCallback, context) {
13187
+ if (!configCallback)
13188
+ return null;
13189
+ const parentName = context?.parent;
13190
+ Object.entries(schema.properties).forEach(([fieldName, fieldAttrs]) => {
13191
+ const fullName = parentName ? `${parentName}.${fieldName}` : fieldName;
13192
+ (0, import_merge3.default)((0, import_get5.default)(schema.properties, fieldName), {
13193
+ ...fieldAttrs,
13194
+ ...configCallback(fullName, fieldAttrs)
13195
+ });
13196
+ if (fieldAttrs.properties) {
13197
+ rewriteAllFields(fieldAttrs, configCallback, {
13198
+ parent: fieldName
13199
+ });
13200
+ }
13201
+ });
13202
+ }
13203
+ function modify(originalSchema, config) {
13204
+ const schema = JSON.parse(JSON.stringify(originalSchema));
13205
+ rewriteFields(schema, config.fields);
13206
+ rewriteAllFields(schema, config.allFields);
13207
+ return schema;
13208
+ }
13152
13209
  export {
13153
13210
  buildCompleteYupSchema,
13154
13211
  createHeadlessForm,
13212
+ modify,
13155
13213
  pickXKey
13156
13214
  };
@@ -113,3 +113,28 @@ export function createHeadlessForm(
113
113
  jsonSchema: JSONSchemaObjectType,
114
114
  customConfig?: JSFConfig
115
115
  ): HeadlessFormOutput;
116
+
117
+ type MutationsConfig = {
118
+ /**
119
+ * An object with the list of fields to be mutated.
120
+ */
121
+ fields: Record<string, unknown>;
122
+ /**
123
+ * a callback function that applies a mutation to all the fields.
124
+ * @param fieldName
125
+ * @param fieldAttrs
126
+ * @returns
127
+ */
128
+ allFields: (fieldName: string, fieldAttrs: Record<string, unknown>) => Record<string, unknown>;
129
+ };
130
+
131
+ export function modify(
132
+ /**
133
+ * The original JSON schema to be modified.
134
+ */
135
+ originalSchema: JSONSchemaObjectType,
136
+ /**
137
+ * The configuration object containing the fields and allFields properties.
138
+ */
139
+ config?: MutationsConfig
140
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remoteoss/json-schema-form",
3
- "version": "0.9.2-dev.20240518112325",
3
+ "version": "0.10.0-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",
@@ -467,9 +467,9 @@ describe('createHeadlessForm', () => {
467
467
  const { fields, handleValidation } = createHeadlessForm(schemaInputTypeText);
468
468
 
469
469
  expect(fields[0]).toMatchObject({
470
- description: 'Your username (max 10 characters)',
471
- label: 'Username',
472
- name: 'username',
470
+ description: 'The number of your national identification (max 10 digits)',
471
+ label: 'ID number',
472
+ name: 'id_number',
473
473
  required: true,
474
474
  schema: expect.any(Object),
475
475
  inputType: 'text',
@@ -485,8 +485,8 @@ describe('createHeadlessForm', () => {
485
485
  expect(fieldValidator.isValidSync(1)).toBe(false);
486
486
  expect(fieldValidator.isValidSync(0)).toBe(false);
487
487
 
488
- expect(handleValidation({ username: 1 }).formErrors).toEqual({
489
- username: 'username must be a `string` type, but the final value was: `1`.',
488
+ expect(handleValidation({ id_number: 1 }).formErrors).toEqual({
489
+ id_number: 'id_number must be a `string` type, but the final value was: `1`.',
490
490
  });
491
491
 
492
492
  expect(() => fieldValidator.validateSync('')).toThrowError('Required field');
@@ -496,18 +496,20 @@ describe('createHeadlessForm', () => {
496
496
  const resultsWithRootDescription = createHeadlessForm(
497
497
  JSONSchemaBuilder()
498
498
  .addInput({
499
- username: mockTextInput,
499
+ id_number: mockTextInput,
500
500
  })
501
- .setRequiredFields(['username'])
501
+ .setRequiredFields(['id_number'])
502
502
  .build()
503
503
  );
504
504
 
505
- expect(resultsWithRootDescription.fields[0].description).toMatch(/your username/i);
505
+ expect(resultsWithRootDescription.fields[0].description).toMatch(
506
+ /the number of your national/i
507
+ );
506
508
 
507
509
  const resultsWithPresentationDescription = createHeadlessForm(
508
510
  JSONSchemaBuilder()
509
511
  .addInput({
510
- username: {
512
+ id_number: {
511
513
  ...mockTextInput,
512
514
  'x-jsf-presentation': {
513
515
  inputType: 'text',
@@ -517,7 +519,7 @@ describe('createHeadlessForm', () => {
517
519
  },
518
520
  },
519
521
  })
520
- .setRequiredFields(['username'])
522
+ .setRequiredFields(['id_number'])
521
523
  .build()
522
524
  );
523
525
 
@@ -530,18 +532,20 @@ describe('createHeadlessForm', () => {
530
532
  const resultsWithRootDescription = createHeadlessForm(
531
533
  JSONSchemaBuilder()
532
534
  .addInput({
533
- username: mockTextInputDeprecated,
535
+ id_number: mockTextInputDeprecated,
534
536
  })
535
- .setRequiredFields(['username'])
537
+ .setRequiredFields(['id_number'])
536
538
  .build()
537
539
  );
538
540
 
539
- expect(resultsWithRootDescription.fields[0].description).toMatch(/your username/i);
541
+ expect(resultsWithRootDescription.fields[0].description).toMatch(
542
+ /the number of your national/i
543
+ );
540
544
 
541
545
  const resultsWithPresentationDescription = createHeadlessForm(
542
546
  JSONSchemaBuilder()
543
547
  .addInput({
544
- username: {
548
+ id_number: {
545
549
  ...mockTextInputDeprecated,
546
550
  presentation: {
547
551
  inputType: 'text',
@@ -551,7 +555,7 @@ describe('createHeadlessForm', () => {
551
555
  },
552
556
  },
553
557
  })
554
- .setRequiredFields(['username'])
558
+ .setRequiredFields(['id_number'])
555
559
  .build()
556
560
  );
557
561
 
@@ -1557,9 +1561,9 @@ describe('createHeadlessForm', () => {
1557
1561
  required: false,
1558
1562
  fields: [
1559
1563
  {
1560
- description: 'Your username (max 10 characters)',
1561
- label: 'Username',
1562
- name: 'username',
1564
+ description: 'The number of your national identification (max 10 digits)',
1565
+ label: 'ID number',
1566
+ name: 'id_number',
1563
1567
  type: 'text',
1564
1568
  required: true,
1565
1569
  },
@@ -1604,9 +1608,9 @@ describe('createHeadlessForm', () => {
1604
1608
  required: false,
1605
1609
  fields: [
1606
1610
  {
1607
- description: 'Your username (max 10 characters)',
1608
- label: 'Username',
1609
- name: 'username',
1611
+ description: 'The number of your national identification (max 10 digits)',
1612
+ label: 'ID number',
1613
+ name: 'id_number',
1610
1614
  type: 'text',
1611
1615
  required: true,
1612
1616
  },
@@ -2014,12 +2018,12 @@ describe('createHeadlessForm', () => {
2014
2018
 
2015
2019
  // Assert the yupError shape is really a YupError
2016
2020
  expect(yupError).toEqual(expect.any(Error));
2017
- expect(yupError.inner[0].path).toBe('username');
2021
+ expect(yupError.inner[0].path).toBe('id_number');
2018
2022
  expect(yupError.inner[0].message).toBe('Required field');
2019
2023
 
2020
2024
  // Assert the converted YupError to formErrors
2021
2025
  expect(formErrors).toEqual({
2022
- username: 'Required field',
2026
+ id_number: 'Required field',
2023
2027
  });
2024
2028
  });
2025
2029
  });
@@ -2808,7 +2812,7 @@ describe('createHeadlessForm', () => {
2808
2812
  validateForm({
2809
2813
  validate_tabs: 'no',
2810
2814
  a_fieldset: {
2811
- username: 'abc',
2815
+ id_number: '123',
2812
2816
  },
2813
2817
  mandatory_group_array: 'no',
2814
2818
  })
@@ -2823,7 +2827,7 @@ describe('createHeadlessForm', () => {
2823
2827
  validateForm({
2824
2828
  validate_tabs: 'yes',
2825
2829
  a_fieldset: {
2826
- username: 'abc',
2830
+ id_number: '123',
2827
2831
  },
2828
2832
  mandatory_group_array: 'no',
2829
2833
  })
@@ -2839,7 +2843,7 @@ describe('createHeadlessForm', () => {
2839
2843
  validateForm({
2840
2844
  validate_tabs: 'yes',
2841
2845
  a_fieldset: {
2842
- username: 'abc',
2846
+ id_number: '123',
2843
2847
  },
2844
2848
  mandatory_group_array: 'yes',
2845
2849
  a_group_array: [{ full_name: 'adfs' }],
@@ -2850,7 +2854,7 @@ describe('createHeadlessForm', () => {
2850
2854
  validateForm({
2851
2855
  validate_tabs: 'yes',
2852
2856
  a_fieldset: {
2853
- username: 'abc',
2857
+ id_number: '123',
2854
2858
  tabs: 2,
2855
2859
  },
2856
2860
  mandatory_group_array: 'no',
@@ -2939,18 +2943,18 @@ describe('createHeadlessForm', () => {
2939
2943
 
2940
2944
  expect(
2941
2945
  validateForm({
2942
- validate_fieldset: ['username'],
2946
+ validate_fieldset: ['id_number'],
2943
2947
  a_fieldset: {
2944
- username: 'abc',
2948
+ id_number: '123',
2945
2949
  },
2946
2950
  })
2947
2951
  ).toBeUndefined();
2948
2952
 
2949
2953
  expect(
2950
2954
  validateForm({
2951
- validate_fieldset: ['username', 'all'],
2955
+ validate_fieldset: ['id_number', 'all'],
2952
2956
  a_fieldset: {
2953
- username: 'abc',
2957
+ id_number: '123',
2954
2958
  },
2955
2959
  })
2956
2960
  ).toEqual({
@@ -2961,9 +2965,9 @@ describe('createHeadlessForm', () => {
2961
2965
 
2962
2966
  expect(
2963
2967
  validateForm({
2964
- validate_fieldset: ['username', 'all'],
2968
+ validate_fieldset: ['id_number', 'all'],
2965
2969
  a_fieldset: {
2966
- username: 'abc',
2970
+ id_number: '123',
2967
2971
  tabs: 2,
2968
2972
  },
2969
2973
  })
@@ -2976,18 +2980,18 @@ describe('createHeadlessForm', () => {
2976
2980
 
2977
2981
  expect(
2978
2982
  validateForm({
2979
- validate_fieldset: ['username'],
2983
+ validate_fieldset: ['id_number'],
2980
2984
  a_fieldset: {
2981
- username: 'abc',
2985
+ id_number: '123',
2982
2986
  },
2983
2987
  })
2984
2988
  ).toBeUndefined();
2985
2989
 
2986
2990
  expect(
2987
2991
  validateForm({
2988
- validate_fieldset: ['username', 'all'],
2992
+ validate_fieldset: ['id_number', 'all'],
2989
2993
  a_fieldset: {
2990
- username: 'abc',
2994
+ id_number: '123',
2991
2995
  },
2992
2996
  })
2993
2997
  ).toEqual({
@@ -2998,9 +3002,9 @@ describe('createHeadlessForm', () => {
2998
3002
 
2999
3003
  expect(
3000
3004
  validateForm({
3001
- validate_fieldset: ['username', 'all'],
3005
+ validate_fieldset: ['id_number', 'all'],
3002
3006
  a_fieldset: {
3003
- username: 'abc',
3007
+ id_number: '123',
3004
3008
  tabs: 2,
3005
3009
  },
3006
3010
  })
@@ -3580,7 +3584,7 @@ describe('createHeadlessForm', () => {
3580
3584
 
3581
3585
  // It returns fields without errors
3582
3586
  expect(result.fields).toBeDefined();
3583
- expect(result.fields[0].fields[0].name).toBe('username');
3587
+ expect(result.fields[0].fields[0].name).toBe('id_number');
3584
3588
  expect(result.fields[0].fields[1].name).toBe('tabs');
3585
3589
 
3586
3590
  // Warn about those missmatched values
@@ -3723,14 +3727,14 @@ describe('createHeadlessForm', () => {
3723
3727
  id_number: { 'data-field': 'field' },
3724
3728
  fieldset: {
3725
3729
  customProperties: {
3726
- username: { 'data-fieldset': 'fieldset' },
3730
+ id_number: { 'data-fieldset': 'fieldset' },
3727
3731
  },
3728
3732
  },
3729
3733
  nestedFieldset: {
3730
3734
  customProperties: {
3731
3735
  innerFieldset: {
3732
3736
  customProperties: {
3733
- username: { 'data-nested-fieldset': 'nested-fieldset' },
3737
+ id_number: { 'data-nested-fieldset': 'nested-fieldset' },
3734
3738
  },
3735
3739
  },
3736
3740
  },
@@ -3749,7 +3753,7 @@ describe('createHeadlessForm', () => {
3749
3753
  name: 'fieldset',
3750
3754
  fields: [
3751
3755
  {
3752
- name: 'username',
3756
+ name: 'id_number',
3753
3757
  'data-fieldset': 'fieldset',
3754
3758
  },
3755
3759
  {
@@ -3764,7 +3768,7 @@ describe('createHeadlessForm', () => {
3764
3768
  name: 'innerFieldset',
3765
3769
  fields: [
3766
3770
  {
3767
- name: 'username',
3771
+ name: 'id_number',
3768
3772
  'data-nested-fieldset': 'nested-fieldset',
3769
3773
  },
3770
3774
  {
@@ -3786,8 +3790,8 @@ describe('createHeadlessForm', () => {
3786
3790
  expect(fieldResult).not.toHaveProperty('data-fieldset');
3787
3791
  expect(fieldResult).not.toHaveProperty('data-nested-fieldset');
3788
3792
 
3789
- // $.fieldset.username
3790
- expect(fildsetResult.fields[0]).toHaveProperty('name', 'username');
3793
+ // $.fieldset.id_number
3794
+ expect(fildsetResult.fields[0]).toHaveProperty('name', 'id_number');
3791
3795
  expect(fildsetResult.fields[0]).toHaveProperty('data-fieldset', 'fieldset');
3792
3796
  expect(fildsetResult.fields[0]).not.toHaveProperty('data-field');
3793
3797
  expect(fildsetResult.fields[0]).not.toHaveProperty('data-nested-fieldset');
@@ -3795,7 +3799,7 @@ describe('createHeadlessForm', () => {
3795
3799
  expect(fildsetResult.fields[1]).not.toHaveProperty('data-nested-fieldset');
3796
3800
 
3797
3801
  // $.nestedFieldset.innerFieldset.id_number
3798
- expect(nestedFieldsetResult.fields[0].fields[0]).toHaveProperty('name', 'username');
3802
+ expect(nestedFieldsetResult.fields[0].fields[0]).toHaveProperty('name', 'id_number');
3799
3803
  expect(nestedFieldsetResult.fields[0].fields[0]).toHaveProperty(
3800
3804
  'data-nested-fieldset',
3801
3805
  'nested-fieldset'
@@ -3,8 +3,8 @@
3
3
  // -------------------------------------
4
4
 
5
5
  export const mockTextInput = {
6
- title: 'Username',
7
- description: 'Your username (max 10 characters)',
6
+ title: 'ID number',
7
+ description: 'The number of your national identification (max 10 digits)',
8
8
  maxLength: 10,
9
9
  'x-jsf-presentation': {
10
10
  inputType: 'text',
@@ -14,8 +14,8 @@ export const mockTextInput = {
14
14
  };
15
15
 
16
16
  export const mockTextInputDeprecated = {
17
- title: 'Username',
18
- description: 'Your username (max 10 characters)',
17
+ title: 'ID number',
18
+ description: 'The number of your national identification (max 10 digits)',
19
19
  maxLength: 10,
20
20
  presentation: {
21
21
  inputType: 'text',
@@ -313,10 +313,10 @@ export const mockFieldset = {
313
313
  inputType: 'fieldset',
314
314
  },
315
315
  properties: {
316
- username: mockTextInput,
316
+ id_number: mockTextInput,
317
317
  tabs: mockNumberInput,
318
318
  },
319
- required: ['username'],
319
+ required: ['id_number'],
320
320
  type: 'object',
321
321
  };
322
322
 
@@ -328,10 +328,10 @@ export const mockFocusedFieldset = {
328
328
  variant: 'focused',
329
329
  },
330
330
  properties: {
331
- username: mockTextInput,
331
+ id_number: mockTextInput,
332
332
  tabs: mockNumberInput,
333
333
  },
334
- required: ['username'],
334
+ required: ['id_number'],
335
335
  type: 'object',
336
336
  };
337
337
 
@@ -501,7 +501,7 @@ export const mockTelWithPattern = {
501
501
  * @returns {Object} A JSON schema
502
502
  * @example
503
503
  * JSONSchemaBuilder().addInput({
504
- username: mockTextInput,
504
+ id_number: mockTextInput,
505
505
  })
506
506
  .build();
507
507
  */
@@ -708,9 +708,9 @@ export const schemaWithoutTypes = {
708
708
 
709
709
  export const schemaInputTypeText = {
710
710
  properties: {
711
- username: mockTextInput,
711
+ id_number: mockTextInput,
712
712
  },
713
- required: ['username'],
713
+ required: ['id_number'],
714
714
  };
715
715
 
716
716
  export const schemaInputWithStatement = {
@@ -1292,7 +1292,7 @@ export const schemaDynamicValidationConst = {
1292
1292
  then: {
1293
1293
  properties: {
1294
1294
  a_fieldset: {
1295
- required: ['username', 'tabs'],
1295
+ required: ['id_number', 'tabs'],
1296
1296
  },
1297
1297
  },
1298
1298
  },
@@ -1369,7 +1369,7 @@ export const schemaDynamicValidationContains = JSONSchemaBuilder()
1369
1369
  type: 'array',
1370
1370
  description: 'Select what fieldset fields are required',
1371
1371
  items: {
1372
- enum: ['all', 'username'],
1372
+ enum: ['all', 'id_number'],
1373
1373
  },
1374
1374
  'x-jsf-presentation': {
1375
1375
  inputType: 'select',
@@ -1379,8 +1379,8 @@ export const schemaDynamicValidationContains = JSONSchemaBuilder()
1379
1379
  value: 'all',
1380
1380
  },
1381
1381
  {
1382
- label: 'Username',
1383
- value: 'username',
1382
+ label: 'ID Number',
1383
+ value: 'id_number',
1384
1384
  },
1385
1385
  ],
1386
1386
  placeholder: 'Select...',
@@ -1401,7 +1401,7 @@ export const schemaDynamicValidationContains = JSONSchemaBuilder()
1401
1401
  {
1402
1402
  properties: {
1403
1403
  a_fieldset: {
1404
- required: ['username', 'tabs'],
1404
+ required: ['id_number', 'tabs'],
1405
1405
  },
1406
1406
  },
1407
1407
  }
@@ -0,0 +1,300 @@
1
+ import { modify } from '../modify';
2
+
3
+ const schemaPet = {
4
+ type: 'object',
5
+ additionalProperties: false,
6
+ properties: {
7
+ has_pet: {
8
+ title: 'Has Pet',
9
+ description: 'Do you have a pet?',
10
+ oneOf: [
11
+ {
12
+ title: 'Yes',
13
+ const: 'yes',
14
+ },
15
+ {
16
+ title: 'No',
17
+ const: 'no',
18
+ },
19
+ ],
20
+ 'x-jsf-presentation': {
21
+ inputType: 'radio',
22
+ },
23
+ type: 'string',
24
+ },
25
+ pet_name: {
26
+ title: "Pet's name",
27
+ description: "What's your pet's name?",
28
+ 'x-jsf-presentation': {
29
+ inputType: 'text',
30
+ },
31
+ type: 'string',
32
+ },
33
+ pet_age: {
34
+ title: "Pet's age in months",
35
+ maximum: 24,
36
+ 'x-jsf-presentation': {
37
+ inputType: 'number',
38
+ },
39
+ 'x-jsf-errorMessage': {
40
+ maximum: 'Your pet cannot be older than 24 months.',
41
+ },
42
+ type: 'integer',
43
+ },
44
+ pet_fat: {
45
+ title: 'Pet fat percentage',
46
+ 'x-jsf-presentation': {
47
+ inputType: 'number',
48
+ percentage: true,
49
+ },
50
+ type: 'integer',
51
+ },
52
+ pet_address: {
53
+ properties: {
54
+ street: {
55
+ title: 'Street',
56
+ },
57
+ },
58
+ },
59
+ },
60
+ required: ['has_pet'],
61
+ 'x-jsf-order': ['has_pet', 'pet_name'],
62
+ allOf: [
63
+ {
64
+ id: 'pet_conditional_id',
65
+ if: {
66
+ properties: {
67
+ has_pet: {
68
+ const: 'yes',
69
+ },
70
+ },
71
+ required: ['has_pet'],
72
+ },
73
+ then: {
74
+ required: ['pet_name', 'pet_age', 'pet_fat'],
75
+ },
76
+ else: {
77
+ properties: {
78
+ pet_name: false,
79
+ pet_age: false,
80
+ pet_fat: false,
81
+ },
82
+ },
83
+ },
84
+ ],
85
+ };
86
+
87
+ const schemaAddress = {
88
+ properties: {
89
+ address: {
90
+ properties: {
91
+ street: {
92
+ title: 'Street',
93
+ },
94
+ number: {
95
+ title: 'Number',
96
+ },
97
+ city: {
98
+ title: 'City',
99
+ },
100
+ },
101
+ },
102
+ },
103
+ };
104
+
105
+ describe('modify() - basic mutations', () => {
106
+ it('replace base field', () => {
107
+ const result = modify(schemaPet, {
108
+ fields: {
109
+ pet_name: {
110
+ title: 'Your pet name',
111
+ },
112
+ has_pet: (fieldAttrs) => {
113
+ const options = fieldAttrs.oneOf?.map(({ title }) => title).join(' or ') || '';
114
+ return {
115
+ title: 'Pet owner',
116
+ description: `Do you own a pet? ${options}?`, // "Do you own a pet? Yes or No?"
117
+ };
118
+ },
119
+ },
120
+ });
121
+
122
+ expect(result).toMatchObject({
123
+ properties: {
124
+ pet_name: {
125
+ title: 'Your pet name',
126
+ },
127
+ has_pet: {
128
+ title: 'Pet owner',
129
+ description: 'Do you own a pet? Yes or No?',
130
+ },
131
+ },
132
+ });
133
+ });
134
+
135
+ it('replace nested field', () => {
136
+ const result = modify(schemaAddress, {
137
+ fields: {
138
+ 'address.street': {
139
+ title: 'Street name',
140
+ },
141
+ 'address.city': () => ({
142
+ title: 'City name',
143
+ }),
144
+ address: () => {
145
+ return {
146
+ properties: {
147
+ number: { title: 'Door number' },
148
+ },
149
+ };
150
+ },
151
+ // TODO: write test to nested field
152
+ },
153
+ });
154
+
155
+ expect(result).toMatchObject({
156
+ properties: {
157
+ address: {
158
+ properties: {
159
+ street: {
160
+ title: 'Street name',
161
+ },
162
+ number: {
163
+ title: 'Door number',
164
+ },
165
+ city: {
166
+ title: 'City name',
167
+ },
168
+ },
169
+ },
170
+ },
171
+ });
172
+ });
173
+
174
+ it('replace all fields', () => {
175
+ const result = modify(schemaPet, {
176
+ allFields: (fieldName, fieldAttrs) => {
177
+ const { inputType, percentage } = fieldAttrs?.['x-jsf-presentation'] || {};
178
+
179
+ if (inputType === 'number' && percentage === true) {
180
+ return {
181
+ styleDecimals: 2,
182
+ };
183
+ }
184
+
185
+ return {
186
+ dataFoo: 'abc',
187
+ };
188
+ },
189
+ });
190
+
191
+ expect(result).toMatchObject({
192
+ properties: {
193
+ has_pet: {
194
+ dataFoo: 'abc',
195
+ },
196
+ pet_name: {
197
+ dataFoo: 'abc',
198
+ },
199
+ pet_age: {
200
+ dataFoo: 'abc',
201
+ },
202
+ pet_fat: {
203
+ styleDecimals: 2,
204
+ },
205
+ pet_address: {
206
+ properties: {
207
+ street: {
208
+ dataFoo: 'abc',
209
+ },
210
+ },
211
+ },
212
+ },
213
+ });
214
+ });
215
+
216
+ it('replace field options (radio/select)', () => {
217
+ const result = modify(schemaPet, {
218
+ fields: {
219
+ has_pet: (fieldAttrs) => {
220
+ const labelsMap = {
221
+ yes: 'Yes, I have',
222
+ };
223
+
224
+ return {
225
+ oneOf: fieldAttrs.oneOf.map((option) => {
226
+ const customTitle = labelsMap[option.const];
227
+ if (!customTitle) {
228
+ // TODO - test this
229
+ // console.error('The option is not handled.');
230
+ return option;
231
+ }
232
+ return {
233
+ ...option,
234
+ title: customTitle,
235
+ };
236
+ }),
237
+ };
238
+ },
239
+ },
240
+ });
241
+
242
+ expect(result).toMatchObject({
243
+ properties: {
244
+ has_pet: {
245
+ oneOf: [
246
+ {
247
+ title: 'Yes, I have',
248
+ const: 'yes',
249
+ },
250
+ {
251
+ title: 'No',
252
+ const: 'no',
253
+ },
254
+ ],
255
+ },
256
+ },
257
+ });
258
+ });
259
+
260
+ it('error message', () => {
261
+ const result = modify(schemaPet, {
262
+ fields: {
263
+ pet_age: (fieldAttrs) => {
264
+ return {
265
+ errorMessage: {
266
+ minimum: `We only accept pets up to ${fieldAttrs.maximum} months old.`,
267
+ required: 'We need to know your pet name.',
268
+ },
269
+ };
270
+ },
271
+ 'pet_address.street': {
272
+ errorMessage: {
273
+ required: 'Your pet cannot live in the street.',
274
+ },
275
+ },
276
+ },
277
+ // ...
278
+ });
279
+
280
+ expect(result).toMatchObject({
281
+ properties: {
282
+ pet_age: {
283
+ 'x-jsf-errorMessage': {
284
+ minimum: `We only accept pets up to 24 months old.`,
285
+ required: 'We need to know your pet name.',
286
+ },
287
+ },
288
+ pet_address: {
289
+ properties: {
290
+ street: {
291
+ 'x-jsf-errorMessage': {
292
+ required: 'Your pet cannot live in the street.',
293
+ },
294
+ },
295
+ },
296
+ },
297
+ },
298
+ });
299
+ });
300
+ });