@ukhomeoffice/cop-react-form-renderer 6.0.5-peter → 6.5.1-peter

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.
Files changed (74) hide show
  1. package/dist/components/CheckYourAnswers/CheckYourAnswers.scss +2 -2
  2. package/dist/components/CollectionPage/CollectionPage.js +8 -2
  3. package/dist/components/CollectionSummary/BannerStrip.js +3 -2
  4. package/dist/components/CollectionSummary/BannerStrip.scss +2 -2
  5. package/dist/components/CollectionSummary/BannerStrip.test.js +39 -4
  6. package/dist/components/CollectionSummary/CollectionSummary.js +82 -63
  7. package/dist/components/CollectionSummary/CollectionSummary.scss +1 -1
  8. package/dist/components/CollectionSummary/CollectionSummary.test.js +40 -80
  9. package/dist/components/CollectionSummary/Confirmation.scss +1 -1
  10. package/dist/components/CollectionSummary/RenderListView.js +24 -20
  11. package/dist/components/CollectionSummary/RenderListView.scss +10 -1
  12. package/dist/components/CollectionSummary/RenderListView.test.js +14 -4
  13. package/dist/components/CollectionSummary/SummaryCard.js +59 -38
  14. package/dist/components/CollectionSummary/SummaryCard.scss +2 -1
  15. package/dist/components/CollectionSummary/SummaryCard.test.js +193 -150
  16. package/dist/components/CollectionSummary/SummaryCardDetails.js +70 -13
  17. package/dist/components/CollectionSummary/SummaryCardDetails.scss +43 -6
  18. package/dist/components/CollectionSummary/SummaryCardDetails.test.js +174 -26
  19. package/dist/components/CollectionSummary/SummaryCardValidationContext.js +15 -5
  20. package/dist/components/CollectionSummary/SummaryCardValidationContext.test.js +5 -4
  21. package/dist/components/FormComponent/Collection.js +24 -17
  22. package/dist/components/FormComponent/Collection.test.js +138 -0
  23. package/dist/components/FormComponent/FormComponent.js +12 -0
  24. package/dist/components/FormPage/FormPage.scss +1 -1
  25. package/dist/components/FormRenderer/FormRenderer.js +7 -4
  26. package/dist/components/FormRenderer/FormRenderer.scss +1 -1
  27. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-airpax-after.json +429 -0
  28. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-airpax-before.json +449 -0
  29. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-airpax-form.json +15219 -0
  30. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-eab-2-data-after.json +516 -0
  31. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-eab-2-data-before.json +593 -0
  32. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-eab2-form.json +15219 -0
  33. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-mandec-data-after.json +84 -0
  34. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-mandec-data-before.json +98 -0
  35. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/cop-mandec-form.json +9158 -0
  36. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/test.json +1605 -0
  37. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/test2.json +205 -0
  38. package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.js +114 -61
  39. package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.test.js +30 -0
  40. package/dist/components/FormRenderer/helpers/deleteNodeByPath.js +8 -2
  41. package/dist/components/FormRenderer/onPageAction.js +6 -1
  42. package/dist/components/FormRenderer/onPageAction.test.js +18 -4
  43. package/dist/components/SummaryList/SummaryList.scss +2 -2
  44. package/dist/components/TaskList/TaskList.scss +1 -1
  45. package/dist/context/ValidationContext/ValidationContext.js +49 -5
  46. package/dist/context/ValidationContext/ValidationContext.test.js +16 -7
  47. package/dist/hooks/useRefData.js +1 -1
  48. package/dist/utils/CheckYourAnswers/showComponentCYA.js +1 -2
  49. package/dist/utils/CheckYourAnswers/showComponentCYA.test.js +5 -0
  50. package/dist/utils/CollectionPage/addCollectionPageEntry.js +1 -2
  51. package/dist/utils/CollectionPage/addCollectionPageEntry.test.js +4 -24
  52. package/dist/utils/CollectionPage/duplicateCollectionPageEntry.js +13 -1
  53. package/dist/utils/CollectionPage/duplicateCollectionPageEntry.test.js +17 -2
  54. package/dist/utils/CollectionPage/getErrorsForCollection.js +55 -0
  55. package/dist/utils/CollectionPage/getErrorsForCollection.test.js +155 -0
  56. package/dist/utils/CollectionPage/getQuickEditPage.js +7 -1
  57. package/dist/utils/CollectionPage/index.js +2 -0
  58. package/dist/utils/CollectionPage/setCollectionPageData.js +9 -4
  59. package/dist/utils/CollectionPage/setCollectionPageData.test.js +18 -0
  60. package/dist/utils/Component/isEditable.js +1 -1
  61. package/dist/utils/Condition/meetsAllConditions.js +5 -1
  62. package/dist/utils/Condition/meetsAllConditions.test.js +13 -0
  63. package/dist/utils/Condition/meetsCondition.js +18 -0
  64. package/dist/utils/Condition/meetsCondition.test.js +100 -0
  65. package/dist/utils/Data/getOptions.js +10 -0
  66. package/dist/utils/Data/getOptions.test.js +73 -0
  67. package/dist/utils/Data/nestInRefdataOptions.js +49 -0
  68. package/dist/utils/Data/nestInRefdataOptions.test.js +236 -0
  69. package/dist/utils/Validate/validateContainer.js +3 -1
  70. package/dist/utils/Validate/validateContainer.test.js +33 -0
  71. package/dist/utils/Validate/validateEmail.js +1 -1
  72. package/dist/utils/Validate/validatePage.js +10 -1
  73. package/dist/utils/Validate/validatePage.test.js +69 -0
  74. package/package.json +4 -4
