@ukhomeoffice/cop-react-form-renderer 4.13.1-alpha → 4.14.3

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.
@@ -120,6 +120,7 @@ var CollectionPage = function CollectionPage(_ref) {
120
120
  }),
121
121
  onAction: onInnerPageAction,
122
122
  onWrapperChange: onInnerPageChange,
123
+ onTopLevelChange: onPageChange,
123
124
  classBlock: classBlock,
124
125
  classModifiers: classModifiers,
125
126
  className: className
@@ -57,6 +57,7 @@ var Collection = function Collection(_ref) {
57
57
  _value = _ref.value,
58
58
  formData = _ref.formData,
59
59
  onChange = _ref.onChange,
60
+ onTopLevelChange = _ref.onTopLevelChange,
60
61
  wrap = _ref.wrap;
61
62
 
62
63
  var _useState = (0, _react.useState)(_value),
@@ -195,6 +196,7 @@ var Collection = function Collection(_ref) {
195
196
  value: item,
196
197
  formData: formData,
197
198
  onChange: onCollectionChange,
199
+ onTopLevelChange: onTopLevelChange,
198
200
  wrap: wrap
199
201
  }));
200
202
  }), !config.disableAddAndRemove && /*#__PURE__*/_react.default.createElement(_copReactComponents.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_copReactComponents.Button, {
@@ -15,7 +15,7 @@ var _utils = _interopRequireDefault(require("../../utils"));
15
15
 
16
16
  var _FormComponent = _interopRequireDefault(require("./FormComponent"));
17
17
 
18
- var _excluded = ["container", "value", "formData", "onChange", "wrap"];
18
+ var _excluded = ["container", "value", "formData", "onChange", "wrap", "onTopLevelChange"];
19
19
 
20
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
21
 
@@ -40,6 +40,7 @@ var Container = function Container(_ref) {
40
40
  formData = _ref.formData,
41
41
  onChange = _ref.onChange,
42
42
  wrap = _ref.wrap,
43
+ onTopLevelChange = _ref.onTopLevelChange,
43
44
  attrs = _objectWithoutProperties(_ref, _excluded);
44
45
 
45
46
  var onComponentChange = function onComponentChange(_ref2) {
@@ -88,7 +89,8 @@ var Container = function Container(_ref) {
88
89
  formData: formData,
89
90
  value: val || defaultValue,
90
91
  wrap: wrap,
91
- onChange: onComponentChange
92
+ onChange: onComponentChange,
93
+ onTopLevelChange: onTopLevelChange
92
94
  }));
93
95
  }));
94
96
  };
@@ -212,7 +212,7 @@ describe('components.FormComponent.Container', function () {
212
212
  }, _callee3);
213
213
  })));
