@ukhomeoffice/cop-react-form-renderer 4.68.1 → 4.69.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.
@@ -4,13 +4,15 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _optionIsSelected = _interopRequireDefault(require("../../../utils/Component/optionIsSelected"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
9
  function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
8
10
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
9
11
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
10
12
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
13
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
12
14
  function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
13
- var parentComponents = ['radios'];
15
+ var parentComponents = ['radios', 'checkboxes'];
14
16
  var cleanHiddenNestedData = function cleanHiddenNestedData(patch, page) {
15
17
  page.components.forEach(function (component) {
16
18
  if (!parentComponents.includes(component.type)) {
@@ -22,10 +24,12 @@ var cleanHiddenNestedData = function cleanHiddenNestedData(patch, page) {
22
24
  });
23
25
  });
24
26
  if (page.collection && patch[page.collection.name]) {
27
+ var _page$formData;
28
+ var activeId = patch["".concat(page.collection.name, "ActiveId")] || ((_page$formData = page.formData) === null || _page$formData === void 0 ? void 0 : _page$formData["".concat(page.collection.name, "ActiveId")]);
25
29
  patch[page.collection.name] = patch[page.collection.name].map(function (entry) {
26
- return cleanHiddenNestedData(entry, _objectSpread(_objectSpread({}, page), {}, {
30
+ return entry.id === activeId ? cleanHiddenNestedData(entry, _objectSpread(_objectSpread({}, page), {}, {
27
31
  collection: undefined
28
- }));
32
+ })) : entry;
29
33
  });
30
34
  }
31
35
  return patch;
@@ -34,7 +38,7 @@ function getIdsToDelete(component, selectedValue) {
34
38
  var _component$data, _component$data$optio;
35
39
  var idsToDelete = [];
36
40
  component === null || component === void 0 ? void 0 : (_component$data = component.data) === null || _component$data === void 0 ? void 0 : (_component$data$optio = _component$data.options) === null || _component$data$optio === void 0 ? void 0 : _component$data$optio.forEach(function (option) {
37
- if (option.value !== selectedValue && option.nested) {
41
+ if (!(0, _optionIsSelected.default)(selectedValue, option) && option.nested) {
38
42
  option.nested.forEach(function (nested) {
39
43
  idsToDelete.push(nested.id);
40
44
  });
@@ -8,13 +8,13 @@ describe('components', function () {
8
8
  describe('FormRenderer', function () {
9
9
  describe('helpers', function () {
10
10
  describe('cleanHiddenNestedData', function () {
11
- it('remove data corresponding to hidden nested components', function () {
12
- var patch = {
11
+ it('should remove data corresponding to hidden nested components in radios', function () {
12
+ var patchRadios = {
13
13
  parent: 'option2',
14
14
  nested1: 'should not be included',
15
15
  nested2: 'should be included'
16
16
  };
17
- var page = {
17
+ var pageRadios = {
18
18
  id: 'page',
19
19
  name: 'page',
20
20
  title: 'Page',
@@ -39,17 +39,55 @@ describe('components', function () {
39
39
  }
40
40
  }]
41
41
  };
42
- var updatedPatch = (0, _cleanHiddenNestedData.default)(patch, page);
43
- expect(updatedPatch['nested1']).toBeFalsy();
44
- expect(updatedPatch['nested2']).toBeTruthy();
42
+ var updatedPatchRadios = (0, _cleanHiddenNestedData.default)(patchRadios, pageRadios);
43
+ expect(updatedPatchRadios['nested1']).toBeFalsy();
44
+ expect(updatedPatchRadios['nested2']).toBeTruthy();
45
45
  });
46
- it('remove data corresponding to hidden nested components within a collection', function () {
46
+ it('should remove data corresponding to hidden nested components in checkboxes', function () {
47
+ var patchCheckboxes = {
48
+ parent: ['option2'],
49
+ nested1: 'should not be included',
50
+ nested2: 'should be included'
51
+ };
52
+ var pageCheckboxes = {
53
+ id: 'page',
54
+ name: 'page',
55
+ title: 'Page',
56
+ components: [{
57
+ id: 'parent',
58
+ fieldId: 'parent',
59
+ type: 'checkboxes',
60
+ data: {
61
+ options: [{
62
+ value: 'option1',
63
+ nested: [{
64
+ id: 'nested1',
65
+ fieldId: 'nested1'
66
+ }]
67
+ }, {
68
+ value: 'option2',
69
+ nested: [{
70
+ id: 'nested2',
71
+ fieldId: 'nested2'
72
+ }]
73
+ }]
74
+ }
75
+ }]
76
+ };
77
+ var updatedPatchCheckboxes = (0, _cleanHiddenNestedData.default)(patchCheckboxes, pageCheckboxes);
78
+ expect(updatedPatchCheckboxes['nested1']).toBeFalsy();
79
+ expect(updatedPatchCheckboxes['nested2']).toBeTruthy();
80
+ });
81
+ it('remove data corresponding to hidden nested components within the active collection entry', function () {
47
82
  var patch = {
83
+ collectionNameActiveId: '456',
48
84
  collectionName: [{
85
+ id: '123',
49
86
  parent: 'option1',
50
87
  nested1: 'should be included',
51
- nested2: 'should not be included'
88
+ nested2: 'should be included'
52
89
  }, {
90
+ id: '456',
53
91
  parent: 'option2',
54
92
  nested1: 'should not be included',
55
93
  nested2: 'should be included'
@@ -84,7 +122,7 @@ describe('components', function () {
84
122
  };
85
123
  var updatedPatch = (0, _cleanHiddenNestedData.default)(patch, page);
86
124
  expect(updatedPatch['collectionName'][0]['nested1']).toBeTruthy();
87
- expect(updatedPatch['collectionName'][0]['nested2']).toBeFalsy();
125
+ expect(updatedPatch['collectionName'][0]['nested2']).toBeTruthy();
88
126
  expect(updatedPatch['collectionName'][1]['nested1']).toBeFalsy();
89
127
  expect(updatedPatch['collectionName'][1]['nested2']).toBeTruthy();
90
128
  });
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _copReactComponents = require("@ukhomeoffice/cop-react-components");
8
8
  var _Component = _interopRequireDefault(require("../Component"));
9
+ var _optionIsSelected = _interopRequireDefault(require("../Component/optionIsSelected"));
9
10
  var _getCYAAction = _interopRequireDefault(require("./getCYAAction"));
10
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
12
  // Global imports
@@ -43,7 +44,7 @@ var setNestedValue = function setNestedValue(component, page) {
43
44
  var _component$data, _component$data$optio;
44
45
  (_component$data = component.data) === null || _component$data === void 0 ? void 0 : (_component$data$optio = _component$data.options) === null || _component$data$optio === void 0 ? void 0 : _component$data$optio.forEach(function (option) {
45
46
  //check if option is selected and has nested component
46
- if (Array.isArray(option.nested) && page.formData[component.id] === option.value) {
47
+ if (Array.isArray(option.nested) && (0, _optionIsSelected.default)(page.formData[component.id], option)) {
47
48
  option.nested.forEach(function (child) {
48
49
  child.value = page.formData[child.id];
49
50
  });
@@ -134,7 +134,7 @@ describe('utils', function () {
134
134
  onAction: ON_ACTION
135
135
  });
136
136
  });
137
- it('should update any nested components with corresponding values from the stored formdata', function () {
137
+ it('should update any nested components in radios with corresponding values from the stored formdata', function () {
138
138
  var SELECTED_VALUE = 'selectedValue';
139
139
  var NESTED_ID = 'nestedId';
140
140
  var NESTED_VALUE = 'nestedValue';
@@ -161,7 +161,7 @@ describe('utils', function () {
161
161
  var ROW = (0, _getCYARow.default)(PAGE, COMPONENT, function () {});
162
162
  expect(ROW.component.data.options[0].nested[0].value).toEqual(NESTED_VALUE);
163
163
  });
164
- it('should handle an undefined formData when attempting to set nested values', function () {
164
+ it('should handle an undefined formData when attempting to set nested values in radios', function () {
165
165
  var SELECTED_VALUE = 'selectedValue';
166
166
  var NESTED_ID = 'nestedId';
167
167
  var PAGE = {
@@ -184,6 +184,56 @@ describe('utils', function () {
184
184
  var ROW = (0, _getCYARow.default)(PAGE, COMPONENT, function () {});
185
185
  expect(ROW.component.data.options[0].nested[0].value).toBeUndefined();
186
186
  });
187
+ it('should update any nested components in checkboxes with corresponding values from the stored formdata', function () {
188
+ var SELECTED_VALUE = 'selectedValue';
189
+ var NESTED_ID = 'nestedId';
190
+ var NESTED_VALUE = 'nestedValue';
191
+ var PAGE = {
192
+ id: 'page',
193
+ formData: _defineProperty({
194
+ a: [SELECTED_VALUE]
195
+ }, NESTED_ID, NESTED_VALUE),
196
+ cya_link: {}
197
+ };
198
+ var COMPONENT = {
199
+ type: 'checkboxes',
200
+ id: 'a',
201
+ fieldId: 'a',
202
+ data: {
203
+ options: [{
204
+ value: SELECTED_VALUE,
205
+ nested: [{
206
+ id: NESTED_ID
207
+ }]
208
+ }]
209
+ }
210
+ };
211
+ var ROW = (0, _getCYARow.default)(PAGE, COMPONENT, function () {});
212
+ expect(ROW.component.data.options[0].nested[0].value).toEqual(NESTED_VALUE);
213
+ });
214
+ it('should handle an undefined formData when attempting to set nested values in checkboxes', function () {
215
+ var SELECTED_VALUE = 'selectedValue';
216
+ var NESTED_ID = 'nestedId';
217
+ var PAGE = {
218
+ id: 'page',
219
+ cya_link: {}
220
+ };
221
+ var COMPONENT = {
222
+ type: 'checkboxes',
223
+ id: 'a',
224
+ fieldId: 'a',
225
+ data: {
226
+ options: [{
227
+ value: SELECTED_VALUE,
228
+ nested: [{
229
+ id: NESTED_ID
230
+ }]
231
+ }]
232
+ }
233
+ };
234
+ var ROW = (0, _getCYARow.default)(PAGE, COMPONENT, function () {});
235
+ expect(ROW.component.data.options[0].nested[0].value).toBeUndefined();
236
+ });
187
237
  it('should get an appropriate row for a readonly text component with no value and interpolated label', function () {
188
238
  var PAGE = {
189
239
  id: 'page',
@@ -51,6 +51,12 @@ var getCheckboxes = function getCheckboxes(config) {
51
51
  _Data.default.getOptions(config, function (val) {
52
52
  options = val;
53
53
  });
54
+ options.forEach(function (option) {
55
+ if (!Array.isArray(option.nested)) {
56
+ return;
57
+ }
58
+ option.children = getChildrenJsx(config, option.nested);
59
+ });
54
60
  var attrs = (0, _cleanAttributes.default)(config);
55
61
  return /*#__PURE__*/_react.default.createElement(_copReactComponents.Checkboxes, _extends({}, attrs, {
56
62
  options: options
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ /**
8
+ * Checks whether an option for a component has been selected.
9
+ *
10
+ * @param {object} componentValue The option's value selected for that component.
11
+ * @param {object} option The option of the component being tested.
12
+ *
13
+ * @returns A boolean of whether the option is selected.
14
+ */
15
+ var optionIsSelected = function optionIsSelected(componentValue, option) {
16
+ if (Array.isArray(componentValue)) {
17
+ return componentValue.includes(option.value);
18
+ }
19
+ return componentValue === option.value;
20
+ };
21
+ var _default = optionIsSelected;
22
+ exports.default = _default;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ var _optionIsSelected = _interopRequireDefault(require("./optionIsSelected"));
4
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
5
+ // Local imports
6
+
7
+ describe('utils.Component.isSelected', function () {
8
+ var SELECTED_VALUE = 'selectedValue';
9
+ var NOT_SELECTED_VALUE = 'notSelectedValue';
10
+ var OPTIONS = [{
11
+ value: SELECTED_VALUE
12
+ }, {
13
+ value: NOT_SELECTED_VALUE
14
+ }];
15
+ var COMPONENT = {
16
+ id: 'a',
17
+ fieldId: 'a',
18
+ data: {
19
+ options: OPTIONS
20
+ }
21
+ };
22
+ it('should properly identify which option is selected for checkboxes', function () {
23
+ var PAGE = {
24
+ formData: {
25
+ a: [SELECTED_VALUE]
26
+ }
27
+ };
28
+ COMPONENT.type = 'checkboxes';
29
+ expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[0])).toEqual(true);
30
+ expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[1])).toEqual(false);
31
+ });
32
+ it('should properly identify which option is selected for radios', function () {
33
+ var PAGE = {
34
+ formData: {
35
+ a: SELECTED_VALUE
36
+ }
37
+ };
38
+ COMPONENT.type = 'radios';
39
+ expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[0])).toEqual(true);
40
+ expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[1])).toEqual(false);
41
+ });
42
+ });
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
  var _models = require("../../models");
8
+ var _optionIsSelected = _interopRequireDefault(require("../Component/optionIsSelected"));
8
9
  var _showComponent = _interopRequireDefault(require("../Component/showComponent"));
9
10
  var _additional = _interopRequireDefault(require("./additional"));
10
11
  var _validateCollection = _interopRequireDefault(require("./validateCollection"));
@@ -57,10 +58,11 @@ var validateComponent = function validateComponent(component, outerData, formDat
57
58
  properties = propsInError;
58
59
  error = message;
59
60
  break;
61
+ case _models.ComponentTypes.CHECKBOXES:
60
62
  case _models.ComponentTypes.RADIOS:
61
63
  var nestedErrors = [];
62
64
  (_component$data$optio = component.data.options) === null || _component$data$optio === void 0 ? void 0 : _component$data$optio.forEach(function (option) {
63
- if (option.nested && formData[component.id] === option.value) {
65
+ if (option.nested && (0, _optionIsSelected.default)(formData[component.id], option)) {
64
66
  nestedErrors = nestedErrors.concat((0, _validateContainer.default)({
65
67
  components: option.nested
66
68
  }, formData));
@@ -245,5 +245,121 @@ describe('utils.Validate.Component', function () {
245
245
  };
246
246
  expect((0, _validateComponent.default)(COMPONENT, undefined, {})).toBeUndefined();
247
247
  });
248
+ it('should return no error when the checkbox component contains nested components without errors', function () {
249
+ var NESTED_ID = 'nestedId';
250
+ var NESTED_VALUE = 'nestedValue';
251
+ var FORMDATA = _defineProperty({}, NESTED_ID, NESTED_VALUE);
252
+ var COMPONENT = {
253
+ type: 'checkboxes',
254
+ id: 'a',
255
+ data: {
256
+ options: [{
257
+ nested: [{
258
+ type: 'text',
259
+ fieldId: NESTED_ID,
260
+ id: NESTED_ID,
261
+ required: true
262
+ }]
263
+ }]
264
+ }
265
+ };
266
+ expect((0, _validateComponent.default)(COMPONENT, undefined, FORMDATA)).toBeUndefined();
267
+ });
268
+ it('should return an error when the checkbox component contains nested components with errors', function () {
269
+ var NESTED_ID = 'nestedId';
270
+ var OPTION_VALUE = 'optionValue';
271
+ var FORMDATA = {
272
+ 'a': [OPTION_VALUE]
273
+ };
274
+ var COMPONENT = {
275
+ type: 'checkboxes',
276
+ id: 'a',
277
+ data: {
278
+ options: [{
279
+ value: OPTION_VALUE,
280
+ nested: [{
281
+ type: 'text',
282
+ fieldId: NESTED_ID,
283
+ id: NESTED_ID,
284
+ required: true
285
+ }]
286
+ }]
287
+ }
288
+ };
289
+ expect((0, _validateComponent.default)(COMPONENT, undefined, FORMDATA)).toEqual([{
290
+ id: NESTED_ID,
291
+ error: "Field is required"
292
+ }]);
293
+ });
294
+ it('should return no error when a non selected checkbox component contains nested components with errors', function () {
295
+ var NESTED_ID_NOT_SELECTED = 'nestedIdNotSelected';
296
+ var NESTED_ID_SELECTED = 'nestedIdSelected';
297
+ var NESTED_VALUE_SELECTED = 'nestedValueSelected';
298
+ var FORMDATA = _defineProperty({
299
+ 'a': ['optionValueSelected']
300
+ }, NESTED_ID_SELECTED, NESTED_VALUE_SELECTED);
301
+ var COMPONENT = {
302
+ type: 'checkboxes',
303
+ id: 'a',
304
+ data: {
305
+ options: [{
306
+ id: 'optionIdNotSelected',
307
+ value: 'optionValueNotSelected',
308
+ nested: [{
309
+ type: 'text',
310
+ fieldId: NESTED_ID_NOT_SELECTED,
311
+ id: NESTED_ID_NOT_SELECTED,
312
+ required: true
313
+ }]
314
+ }, {
315
+ id: 'optionIdSelected',
316
+ value: 'optionValueSelected',
317
+ nested: [{
318
+ type: 'text',
319
+ fieldId: NESTED_ID_SELECTED,
320
+ id: NESTED_ID_SELECTED,
321
+ required: true
322
+ }]
323
+ }]
324
+ }
325
+ };
326
+ expect((0, _validateComponent.default)(COMPONENT, undefined, FORMDATA)).toBeUndefined();
327
+ });
328
+ it('should return no error when all selected checkbox components contains nested components without errors', function () {
329
+ var _FORMDATA4;
330
+ var NESTED_ID_SELECTED_1 = 'nestedIdSelected1';
331
+ var NESTED_ID_SELECTED_2 = 'nestedIdSelected2';
332
+ var NESTED_VALUE_SELECTED_1 = 'nestedValueSelected1';
333
+ var NESTED_VALUE_SELECTED_2 = 'nestedValueSelected2';
334
+ var FORMDATA = (_FORMDATA4 = {
335
+ 'a': ['optionValueSelected1', 'optionValueSelected2']
336
+ }, _defineProperty(_FORMDATA4, NESTED_ID_SELECTED_1, NESTED_VALUE_SELECTED_1), _defineProperty(_FORMDATA4, NESTED_ID_SELECTED_2, NESTED_VALUE_SELECTED_2), _FORMDATA4);
337
+ var COMPONENT = {
338
+ type: 'checkboxes',
339
+ id: 'a',
340
+ data: {
341
+ options: [{
342
+ id: 'optionIdSelected1',
343
+ value: 'optionValueSelected1',
344
+ nested: [{
345
+ type: 'text',
346
+ fieldId: NESTED_ID_SELECTED_1,
347
+ id: NESTED_ID_SELECTED_1,
348
+ required: true
349
+ }]
350
+ }, {
351
+ id: 'optionIdSelected2',
352
+ value: 'optionValueSelected2',
353
+ nested: [{
354
+ type: 'text',
355
+ fieldId: NESTED_ID_SELECTED_2,
356
+ id: NESTED_ID_SELECTED_2,
357
+ required: true
358
+ }]
359
+ }]
360
+ }
361
+ };
362
+ expect((0, _validateComponent.default)(COMPONENT, undefined, FORMDATA)).toBeUndefined();
363
+ });
248
364
  });
249
365
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ukhomeoffice/cop-react-form-renderer",
3
- "version": "4.68.1",
3
+ "version": "4.69.0",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "clean": "rimraf dist",
@@ -16,7 +16,7 @@
16
16
  "post-compile": "rimraf dist/*.test.* dist/**/*.test.* dist/**/*.stories.* dist/docs dist/assets"
17
17
  },
18
18
  "dependencies": {
19
- "@ukhomeoffice/cop-react-components": "^2.12.0-alpha",
19
+ "@ukhomeoffice/cop-react-components": "^2.14.1",
20
20
  "axios": "^0.23.0",
21
21
  "dayjs": "^1.11.0",
22
22
  "govuk-frontend": "^4.3.1",