@@ -31,6 +31,45 @@ var ValidationContextProvider = function ValidationContextProvider(_ref) {
31
31
  _useState2 = _slicedToArray(_useState, 2),
32
32
  errors = _useState2[0],
33
33
  setErrors = _useState2[1];
34
+ var _useState3 = (0, _react.useState)([]),
35
+ _useState4 = _slicedToArray(_useState3, 2),
36
+ queuedErrors = _useState4[0],
37
+ setQueuedErrors = _useState4[1];
38
+
39
+ /**
40
+ * Queues errors to be displayed when the next validation takes place.
41
+ *
42
+ * @param {array} errors An array of errors to queue.
43
+ */
44
+ var enqueueErrors = function enqueueErrors(errors) {
45
+ setQueuedErrors(function (prev) {
46
+ return [].concat(prev, errors).filter(function (e) {
47
+ return !!e;
48
+ });
49
+ });
50
+ };
51
+
52
+ /**
53
+ * Removed errors from the queue if they match the given criteria.
54
+ *
55
+ * @param {function} matcher A function that should take an error and return true if that
56
+ * error should be removed from the queue.
57
+ */
58
+ var dequeueErrors = function dequeueErrors(matcher) {
59
+ if (typeof matcher !== 'function') {
60
+ return;
61
+ }
62
+ setQueuedErrors(function (prev) {
63
+ return prev.filter(function (e) {
64
+ return !matcher(e);
65
+ });
66
+ });
67
+ };
68
+ var clearQueuedErrors = function clearQueuedErrors() {
69
+ if (queuedErrors.length) {
70
+ setQueuedErrors([]);
71
+ }
72
+ };
34
73
  var addErrors = /*#__PURE__*/function () {
35
74
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(errors) {
36
75
  return _regeneratorRuntime().wrap(function _callee$(_context) {
@@ -56,8 +95,9 @@ var ValidationContextProvider = function ValidationContextProvider(_ref) {
56
95
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
57
96
  while (1) switch (_context2.prev = _context2.next) {
58
97
  case 0:
98
+ setQueuedErrors([]);
59
99
  setErrors([]);
60
- case 1:
100
+ case 2:
61
101
  case "end":
62
102
  return _context2.stop();
63
103
  }
@@ -69,17 +109,17 @@ var ValidationContextProvider = function ValidationContextProvider(_ref) {
69
109
  }();
70
110
  var validate = {
71
111
  page: function page(_page) {
72
- var pageErrors = _utils.default.Validate.page(_page);
112
+ var pageErrors = _utils.default.Validate.page(_page, queuedErrors);
73
113
  var allErrors = hooks.onValidate(_page, pageErrors);
74
114
  setErrors(allErrors);
75
115
  return allErrors;
76
116
  },
77
117
  pages: function pages(_pages) {
78
- var allPagesErrors = _pages.map(function (page) {
79
- return _utils.default.Validate.page(page);
118
+ var pageErrors = _pages.map(function (page) {
119
+ return _utils.default.Validate.page(page, queuedErrors);
80
120
  });
81
121
  var allErrors = _pages.flatMap(function (page, index) {
82
- return hooks.onValidate(page, allPagesErrors[index]);
122
+ return hooks.onValidate(page, pageErrors[index]);
83
123
  });
84
124
  setErrors(allErrors);
85
125
  return allErrors;
@@ -90,6 +130,10 @@ var ValidationContextProvider = function ValidationContextProvider(_ref) {
90
130
  errors: errors,
91
131
  addErrors: addErrors,
92
132
  clearErrors: clearErrors,
133
+ queuedErrors: queuedErrors,
134
+ enqueueErrors: enqueueErrors,
135
+ dequeueErrors: dequeueErrors,
136
+ clearQueuedErrors: clearQueuedErrors,
93
137
  validate: validate
94
138
  }
95
139
  }, children);
@@ -6,8 +6,8 @@ var _copReactComponents = require("@ukhomeoffice/cop-react-components");
6
6
  var _react2 = _interopRequireWildcard(require("react"));
7
7
  var _propTypes = _interopRequireDefault(require("prop-types"));
8
8
  var _hooks = require("../../hooks");
9
- var _ValidationContext = _interopRequireDefault(require("./ValidationContext"));
10
9
  var _HooksContext = _interopRequireDefault(require("../HooksContext"));
10
+ var _ValidationContext = _interopRequireDefault(require("./ValidationContext"));
11
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
12
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
13
13
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -20,6 +20,9 @@ var TestComponent = function TestComponent(_ref) {
20
20
  var _useValidation = (0, _hooks.useValidation)(),
21
21
  addErrors = _useValidation.addErrors,
22
22
  clearErrors = _useValidation.clearErrors,
23
+ enqueueErrors = _useValidation.enqueueErrors,
24
+ dequeueErrors = _useValidation.dequeueErrors,
25
+ clearQueuedErrors = _useValidation.clearQueuedErrors,
23
26
  errors = _useValidation.errors,
24
27
  validate = _useValidation.validate;
25
28
  (0, _react2.useEffect)(function () {
@@ -27,7 +30,7 @@ var TestComponent = function TestComponent(_ref) {
27
30
  addErrors(customErrors);
28
31
  }
29
32
  }, [customErrors]);
30
- return /*#__PURE__*/_react2.default.createElement(_react2.default.Fragment, null, typeof addErrors === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "addErrors is a function"), typeof clearErrors === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "clearErrors is a function"), typeof validate.page === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "validate.page is a function"), Array.isArray(errors) && /*#__PURE__*/_react2.default.createElement("span", null, "errors is an array of length ", errors.length), (errors === null || errors === void 0 ? void 0 : errors.length) > 0 && /*#__PURE__*/_react2.default.createElement(_copReactComponents.ErrorSummary, {
33
+ return /*#__PURE__*/_react2.default.createElement(_react2.default.Fragment, null, typeof addErrors === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "addErrors is a function"), typeof clearErrors === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "clearErrors is a function"), typeof enqueueErrors === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "enqueueErrors is a function"), typeof dequeueErrors === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "dequeueErrors is a function"), typeof clearQueuedErrors === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "clearQueuedErrors is a function"), typeof validate.page === 'function' && /*#__PURE__*/_react2.default.createElement("span", null, "validate.page is a function"), Array.isArray(errors) && /*#__PURE__*/_react2.default.createElement("span", null, "errors is an array of length ", errors.length), (errors === null || errors === void 0 ? void 0 : errors.length) > 0 && /*#__PURE__*/_react2.default.createElement(_copReactComponents.ErrorSummary, {
31
34
  errors: errors
32
35
  }));
33
36
  };
@@ -38,12 +41,15 @@ describe('context.ValidationContext', function () {
38
41
  while (1) switch (_context.prev = _context.next) {
39
42
  case 0:
40
43
  _render = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_HooksContext.default, null, /*#__PURE__*/_react2.default.createElement(_ValidationContext.default, null, /*#__PURE__*/_react2.default.createElement(TestComponent, null)))), container = _render.container;
41
- expect(container.childNodes.length).toEqual(4);
44
+ expect(container.childNodes.length).toEqual(7);
42
45
  expect(container.textContent).toContain('addErrors is a function');
43
46
  expect(container.textContent).toContain('clearErrors is a function');
47
+ expect(container.textContent).toContain('enqueueErrors is a function');
48
+ expect(container.textContent).toContain('dequeueErrors is a function');
49
+ expect(container.textContent).toContain('clearQueuedErrors is a function');
44
50
  expect(container.textContent).toContain('validate.page is a function');
45
51
  expect(container.textContent).toContain('errors is an array of length 0');
46
- case 6:
52
+ case 9:
47
53
  case "end":
48
54
  return _context.stop();
49
55
  }
@@ -61,16 +67,19 @@ describe('context.ValidationContext', function () {
61
67
  _render2 = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_HooksContext.default, null, /*#__PURE__*/_react2.default.createElement(_ValidationContext.default, null, /*#__PURE__*/_react2.default.createElement(TestComponent, {
62
68
  customErrors: CUSTOM_ERRORS
63
69
  })))), container = _render2.container;
64
- expect(container.childNodes.length).toEqual(5);
70
+ expect(container.childNodes.length).toEqual(8);
65
71
  expect(container.textContent).toContain('addErrors is a function');
66
72
  expect(container.textContent).toContain('clearErrors is a function');
73
+ expect(container.textContent).toContain('enqueueErrors is a function');
74
+ expect(container.textContent).toContain('dequeueErrors is a function');
75
+ expect(container.textContent).toContain('clearQueuedErrors is a function');
67
76
  expect(container.textContent).toContain('validate.page is a function');
68
77
  expect(container.textContent).toContain('errors is an array of length 1');
69
- errorSummary = container.childNodes[4];
78
+ errorSummary = container.childNodes[7];
70
79
  expect(errorSummary.tagName).toEqual('DIV');
71
80
  expect(errorSummary.classList).toContain('govuk-error-summary');
72
81
  expect(errorSummary.textContent).toContain(CUSTOM_ERRORS[0].error);
73
- case 11:
82
+ case 14:
74
83
  case "end":
75
84
  return _context2.stop();
76
85
  }
@@ -29,7 +29,7 @@ var STATUS_COMPLETE = exports.STATUS_COMPLETE = 'complete';
29
29
  var getRefDataUrl = function getRefDataUrl(component) {
30
30
  // eslint-disable-next-line prefer-destructuring
31
31
  var data = component.data;
32
- if (data && !data.options) {
32
+ if (data && !data.options || data !== null && data !== void 0 && data.url) {
33
33
  return _copReactComponents.Utils.interpolateString(data.url, component.formData);
34
34
  }
35
35
  return undefined;
@@ -9,10 +9,9 @@ var _Component = _interopRequireDefault(require("../Component"));
9
9
  var _Container = _interopRequireDefault(require("../Container"));
10
10
  var _getSourceData = _interopRequireDefault(require("../Data/getSourceData"));
11
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
- /* eslint-disable no-console */
13
12
  // Local imports
14
13
 
15
- var EXCLUDE_FROM_CYA = exports.EXCLUDE_FROM_CYA = [_models.ComponentTypes.ALERT, _models.ComponentTypes.COLLECTION_SUMMARY, _models.ComponentTypes.HEADING, _models.ComponentTypes.HTML, _models.ComponentTypes.INSET_TEXT];
14
+ var EXCLUDE_FROM_CYA = exports.EXCLUDE_FROM_CYA = [_models.ComponentTypes.ALERT, _models.ComponentTypes.COLLECTION_SUMMARY, _models.ComponentTypes.DETAILS, _models.ComponentTypes.HEADING, _models.ComponentTypes.HTML, _models.ComponentTypes.INSET_TEXT];
16
15
 
17
16
  /**
18
17
  * Determines whether a given component should display on the Check your answers screen.
@@ -31,6 +31,11 @@ describe('utils', function () {
31
31
  type: _models.ComponentTypes.INSET_TEXT
32
32
  }, null)).toBeFalsy();
33
33
  });
34
+ it('should not show when it is a details type', function () {
35
+ expect((0, _showComponentCYA.default)({
36
+ type: _models.ComponentTypes.DETAILS
37
+ }, null)).toBeFalsy();
38
+ });
34
39
  it('should not show when it hidden and disabled', function () {
35
40
  expect((0, _showComponentCYA.default)({
36
41
  hidden: true,
@@ -17,7 +17,6 @@ exports.default = void 0;
17
17
  */
18
18
  var addCollectionPageEntry = function addCollectionPageEntry(collectionName, formData) {
19
19
  var fieldName = collectionName.split('.').pop();
20
- formData["".concat(fieldName, "ActiveId")] = '0';
21
- formData["".concat(fieldName, "NumberedIndex")] = Number(formData["".concat(fieldName, "ActiveId")]) + 1;
20
+ formData["".concat(fieldName, "ActiveId")] = null;
22
21
  };
23
22
  var _default = exports.default = addCollectionPageEntry;
@@ -3,34 +3,14 @@
3
3
  var _addCollectionPageEntry = _interopRequireDefault(require("./addCollectionPageEntry"));
4
4
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
5
5
  describe('Utils.CollectionPage.addCollectionPageEntry', function () {
6
- it('should correctly add a new entry for a top-level collection', function () {
6
+ it('should set active ID as null for a top-level collection', function () {
7
7
  var FORM_DATA = {};
8
8
  (0, _addCollectionPageEntry.default)('testCollection', FORM_DATA);
9
- expect(FORM_DATA.testCollectionActiveId).toBeTruthy();
9
+ expect(FORM_DATA.testCollectionActiveId).toBeFalsy();
10
10
  });
11
- it('should correctly add a new entry for a nested collection', function () {
11
+ it('should set a active ID as null for a nested collection', function () {
12
12
  var FORM_DATA = {};
13
13
  (0, _addCollectionPageEntry.default)('parent.child.grandchild', FORM_DATA);
14
- expect(FORM_DATA.grandchildActiveId).toBeTruthy();
15
- });
16
- it('should correctly set the active ID for a top-level collection', function () {
17
- var FORM_DATA = {};
18
- (0, _addCollectionPageEntry.default)('testCollection', FORM_DATA);
19
- expect(FORM_DATA.testCollectionActiveId).toBe('0');
20
- });
21
- it('should correctly set the active ID for a nested collection', function () {
22
- var FORM_DATA = {};
23
- (0, _addCollectionPageEntry.default)('parent.child.grandchild', FORM_DATA);
24
- expect(FORM_DATA.grandchildActiveId).toBe('0');
25
- });
26
- it('should correctly increment the numbered index for a top-level collection', function () {
27
- var FORM_DATA = {};
28
- (0, _addCollectionPageEntry.default)('testCollection', FORM_DATA);
29
- expect(FORM_DATA.testCollectionNumberedIndex).toBe(1);
30
- });
31
- it('should correctly increment the numbered index for a nested collection', function () {
32
- var FORM_DATA = {};
33
- (0, _addCollectionPageEntry.default)('parent.child.grandchild', FORM_DATA);
34
- expect(FORM_DATA.grandchildNumberedIndex).toBe(1);
14
+ expect(FORM_DATA.grandchildActiveId).toBeFalsy();
35
15
  });
36
16
  });
@@ -12,8 +12,20 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
12
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; }
13
13
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
14
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); }
15
+ /**
16
+ * Duplicates an entry with the given ID in the given collection, optionally
17
+ * ignoring named fields or adding extras to the duplicate if they're provided.
18
+ *
19
+ * @param {string} collectionName The name of the collection the entry to duplicate is in.
20
+ * @param {object} formData The top-level formData object.
21
+ * @param {string} entryId The ID of the entry to duplicate.
22
+ * @param {array} fieldsToIgnore An array of field names that shouldn't be copied to the duplicate.
23
+ * @param {object} fieldsToAdd An object that will be spread to the new entry.
24
+ * @returns The ID of the duplicate entry.
25
+ */
15
26
  var duplicateCollectionPageEntry = function duplicateCollectionPageEntry(collectionName, formData, entryId) {
16
27
  var fieldsToIgnore = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
28
+ var fieldsToAdd = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
17
29
  var collectionData = (0, _getCollectionPageData.default)(collectionName, formData);
18
30
  var entryToDuplicate = collectionData === null || collectionData === void 0 ? void 0 : collectionData.find(function (entry) {
19
31
  return entry.id === entryId;
@@ -22,7 +34,7 @@ var duplicateCollectionPageEntry = function duplicateCollectionPageEntry(collect
22
34
  return null;
23
35
  }
24
36
  var newEntryId = Date.now().toString();
25
- var newEntry = _objectSpread(_objectSpread({}, entryToDuplicate), {}, {
37
+ var newEntry = _objectSpread(_objectSpread(_objectSpread({}, entryToDuplicate), fieldsToAdd), {}, {
26
38
  id: newEntryId
27
39
  });
28
40
  fieldsToIgnore.forEach(function (field) {
@@ -65,10 +65,25 @@ describe('utils.CollectionPage.duplicateCollectionPageEntry', function () {
65
65
  expect(FORM_DATA[COLLECTION_NAME][1].id).toBeTruthy();
66
66
  expect(FORM_DATA[COLLECTION_NAME][1].value).toBeUndefined();
67
67
  });
68
- it('should do nothing if an entry with the given id does not exist', function () {
69
- var _FORM_DATA3, _expect$toEqual;
68
+ it('should add fields from the fieldsToAdd object', function () {
69
+ var _FORM_DATA3;
70
70
  var FORM_DATA = (_FORM_DATA3 = {}, _defineProperty(_FORM_DATA3, "".concat(COLLECTION_NAME, "ActiveId"), '1'), _defineProperty(_FORM_DATA3, COLLECTION_NAME, [OBJ]), _FORM_DATA3);
71
71
  ;
72
+ var FIELDS_TO_ADD = {
73
+ addedKey: 'addedValue'
74
+ };
75
+ (0, _duplicateCollectionPageEntry.default)(COLLECTION_NAME, FORM_DATA, '1', [], FIELDS_TO_ADD);
76
+ expect(FORM_DATA[COLLECTION_NAME].length).toEqual(2);
77
+ expect(FORM_DATA[COLLECTION_NAME][0].id).toBeTruthy();
78
+ expect(FORM_DATA[COLLECTION_NAME][0].value).toBeTruthy();
79
+ expect(FORM_DATA[COLLECTION_NAME][1].id).toBeTruthy();
80
+ expect(FORM_DATA[COLLECTION_NAME][1].value).toBeTruthy();
81
+ expect(FORM_DATA[COLLECTION_NAME][1].addedKey).toEqual('addedValue');
82
+ });
83
+ it('should do nothing if an entry with the given id does not exist', function () {
84
+ var _FORM_DATA4, _expect$toEqual;
85
+ var FORM_DATA = (_FORM_DATA4 = {}, _defineProperty(_FORM_DATA4, "".concat(COLLECTION_NAME, "ActiveId"), '1'), _defineProperty(_FORM_DATA4, COLLECTION_NAME, [OBJ]), _FORM_DATA4);
86
+ ;
72
87
  (0, _duplicateCollectionPageEntry.default)(COLLECTION_NAME, FORM_DATA, '0');
73
88
  expect(FORM_DATA).toEqual((_expect$toEqual = {}, _defineProperty(_expect$toEqual, "".concat(COLLECTION_NAME, "ActiveId"), '1'), _defineProperty(_expect$toEqual, COLLECTION_NAME, [OBJ]), _expect$toEqual));
74
89
  });
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _ = _interopRequireDefault(require(".."));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
10
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
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; }
13
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
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); }
15
+ var getErrorsForCollection = function getErrorsForCollection(config, masterPage, formData, hooks) {
16
+ var activeIds = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
17
+ if (!masterPage) {
18
+ return [];
19
+ }
20
+ // Get data for current collection
21
+ var collectionData = _.default.CollectionPage.getData(masterPage.collection.name, masterPage.formData) || [];
22
+ var allErrors = [];
23
+
24
+ // Loop over each entry in the collection data
25
+ collectionData.forEach(function (entry) {
26
+ var _masterPage$childPage;
27
+ // eslint-disable-next-line no-param-reassign
28
+ activeIds = _objectSpread(_objectSpread({}, activeIds), {}, _defineProperty({}, "".concat(masterPage.collection.name.split('.').pop(), "ActiveId"), entry.id));
29
+
30
+ // Loop over child pages and validate each one
31
+ var allPagesErrors = (_masterPage$childPage = masterPage.childPages) === null || _masterPage$childPage === void 0 ? void 0 : _masterPage$childPage.flatMap(function (page) {
32
+ var pageWithIds = _objectSpread(_objectSpread({}, page), {}, {
33
+ formData: _objectSpread(_objectSpread({}, formData), activeIds)
34
+ });
35
+
36
+ // Handle nested collections
37
+ if (page.childPages) {
38
+ return getErrorsForCollection(config, pageWithIds, formData, hooks, activeIds);
39
+ }
40
+ var pageErrors = _.default.Validate.page(pageWithIds);
41
+ return hooks.onValidate(pageWithIds, pageErrors);
42
+ });
43
+
44
+ // For each error add the entryId so we know what Summary Card we have to pass it to.
45
+ allErrors = allErrors.concat(allPagesErrors.map(function (e) {
46
+ return _objectSpread(_objectSpread({}, e), {}, {
47
+ entryId: entry.id,
48
+ showFor: config.id,
49
+ raisedBy: config.id
50
+ });
51
+ }));
52
+ });
53
+ return allErrors;
54
+ };
55
+ var _default = exports.default = getErrorsForCollection;
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+
3
+ var _getErrorsForCollection = _interopRequireDefault(require("./getErrorsForCollection"));
4
+ var _models = require("../../models");
5
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
+ describe('Utils.CollectionPage.getErrorsForCollection', function () {
7
+ var HOOKS = {
8
+ onValidate: function onValidate(_, errors) {
9
+ return errors;
10
+ }
11
+ };
12
+ var CONFIG = {
13
+ id: 'testId'
14
+ };
15
+ var FORM_DATA = {
16
+ collection: [{
17
+ id: 22,
18
+ item1: 'blue',
19
+ child: [{
20
+ id: 11,
21
+ item4: 'red'
22
+ }]
23
+ }]
24
+ };
25
+ var FORM_DATA_MISSING_TOP = {
26
+ collection: [{
27
+ id: 22,
28
+ item2: 'blue',
29
+ child: [{
30
+ id: 11,
31
+ item4: 'red'
32
+ }]
33
+ }]
34
+ };
35
+ var FORM_DATA_MISSING_NESTED = {
36
+ collection: [{
37
+ id: 22,
38
+ item1: 'blue',
39
+ child: [{
40
+ id: 11,
41
+ item9: 'red'
42
+ }]
43
+ }]
44
+ };
45
+ var FORM_DATA_MISSING_BOTH = {
46
+ collection: [{
47
+ id: 22,
48
+ item9: 'blue',
49
+ child: [{
50
+ id: 11,
51
+ item9: 'red'
52
+ }]
53
+ }]
54
+ };
55
+ var MASTER_PAGE = {
56
+ id: 'masterPage',
57
+ collection: {
58
+ name: 'collection',
59
+ masterPage: true
60
+ },
61
+ formData: FORM_DATA,
62
+ childPages: [{
63
+ id: 'page1',
64
+ collection: {
65
+ name: 'collection'
66
+ },
67
+ formData: FORM_DATA,
68
+ components: [{
69
+ id: 'item1',
70
+ fieldId: 'item1',
71
+ label: 'Item 1',
72
+ required: true,
73
+ type: _models.ComponentTypes.TEXT
74
+ }, {
75
+ id: 'item2',
76
+ fieldId: 'item2',
77
+ label: 'Item 2',
78
+ type: _models.ComponentTypes.TEXT
79
+ }]
80
+ }]
81
+ };
82
+ var MASTER_PAGE_WITH_NESTED = {
83
+ id: 'masterPage',
84
+ collection: {
85
+ name: 'collection',
86
+ masterPage: true
87
+ },
88
+ formData: FORM_DATA,
89
+ childPages: [{
90
+ id: 'page1',
91
+ collection: {
92
+ name: 'collection'
93
+ },
94
+ formData: FORM_DATA,
95
+ components: [{
96
+ id: 'item1',
97
+ fieldId: 'item1',
98
+ label: 'Item 1',
99
+ required: true,
100
+ type: _models.ComponentTypes.TEXT
101
+ }, {
102
+ id: 'item2',
103
+ fieldId: 'item2',
104
+ label: 'Item 2',
105
+ type: _models.ComponentTypes.TEXT
106
+ }]
107
+ }, {
108
+ id: 'page2',
109
+ formData: FORM_DATA,
110
+ collection: {
111
+ name: 'collection.child',
112
+ masterPage: true
113
+ },
114
+ childPages: [{
115
+ id: 'nestedPage',
116
+ formData: FORM_DATA,
117
+ collection: {
118
+ name: 'collection.child'
119
+ },
120
+ components: [{
121
+ id: 'item4',
122
+ fieldId: 'item4',
123
+ label: 'Item 4',
124
+ required: true,
125
+ type: _models.ComponentTypes.TEXT
126
+ }, {
127
+ id: 'item5',
128
+ fieldId: 'item5',
129
+ label: 'Item 5',
130
+ type: _models.ComponentTypes.TEXT
131
+ }]
132
+ }]
133
+ }]
134
+ };
135
+ it('should return nothing for a master page without errors', function () {
136
+ var errors = (0, _getErrorsForCollection.default)(CONFIG, MASTER_PAGE, FORM_DATA, HOOKS);
137
+ expect(errors.length).toEqual(0);
138
+ });
139
+ it('should return erorrs for a master page with errors', function () {
140
+ var errors = (0, _getErrorsForCollection.default)(CONFIG, MASTER_PAGE, FORM_DATA_MISSING_TOP, HOOKS);
141
+ expect(errors.length).toEqual(1);
142
+ });
143
+ it('should return nothing for a master page with a nested master page without errors', function () {
144
+ var errors = (0, _getErrorsForCollection.default)(CONFIG, MASTER_PAGE_WITH_NESTED, FORM_DATA, HOOKS);
145
+ expect(errors.length).toEqual(0);
146
+ });
147
+ it('should return errors for a master page with a nested master page without errors', function () {
148
+ var errors = (0, _getErrorsForCollection.default)(CONFIG, MASTER_PAGE_WITH_NESTED, FORM_DATA_MISSING_NESTED, HOOKS);
149
+ expect(errors.length).toEqual(1);
150
+ });
151
+ it('should return errors for a master page with errors with a nested master page with errors', function () {
152
+ var errors = (0, _getErrorsForCollection.default)(CONFIG, MASTER_PAGE_WITH_NESTED, FORM_DATA_MISSING_BOTH, HOOKS);
153
+ expect(errors.length).toEqual(2);
154
+ });
155
+ });
@@ -6,8 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _meetsAllConditions = _interopRequireDefault(require("../Condition/meetsAllConditions"));
8
8
  var _showFormPage = _interopRequireDefault(require("../FormPage/showFormPage"));
9
+ var _excluded = ["id"];
9
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
11
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
12
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
13
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
11
14
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
12
15
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
13
16
  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; }
@@ -104,7 +107,10 @@ var getQuickEditPage = function getQuickEditPage(masterPage, entryData) {
104
107
  }];
105
108
 
106
109
  // Need to have the collection data at the top level
107
- pageToReturn.formData = _objectSpread(_objectSpread({}, pageToReturn.formData), entryData);
110
+ // Remove ID to stop overwriting top-level form ID.
111
+ var id = entryData.id,
112
+ entryWithNoId = _objectWithoutProperties(entryData, _excluded);
113
+ pageToReturn.formData = _objectSpread(_objectSpread({}, pageToReturn.formData), entryWithNoId);
108
114
  delete pageToReturn.title;
109
115
  delete pageToReturn.collection;
110
116
  return pageToReturn;
@@ -10,6 +10,7 @@ var _duplicateCollectionPageEntry = _interopRequireDefault(require("./duplicateC
10
10
  var _getCollectionPageActiveId = _interopRequireDefault(require("./getCollectionPageActiveId"));
11
11
  var _getCollectionPageActiveIndex = _interopRequireDefault(require("./getCollectionPageActiveIndex"));
12
12
  var _getCollectionPageData = _interopRequireDefault(require("./getCollectionPageData"));
13
+ var _getErrorsForCollection = _interopRequireDefault(require("./getErrorsForCollection"));
13
14
  var _mergeCollectionPages = _interopRequireDefault(require("./mergeCollectionPages"));
14
15
  var _removeCollectionPageEntry = _interopRequireDefault(require("./removeCollectionPageEntry"));
15
16
  var _setCollectionPageData = _interopRequireDefault(require("./setCollectionPageData"));
@@ -23,6 +24,7 @@ var CollectionPage = {
23
24
  getActiveId: _getCollectionPageActiveId.default,
24
25
  getActiveIndex: _getCollectionPageActiveIndex.default,
25
26
  getData: _getCollectionPageData.default,
27
+ getErrorsForCollection: _getErrorsForCollection.default,
26
28
  mergePages: _mergeCollectionPages.default,
27
29
  removeEntry: _removeCollectionPageEntry.default,
28
30
  setData: _setCollectionPageData.default
@@ -28,15 +28,20 @@ var setCollectionPageData = function setCollectionPageData(collectionName, newDa
28
28
  var data = formData;
29
29
  nameParts.some(function (name) {
30
30
  var _data$name;
31
- // Current collection doesn't exist, so create it,
32
- // add an entry and set the active id.
31
+ // Current collection doesn't exist, so create it
33
32
  if (!data[name]) {
33
+ data[name] = [];
34
+ }
35
+ // If the entry matching the active ID doesn't exist in the collection, create it.
36
+ if (!data[name].find(function (e) {
37
+ return e.id === formData["".concat(name, "ActiveId")];
38
+ })) {
34
39
  var newEntryId = Date.now().toString();
35
40
  // eslint-disable-next-line no-param-reassign
36
41
  formData["".concat(name, "ActiveId")] = formData["".concat(name, "ActiveId")] || newEntryId;
37
- data[name] = [{
42
+ data[name].push({
38
43
  id: formData["".concat(name, "ActiveId")]
39
- }];
44
+ });
40
45
  }
41
46
  // We're at the target collection's level, so
42
47
  // set the new data.
@@ -160,4 +160,22 @@ describe('Utils.CollectionPage.setCollectionPageData', function () {
160
160
  value: 'newValue'
161
161
  });
162
162
  });
163
+ it('creates a new entry and updates active ID if no matching active ID is found', function () {
164
+ var formData = {};
165
+ var collectionName = 'testCollection';
166
+ var newData = [{
167
+ id: 'dataId',
168
+ value: 'testValue'
169
+ }];
170
+ (0, _setCollectionPageData.default)(collectionName, newData, formData);
171
+
172
+ // Check if formData has been updated
173
+ expect(formData["".concat(collectionName, "ActiveId")]).toBeDefined();
174
+
175
+ // Check if the new entry was added to the collection
176
+ expect(formData[collectionName]).toBeDefined();
177
+ expect(formData[collectionName].length).toBe(1);
178
+ expect(formData[collectionName][0].id).toBe(newData[0].id);
179
+ expect(formData[collectionName][0]).toEqual(expect.objectContaining(newData[0]));
180
+ });
163
181
  });
@@ -7,7 +7,7 @@ exports.default = exports.EDITABLE_TYPES = void 0;
7
7
  var _models = require("../../models");
8
8
  // Local imports
9
9
 
10
- var EDITABLE_TYPES = exports.EDITABLE_TYPES = [_models.ComponentTypes.AUTOCOMPLETE, _models.ComponentTypes.CALCULATION, _models.ComponentTypes.CHECKBOXES, _models.ComponentTypes.DATE, _models.ComponentTypes.EMAIL, _models.ComponentTypes.FILE, _models.ComponentTypes.MULTI_FILE, _models.ComponentTypes.PHONE_NUMBER, _models.ComponentTypes.RADIOS, _models.ComponentTypes.SELECT, _models.ComponentTypes.TEXT, _models.ComponentTypes.TEXT_AREA, _models.ComponentTypes.TIME];
10
+ var EDITABLE_TYPES = exports.EDITABLE_TYPES = [_models.ComponentTypes.AUTOCOMPLETE, _models.ComponentTypes.CALCULATION, _models.ComponentTypes.CHECKBOXES, _models.ComponentTypes.COLLECTION_SUMMARY, _models.ComponentTypes.DATE, _models.ComponentTypes.EMAIL, _models.ComponentTypes.FILE, _models.ComponentTypes.MULTI_FILE, _models.ComponentTypes.PHONE_NUMBER, _models.ComponentTypes.RADIOS, _models.ComponentTypes.SELECT, _models.ComponentTypes.TEXT, _models.ComponentTypes.TEXT_AREA, _models.ComponentTypes.TIME];
11
11
  var isEditable = function isEditable(options) {
12
12
  return EDITABLE_TYPES.includes(options === null || options === void 0 ? void 0 : options.type) || (options === null || options === void 0 ? void 0 : options.isEditable) || false;
13
13
  };
@@ -4,10 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _copReactComponents = require("@ukhomeoffice/cop-react-components");
7
8
  var _Data = _interopRequireDefault(require("../Data"));
8
9
  var _meetsCondition = _interopRequireDefault(require("./meetsCondition"));
9
10
  var _setupConditions = _interopRequireDefault(require("./setupConditions"));
10
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ // Global imports
13
+
11
14
  // Local imports
12
15
 
13
16
  var testConditions = function testConditions(conditions, data) {
@@ -17,7 +20,8 @@ var testConditions = function testConditions(conditions, data) {
17
20
  if (Array.isArray(condition.conditions)) {
18
21
  return testConditions(condition.conditions, data, condition.type);
19
22
  }
20
- var sourceDataValue = _Data.default.getSource(data, condition.field);
23
+ var field = condition.field.startsWith('interpolate::') ? _copReactComponents.Utils.interpolateString(condition.field, data).replace('interpolate::', '') : condition.field;
24
+ var sourceDataValue = _Data.default.getSource(data, field);
21
25
  return (0, _meetsCondition.default)(condition, sourceDataValue, data);
22
26
  };
23
27
  return type === 'and' ? arr.every(testCallback) : arr.some(testCallback);