214
214
  it('should handle a change to a file type component appropriately', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
215
- var FILE_ID, ON_CHANGE_EVENTS, ON_CHANGE, CONTAINER, _renderWithValidation4, container, c, formGroup, input, FILE_EXTENSION, FILE_NAME, FILE_TYPE, str, blob, FILE, containerChangeValue, metaChangeValue;
215
+ var FILE_ID, ON_CHANGE_EVENTS, ON_CHANGE, ON_TOP_LEVEL_CHANGE_EVENTS, ON_TOP_LEVEL_CHANGE, CONTAINER, _renderWithValidation4, container, c, formGroup, input, FILE_EXTENSION, FILE_NAME, FILE_TYPE, str, blob, FILE, containerChangeValue, metaChangeValue;
216
216
 
217
217
  return regeneratorRuntime.wrap(function _callee4$(_context4) {
218
218
  while (1) {
@@ -225,6 +225,12 @@ describe('components.FormComponent.Container', function () {
225
225
  ON_CHANGE_EVENTS.push(e);
226
226
  };
227
227
 
228
+ ON_TOP_LEVEL_CHANGE_EVENTS = [];
229
+
230
+ ON_TOP_LEVEL_CHANGE = function ON_TOP_LEVEL_CHANGE(e) {
231
+ ON_TOP_LEVEL_CHANGE_EVENTS.push(e);
232
+ };
233
+
228
234
  CONTAINER = {
229
235
  id: ID,
230
236
  fieldId: ID,
@@ -241,7 +247,8 @@ describe('components.FormComponent.Container', function () {
241
247
  component: CONTAINER,
242
248
  value: FORM_DATA[ID],
243
249
  formData: FORM_DATA,
244
- onChange: ON_CHANGE
250
+ onChange: ON_CHANGE,
251
+ onTopLevelChange: ON_TOP_LEVEL_CHANGE
245
252
  })), container = _renderWithValidation4.container; // Get hold of the text input.
246
253
 
247
254
  c = container.childNodes[0];
@@ -258,22 +265,25 @@ describe('components.FormComponent.Container', function () {
258
265
  type: FILE_TYPE
259
266
  });
260
267
 
261
- _userEvent.default.upload(input, FILE); // And confirm the formData has been changed.
268
+ _userEvent.default.upload(input, FILE); // Expect one call for the regular onChange event, this can change
269
+ // depending on whether the Container is on a normal page or regular page.
262
270
 
263
271
 
264
- expect(ON_CHANGE_EVENTS.length).toEqual(2); // One for the file, another for the meta.
272
+ expect(ON_CHANGE_EVENTS.length).toEqual(1);
273
+ expect(ON_CHANGE_EVENTS[0].target.name).toEqual(ID); // Expect one call for changing the meta data at top level formData.
274
+ // Meta changes should occur at top-level regardless of where the component is.
265
275
 
266
- expect(ON_CHANGE_EVENTS[0].target.name).toEqual(ID);
267
- expect(ON_CHANGE_EVENTS[1].target.name).toEqual(_constants.META_PROPERTY);
276
+ expect(ON_TOP_LEVEL_CHANGE_EVENTS.length).toEqual(1);
277
+ expect(ON_TOP_LEVEL_CHANGE_EVENTS[0].target.name).toEqual(_constants.META_PROPERTY);
268
278
  containerChangeValue = JSON.parse(JSON.stringify(ON_CHANGE_EVENTS[0].target.value));
269
- metaChangeValue = JSON.parse(JSON.stringify(ON_CHANGE_EVENTS[1].target.value));
279
+ metaChangeValue = JSON.parse(JSON.stringify(ON_TOP_LEVEL_CHANGE_EVENTS[0].target.value));
270
280
  expect(metaChangeValue.documents.length).toEqual(2); // Existing one, plus this new one.
271
281
 
272
282
  expect(metaChangeValue.documents[1]).toMatchObject(_objectSpread(_objectSpread({}, containerChangeValue[FILE_ID]), {}, {
273
283
  field: "".concat(ID, ".").concat(FILE_ID)
274
284
  }));
275
285
 
276
- case 22:
286
+ case 25:
277
287
  case "end":
278
288
  return _context4.stop();
279
289
  }
@@ -25,7 +25,7 @@ var _Container = _interopRequireDefault(require("./Container"));
25
25
 
26
26
  var _helpers = require("./helpers");
27
27
 
28
- var _excluded = ["component", "value", "formData", "wrap", "onChange"];
28
+ var _excluded = ["component", "value", "formData", "wrap", "onChange", "onTopLevelChange"];
29
29
 
30
30
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
31
31
 
@@ -63,6 +63,7 @@ var FormComponent = function FormComponent(_ref) {
63
63
  formData = _ref.formData,
64
64
  wrap = _ref.wrap,
65
65
  onChange = _ref.onChange,
66
+ onTopLevelChange = _ref.onTopLevelChange,
66
67
  attrs = _objectWithoutProperties(_ref, _excluded);
67
68
 
68
69
  var _useHooks = (0, _hooks.useHooks)(),
@@ -103,6 +104,7 @@ var FormComponent = function FormComponent(_ref) {
103
104
  container: component,
104
105
  wrap: wrap,
105
106
  onChange: onComponentChange,
107
+ onTopLevelChange: onTopLevelChange,
106
108
  value: value || _utils.default.Component.defaultValue(component),
107
109
  formData: formData
108
110
  }));
@@ -119,13 +121,14 @@ var FormComponent = function FormComponent(_ref) {
119
121
  config: component,
120
122
  wrap: wrap,
121
123
  onChange: onComponentChange,
124
+ onTopLevelChange: onTopLevelChange,
122
125
  value: value || _utils.default.Component.defaultValue(component),
123
126
  formData: formData
124
127
  }));
125
128
  }
126
129
 
127
130
  var changeMetaDocuments = function changeMetaDocuments(document) {
128
- onChange({
131
+ onTopLevelChange({
129
132
  target: {
130
133
  name: _utils.default.Meta.name,
131
134
  value: _utils.default.Meta.documents.setForField(document, formData, component.full_path)
@@ -174,7 +177,8 @@ FormComponent.propTypes = {
174
177
  value: _propTypes.default.any,
175
178
  formData: _propTypes.default.any,
176
179
  wrap: _propTypes.default.bool,
177
- onChange: _propTypes.default.func
180
+ onChange: _propTypes.default.func,
181
+ onTopLevelChange: _propTypes.default.func
178
182
  };
179
183
  FormComponent.defaultProps = {
180
184
  wrap: true
@@ -56,6 +56,7 @@ var FormPage = function FormPage(_ref) {
56
56
  var page = _ref.page,
57
57
  _onAction = _ref.onAction,
58
58
  onWrapperChange = _ref.onWrapperChange,
59
+ onTopLevelChange = _ref.onTopLevelChange,
59
60
  classBlock = _ref.classBlock,
60
61
  classModifiers = _ref.classModifiers,
61
62
  className = _ref.className;
@@ -102,6 +103,7 @@ var FormPage = function FormPage(_ref) {
102
103
  key: index,
103
104
  component: component,
104
105
  onChange: onWrapperChange || onPageChange,
106
+ onTopLevelChange: onTopLevelChange || onPageChange,
105
107
  value: page.formData[component.fieldId] || patch[component.fieldId],
106
108
  formData: page.formData
107
109
  });
@@ -7,6 +7,8 @@ exports.default = void 0;
7
7
 
8
8
  var _copReactComponents = require("@ukhomeoffice/cop-react-components");
9
9
 
10
+ var _elevateNestedComponents = _interopRequireDefault(require("../Component/elevateNestedComponents"));
11
+
10
12
  var _models = require("../../models");
11
13
 
12
14
  var _getCYARowsForContainer = _interopRequireDefault(require("./getCYARowsForContainer"));
@@ -24,13 +26,14 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
24
26
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
25
27
 
26
28
  var getContainerForPage = function getContainerForPage(page, item, labelCount, full_path) {
29
+ var allComponents = (0, _elevateNestedComponents.default)(page.components, item);
27
30
  return {
28
31
  id: item.id,
29
32
  fieldId: item.id,
30
33
  type: _models.ComponentTypes.CONTAINER,
31
34
  required: true,
32
35
  full_path: full_path,
33
- components: page.components.map(function (component) {
36
+ components: allComponents.map(function (component) {
34
37
  return _objectSpread(_objectSpread({}, component), {}, {
35
38
  label: _copReactComponents.Utils.interpolateString(component.label, _objectSpread(_objectSpread({}, item), {}, {
36
39
  index: labelCount
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
+ var _elevateNestedComponents = _interopRequireDefault(require("../Component/elevateNestedComponents"));
9
+
8
10
  var _models = require("../../models");
9
11
 
10
12
  var _FormPage = _interopRequireDefault(require("../FormPage"));
@@ -41,7 +43,8 @@ var getCYARowsForPage = function getCYARowsForPage(page, onAction) {
41
43
  return (0, _getCYARowsForCollectionPage.default)(page, onAction);
42
44
  }
43
45
 
44
- var rows = page.components.filter(function (c) {
46
+ var allComponents = (0, _elevateNestedComponents.default)(page.components, page.formData);
47
+ var rows = allComponents.filter(function (c) {
45
48
  return (0, _showComponentCYA.default)(c, page.formData);
46
49
  }).flatMap(function (component) {
47
50
  switch (component.type) {
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ /**
9
+ * Iterates over an array of components and brings any nested
10
+ * components that should be visible into the top level array.
11
+ * The values provided in data are used to determine if any
12
+ * nested components should be visible.
13
+ *
14
+ * Given this structure in the components array:
15
+ * - Radios
16
+ * - Radio Option 1 (Not selected)
17
+ * - Nested 1
18
+ * - Nested 2
19
+ * - Radio Option 2 (Selected)
20
+ * - Nested 3
21
+ * - Text Input
22
+ *
23
+ * The result will be the following array:
24
+ * - Radios
25
+ * - Nested 3
26
+ * - Text Input
27
+ *
28
+ * @param {*} components An array of components.
29
+ * @param {*} data A chunk of form data used to determine if
30
+ * any nested components are visible or not.
31
+ * @returns A new array consisting of components interspersed
32
+ * with any visible nested components.
33
+ */
34
+ var elevateNestedComponents = function elevateNestedComponents(components, data) {
35
+ var allComponents = [];
36
+ components === null || components === void 0 ? void 0 : components.forEach(function (component) {
37
+ var _component$data, _component$data$optio;
38
+
39
+ allComponents.push(component);
40
+ (_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) {
41
+ // If this option has nested components and is
42
+ // selected, then add its nested components to the array.
43
+ if (Array.isArray(option.nested) && data[component.id] === option.value) {
44
+ allComponents = allComponents.concat(option.nested);
45
+ }
46
+ });
47
+ });
48
+ return allComponents;
49
+ };
50
+
51
+ var _default = elevateNestedComponents;
52
+ exports.default = _default;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+
3
+ var _elevateNestedComponents = _interopRequireDefault(require("./elevateNestedComponents"));
4
+
5
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
+
7
+ describe('utils.Component.elevateNestedComponents', function () {
8
+ it('should return an empty array if components is undefined', function () {
9
+ var DATA = {
10
+ alpha: 'abc'
11
+ };
12
+ expect((0, _elevateNestedComponents.default)(undefined, DATA)).toEqual([]);
13
+ });
14
+ it('should return an empty array if components is null', function () {
15
+ var DATA = {
16
+ alpha: 'abc'
17
+ };
18
+ expect((0, _elevateNestedComponents.default)(null, DATA)).toEqual([]);
19
+ });
20
+ it('should return an empty array if components is empty', function () {
21
+ var DATA = {
22
+ alpha: 'abc'
23
+ };
24
+ expect((0, _elevateNestedComponents.default)([], DATA)).toEqual([]);
25
+ });
26
+ it('should return the original components if none have nested components', function () {
27
+ var COMPONENTS = [{
28
+ id: 'textComp'
29
+ }, {
30
+ id: 'radiosComp',
31
+ data: {
32
+ options: [{
33
+ label: 'Yes',
34
+ value: 'yes'
35
+ }, {
36
+ label: 'No',
37
+ value: 'no'
38
+ }]
39
+ }
40
+ }];
41
+ var DATA = {
42
+ alpha: 'abc'
43
+ };
44
+ expect((0, _elevateNestedComponents.default)(COMPONENTS, DATA)).toEqual(COMPONENTS);
45
+ });
46
+ it('should return the original components if data is null', function () {
47
+ var COMPONENTS = [{
48
+ id: 'textComp'
49
+ }, {
50
+ id: 'radiosComp',
51
+ data: {
52
+ options: [{
53
+ label: 'Yes',
54
+ value: 'yes'
55
+ }, {
56
+ label: 'No',
57
+ value: 'no'
58
+ }]
59
+ }
60
+ }];
61
+ expect((0, _elevateNestedComponents.default)(COMPONENTS, null)).toEqual(COMPONENTS);
62
+ });
63
+ it('should return the original array with elevated nested components when they are visible', function () {
64
+ var COMPONENTS = [{
65
+ id: 'textComp'
66
+ }, {
67
+ id: 'radiosComp',
68
+ data: {
69
+ options: [{
70
+ label: 'Yes',
71
+ value: 'yes',
72
+ nested: [{
73
+ id: 'nestedOne'
74
+ }, {
75
+ id: 'nestedTwo'
76
+ }]
77
+ }, {
78
+ label: 'No',
79
+ value: 'no'
80
+ }]
81
+ }
82
+ }];
83
+ var DATA = {
84
+ radiosComp: 'yes'
85
+ };
86
+ expect((0, _elevateNestedComponents.default)(COMPONENTS, DATA)).toEqual([].concat(COMPONENTS, [{
87
+ id: 'nestedOne'
88
+ }, {
89
+ id: 'nestedTwo'
90
+ }]));
91
+ });
92
+ });
@@ -25,23 +25,12 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
25
25
 
26
26
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
27
27
 
28
- var setupChildrenJSX = function setupChildrenJSX(options, config) {
29
- options.forEach(function (option) {
30
- if (!Array.isArray(option.nested)) {
31
- return;
32
- }
33
-
34
- option.children = getChildrenJsx(config, option.nested);
35
- });
36
- };
37
28
  /**
38
29
  * Separate function for each component type for the sake of
39
30
  * code clarity - having the additional bits and pieces in the
40
31
  * switch statement increases the cyclomatic complexity and
41
32
  * makes it much harder to follow what's going on.
42
33
  */
43
-
44
-
45
34
  var getAutocomplete = function getAutocomplete(config) {
46
35
  var attrs = (0, _cleanAttributes.default)(config);
47
36
 
@@ -59,7 +48,6 @@ var getCheckboxes = function getCheckboxes(config) {
59
48
  options = val;
60
49
  });
61
50
 
62
- setupChildrenJSX(options, config);
63
51
  var attrs = (0, _cleanAttributes.default)(config);
64
52
  return /*#__PURE__*/_react.default.createElement(_copReactComponents.Checkboxes, _extends({}, attrs, {
65
53
  options: options
@@ -118,7 +106,13 @@ var getRadios = function getRadios(config) {
118
106
  options = val;
119
107
  });
120
108
 
121
- setupChildrenJSX(options, config);
109
+ options.forEach(function (option) {
110
+ if (!Array.isArray(option.nested)) {
111
+ return;
112
+ }
113
+
114
+ option.children = getChildrenJsx(config, option.nested);
115
+ });
122
116
  var attrs = (0, _cleanAttributes.default)(config);
123
117
  return /*#__PURE__*/_react.default.createElement(_copReactComponents.Radios, _extends({}, attrs, {
124
118
  options: options
@@ -7,6 +7,8 @@ exports.default = void 0;
7
7
 
8
8
  var _cleanAttributes = _interopRequireDefault(require("./cleanAttributes"));
9
9
 
10
+ var _elevateNestedComponents = _interopRequireDefault(require("./elevateNestedComponents"));
11
+
10
12
  var _getComponent = _interopRequireDefault(require("./getComponent"));
11
13
 
12
14
  var _getDefaultValue = _interopRequireDefault(require("./getDefaultValue"));
@@ -23,6 +25,7 @@ var Component = {
23
25
  clean: _cleanAttributes.default,
24
26
  defaultValue: _getDefaultValue.default,
25
27
  editable: _isEditable.default,
28
+ elevateNested: _elevateNestedComponents.default,
26
29
  get: _getComponent.default,
27
30
  show: _showComponent.default,
28
31
  wrap: _wrapInFormGroup.default
@@ -11,6 +11,47 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
11
11
 
12
12
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
13
13
 
14
+ var getComponentToUse = function getComponentToUse(toUse, formComponents) {
15
+ var path = toUse.use.split('.');
16
+ var firstId = path.shift();
17
+
18
+ var wrapper = _objectSpread({}, formComponents.find(function (fc) {
19
+ return fc.id === firstId;
20
+ }));
21
+
22
+ var parent = wrapper;
23
+
24
+ var _loop = function _loop() {
25
+ var id = path.shift();
26
+
27
+ if (Array.isArray(parent.components)) {
28
+ // Filter the parent components down to just the one referenced
29
+ // by the current id.
30
+ parent.components = parent.components.filter(function (c) {
31
+ return c.id === id;
32
+ });
33
+
34
+ if (parent.components.length > 0) {
35
+ // Make the found child the parent so we can iterate.
36
+ parent = parent.components[0];
37
+ } else {
38
+ // If no child was found, there can be no parent.
39
+ parent = undefined;
40
+ }
41
+ } else {
42
+ // We cannot find the child with this id if there are no child
43
+ // components on this parent.
44
+ parent = undefined;
45
+ }
46
+ };
47
+
48
+ while (parent && path.length > 0) {
49
+ _loop();
50
+ } // If we missed a nested reference along the way, don't return the wrapper.
51
+
52
+
53
+ return parent ? wrapper : undefined;
54
+ };
14
55
  /**
15
56
  * Use an existing component from the formComponents, overriding any properties
16
57
  * where appropriate.
@@ -18,17 +59,19 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
18
59
  * @param {Array} formComponents An array of existing components on the form.
19
60
  * @returns A component configuration object.
20
61
  */
62
+
63
+
21
64
  var useComponent = function useComponent(toUse, formComponents) {
22
- var formComponent = toUse ? formComponents.find(function (fc) {
23
- return fc.id === toUse.use;
24
- }) : undefined;
25
-
26
- if (formComponent) {
27
- var fieldId = toUse.fieldId || formComponent.fieldId;
28
- return _objectSpread(_objectSpread(_objectSpread({}, formComponent), toUse), {}, {
29
- cya_label: formComponent.label || formComponent.cya_label,
30
- fieldId: fieldId
31
- });
65
+ if (toUse) {
66
+ var component = getComponentToUse(toUse, formComponents);
67
+
68
+ if (component) {
69
+ var fieldId = toUse.fieldId || component.fieldId;
70
+ return _objectSpread(_objectSpread(_objectSpread({}, component), toUse), {}, {
71
+ cya_label: component.label || component.cya_label,
72
+ fieldId: fieldId
73
+ });
74
+ }
32
75
  }
33
76
 
34
77
  return _objectSpread({}, toUse);
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
 
3
+ var _models = require("../../models");
4
+
3
5
  var _useComponent = _interopRequireDefault(require("./useComponent"));
4
6
 
5
7
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -13,27 +15,45 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
13
15
  describe('utils', function () {
14
16
  describe('FormPage', function () {
15
17
  describe('useComponent', function () {
18
+ var ZULU = {
19
+ id: 'z',
20
+ fieldId: 'z',
21
+ label: 'Zulu',
22
+ type: _models.ComponentTypes.TEXT
23
+ };
24
+ var CONTAINER = {
25
+ id: 'container',
26
+ fieldId: 'container',
27
+ label: 'Container',
28
+ type: _models.ComponentTypes.CONTAINER,
29
+ components: [{
30
+ id: 'f',
31
+ fieldId: 'f',
32
+ label: 'Foxtrot',
33
+ type: _models.ComponentTypes.TEXT
34
+ }, ZULU]
35
+ };
16
36
  var FORM_COMPONENTS = [{
17
37
  id: 'a',
18
38
  fieldId: 'a',
19
39
  label: 'Alpha',
20
- type: 'text'
40
+ type: _models.ComponentTypes.TEXT
21
41
  }, {
22
42
  id: 'b',
23
43
  fieldId: 'b',
24
44
  label: 'Bravo',
25
- type: 'text'
45
+ type: _models.ComponentTypes.TEXT
26
46
  }, {
27
47
  id: 'c',
28
48
  fieldId: 'c',
29
49
  label: 'Charlie',
30
- type: 'text'
50
+ type: _models.ComponentTypes.TEXT
31
51
  }, {
32
52
  id: 'd',
33
53
  fieldId: 'd',
34
54
  cya_label: 'Delta',
35
- type: 'text'
36
- }];
55
+ type: _models.ComponentTypes.TEXT
56
+ }, CONTAINER];
37
57
  it('should handle a null toUse configuration', function () {
38
58
  var TO_USE = null;
39
59
  expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual({});
@@ -107,6 +127,43 @@ describe('utils', function () {
107
127
  label: TO_USE.label
108
128
  }));
109
129
  });
130
+ it('should handle a container', function () {
131
+ var TO_USE = {
132
+ use: CONTAINER.id
133
+ };
134
+ expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(_objectSpread(_objectSpread({
135
+ use: CONTAINER.id
136
+ }, CONTAINER), {}, {
137
+ cya_label: CONTAINER.label
138
+ }));
139
+ });
140
+ it('should handle a component nested inside a container', function () {
141
+ var ID = "".concat(CONTAINER.id, ".").concat(ZULU.id);
142
+ var TO_USE = {
143
+ use: ID
144
+ };
145
+ expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(_objectSpread(_objectSpread({
146
+ use: ID
147
+ }, CONTAINER), {}, {
148
+ cya_label: CONTAINER.label,
149
+ components: [ZULU // Foxtrot is not included
150
+ ]
151
+ }));
152
+ });
153
+ it('should handle an unrecognised container reference', function () {
154
+ var ID = "unrecognised.".concat(ZULU.id);
155
+ var TO_USE = {
156
+ use: ID
157
+ };
158
+ expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(TO_USE);
159
+ });
160
+ it('should handle an unrecognised component within a container', function () {
161
+ var ID = "".concat(CONTAINER.id, ".unrecognised");
162
+ var TO_USE = {
163
+ use: ID
164
+ };
165
+ expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(TO_USE);
166
+ });
110
167
  });
111
168
  });
112
169
  });
@@ -79,7 +79,6 @@ var validateComponent = function validateComponent(component, outerData, formDat
79
79
  error = message;
80
80
  break;
81
81
 
82
- case _models.ComponentTypes.CHECKBOXES:
83
82
  case _models.ComponentTypes.RADIOS:
84
83
  var nestedErrors = [];
85
84
  (_component$data$optio = component.data.options) === null || _component$data$optio === void 0 ? void 0 : _component$data$optio.forEach(function (option) {
@@ -200,19 +200,19 @@ describe('utils.Validate.Component', function () {
200
200
  });
201
201
  });
202
202
  describe('when the component has a nested component', function () {
203
- it.each([['radios', 'text'], ['checkboxes', 'text']])('should return no error when the radio component contains nested components without errors', function (parentType, nestedType) {
203
+ it('should return no error when the radio component contains nested components without errors', function () {
204
204
  var NESTED_ID = 'nestedId';
205
205
  var NESTED_VALUE = 'nestedValue';
206
206
 
207
207
  var FORMDATA = _defineProperty({}, NESTED_ID, NESTED_VALUE);
208
208
 
209
209
  var COMPONENT = {
210
- type: parentType,
210
+ type: 'radios',
211
211
  id: 'a',
212
212
  data: {
213
213
  options: [{
214
214
  nested: [{
215
- type: nestedType,
215
+ type: 'text',
216
216
  fieldId: NESTED_ID,
217
217
  id: NESTED_ID,
218
218
  required: true
@@ -222,16 +222,16 @@ describe('utils.Validate.Component', function () {
222
222
  };
223
223
  expect((0, _validateComponent.default)(COMPONENT, undefined, FORMDATA)).toBeUndefined();
224
224
  });
225
- it.each([['radios', 'text'], ['checkboxes', 'text']])('should return an error when the radio component contains nested components with errors', function (parentType, nestedType) {
225
+ it('should return an error when the radio component contains nested components with errors', function () {
226
226
  var NESTED_ID = 'nestedId';
227
227
  var FORMDATA = {};
228
228
  var COMPONENT = {
229
- type: parentType,
229
+ type: 'radios',
230
230
  id: 'a',
231
231
  data: {
232
232
  options: [{
233
233
  nested: [{
234
- type: nestedType,
234
+ type: 'text',
235
235
  fieldId: NESTED_ID,
236
236
  id: NESTED_ID,
237
237
  required: true
@@ -244,10 +244,10 @@ describe('utils.Validate.Component', function () {
244
244
  error: "Field is required"
245
245
  }]);
246
246
  });
247
- it.each([['radios'], ['checkboxes']])('should return no error when a non selected radio component contains nested components with errors', function (type) {
247
+ it('should return no error when a non selected radio component contains nested components with errors', function () {
248
248
  var NESTED_ID = 'nestedId';
249
249
  var COMPONENT = {
250
- type: type,
250
+ type: 'radios',
251
251
  id: 'a',
252
252
  data: {
253
253
  options: [{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ukhomeoffice/cop-react-form-renderer",
3
- "version": "4.13.1-alpha",
3
+ "version": "4.14.3",
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.2.3-alpha",
19
+ "@ukhomeoffice/cop-react-components": "2.2.3",
20
20
  "axios": "^0.23.0",
21
21
  "dayjs": "^1.11.0",
22
22
  "govuk-frontend": "^4.3.1",