@ukhomeoffice/cop-react-form-renderer 4.73.0 → 4.75.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.
Files changed (107) hide show
  1. package/dist/components/CheckYourAnswers/Answer.js +10 -4
  2. package/dist/components/CheckYourAnswers/CheckYourAnswers.js +51 -27
  3. package/dist/components/CheckYourAnswers/CheckYourAnswers.test.js +6 -5
  4. package/dist/components/CollectionPage/CollectionPage.js +7 -5
  5. package/dist/components/FormComponent/Collection.js +25 -17
  6. package/dist/components/FormComponent/Container.js +23 -13
  7. package/dist/components/FormComponent/FormComponent.js +24 -9
  8. package/dist/components/FormComponent/helpers/addLabel.js +4 -3
  9. package/dist/components/FormPage/FormPage.js +30 -19
  10. package/dist/components/FormRenderer/FormRenderer.js +90 -34
  11. package/dist/components/FormRenderer/FormRenderer.test.js +29 -27
  12. package/dist/components/FormRenderer/handlers/index.js +1 -2
  13. package/dist/components/FormRenderer/handlers/navigate.js +3 -1
  14. package/dist/components/FormRenderer/helpers/cleanHiddenNestedData.js +19 -15
  15. package/dist/components/FormRenderer/helpers/cleanHiddenNestedData.test.js +8 -8
  16. package/dist/components/FormRenderer/helpers/getCYA.js +5 -1
  17. package/dist/components/FormRenderer/helpers/getNextPageId.js +13 -7
  18. package/dist/components/FormRenderer/helpers/getRelevantPages.js +10 -2
  19. package/dist/components/FormRenderer/helpers/getRelevantPages.test.js +1 -1
  20. package/dist/components/FormRenderer/helpers/getUpdatedSectionStates.js +38 -24
  21. package/dist/components/FormRenderer/helpers/index.js +1 -2
  22. package/dist/components/FormRenderer/onCYAAction.js +2 -2
  23. package/dist/components/FormRenderer/onCYAAction.test.js +13 -13
  24. package/dist/components/FormRenderer/onPageAction.js +28 -9
  25. package/dist/components/FormRenderer/onPageAction.test.js +54 -18
  26. package/dist/components/FormRenderer/onTaskAction.js +14 -11
  27. package/dist/components/PageActions/ActionButton.js +0 -3
  28. package/dist/components/PageActions/PageActions.js +2 -2
  29. package/dist/components/SummaryList/SummaryList.js +13 -8
  30. package/dist/components/SummaryList/SummaryListHeadingRow.js +6 -2
  31. package/dist/components/SummaryList/SummaryListRow.js +5 -2
  32. package/dist/components/SummaryList/helpers/getGroupActionAttributes.js +2 -1
  33. package/dist/components/SummaryList/helpers/getRowActionAttributes.js +2 -1
  34. package/dist/components/TaskList/Task.js +1 -1
  35. package/dist/components/TaskList/TaskList.js +21 -12
  36. package/dist/components/TaskList/TaskState.js +2 -2
  37. package/dist/components/index.js +7 -0
  38. package/dist/context/HooksContext/HooksContext.js +33 -1
  39. package/dist/context/ValidationContext/ValidationContext.js +8 -1
  40. package/dist/context/ValidationContext/ValidationContext.test.js +8 -2
  41. package/dist/hooks/useGetRequest.js +3 -2
  42. package/dist/hooks/useRefData.js +1 -0
  43. package/dist/index.js +6 -0
  44. package/dist/utils/CheckYourAnswers/getCYAAction.js +5 -5
  45. package/dist/utils/CheckYourAnswers/getCYAAction.test.js +34 -34
  46. package/dist/utils/CheckYourAnswers/getCYACollectionChangeAction.js +2 -1
  47. package/dist/utils/CheckYourAnswers/getCYACollectionChangeAction.test.js +4 -4
  48. package/dist/utils/CheckYourAnswers/getCYACollectionDeleteAction.js +2 -1
  49. package/dist/utils/CheckYourAnswers/getCYACollectionDeleteAction.test.js +2 -2
  50. package/dist/utils/CheckYourAnswers/getCYARow.js +13 -11
  51. package/dist/utils/CheckYourAnswers/getCYARowsForCollection.js +8 -8
  52. package/dist/utils/CheckYourAnswers/getCYARowsForCollectionPage.js +25 -22
  53. package/dist/utils/CheckYourAnswers/getCYARowsForContainer.js +1 -0
  54. package/dist/utils/CheckYourAnswers/showComponentCYA.js +1 -1
  55. package/dist/utils/CollectionPage/duplicateCollectionPageActiveEntry.js +1 -0
  56. package/dist/utils/CollectionPage/mergeCollectionPages.js +7 -6
  57. package/dist/utils/Component/applyToComponentTree.js +4 -2
  58. package/dist/utils/Component/cleanAttributes.js +7 -1
  59. package/dist/utils/Component/cleanAttributes.test.js +4 -4
  60. package/dist/utils/Component/getComponent.js +8 -6
  61. package/dist/utils/Component/getComponentTests/getComponent.autocomplete.test.js +4 -4
  62. package/dist/utils/Component/getComponentTests/getComponent.calculation.test.js +1 -0
  63. package/dist/utils/Component/getComponentTests/getComponent.checkboxes.test.js +3 -3
  64. package/dist/utils/Component/getComponentTests/getComponent.email.test.js +1 -1
  65. package/dist/utils/Component/getComponentTests/getComponent.file.test.js +1 -1
  66. package/dist/utils/Component/getComponentTests/getComponent.multifile.test.js +1 -1
  67. package/dist/utils/Component/getComponentTests/getComponent.phoneNumber.test.js +1 -1
  68. package/dist/utils/Component/getComponentTests/getComponent.radios.test.js +3 -3
  69. package/dist/utils/Component/getComponentTests/getComponent.text.test.js +1 -1
  70. package/dist/utils/Component/getComponentTests/getComponent.time.test.js +5 -5
  71. package/dist/utils/Component/setupContainerComponentsPath.js +2 -0
  72. package/dist/utils/Condition/meetsCondition.js +2 -1
  73. package/dist/utils/Condition/setupConditions.js +2 -2
  74. package/dist/utils/Container/setupNesting.js +5 -1
  75. package/dist/utils/Data/applyFormula.js +16 -10
  76. package/dist/utils/Data/getAutocompleteSource.js +3 -1
  77. package/dist/utils/Data/getOptions.js +3 -2
  78. package/dist/utils/Data/setupFormData.js +4 -2
  79. package/dist/utils/FormPage/getFormPage.js +1 -1
  80. package/dist/utils/FormPage/getPageActions.js +5 -3
  81. package/dist/utils/FormPage/showFormPage.js +2 -2
  82. package/dist/utils/FormPage/showFormPageCYA.js +1 -0
  83. package/dist/utils/FormPage/useComponent.js +1 -0
  84. package/dist/utils/Format/formatDataForComponent.js +2 -1
  85. package/dist/utils/Meta/index.js +1 -2
  86. package/dist/utils/Operate/getFirstOf.test.js +2 -1
  87. package/dist/utils/Operate/persistValueInFormData.js +1 -0
  88. package/dist/utils/Operate/persistValueInFormData.test.js +1 -1
  89. package/dist/utils/Operate/setValueInFormData.test.js +1 -1
  90. package/dist/utils/Operate/shouldRun.js +16 -13
  91. package/dist/utils/Validate/additional/index.js +2 -1
  92. package/dist/utils/Validate/additional/mustBeEarlierDateTime.js +1 -1
  93. package/dist/utils/Validate/additional/mustBeEarlierDateTime.test.js +2 -2
  94. package/dist/utils/Validate/additional/mustBeInTheFuture.js +1 -1
  95. package/dist/utils/Validate/additional/mustBeInThePast.js +5 -5
  96. package/dist/utils/Validate/additional/mustEnterAtLeastOne.js +1 -0
  97. package/dist/utils/Validate/additional/utils.js +16 -16
  98. package/dist/utils/Validate/validateCollection.js +3 -3
  99. package/dist/utils/Validate/validateComponent.js +26 -20
  100. package/dist/utils/Validate/validateContainer.js +2 -2
  101. package/dist/utils/Validate/validateDate.js +2 -1
  102. package/dist/utils/Validate/validateEmail.js +1 -0
  103. package/dist/utils/Validate/validatePage.js +6 -3
  104. package/dist/utils/Validate/validatePage.test.js +9 -18
  105. package/dist/utils/Validate/validateRegex.js +2 -5
  106. package/dist/utils/Validate/validateRequired.js +2 -4
  107. package/package.json +3 -2
@@ -40,8 +40,8 @@ describe('components', function () {
40
40
  }]
41
41
  };
42
42
  var updatedPatchRadios = (0, _cleanHiddenNestedData.default)(patchRadios, pageRadios);
43
- expect(updatedPatchRadios['nested1']).toBeFalsy();
44
- expect(updatedPatchRadios['nested2']).toBeTruthy();
43
+ expect(updatedPatchRadios.nested1).toBeFalsy();
44
+ expect(updatedPatchRadios.nested2).toBeTruthy();
45
45
  });
46
46
  it('should remove data corresponding to hidden nested components in checkboxes', function () {
47
47
  var patchCheckboxes = {
@@ -75,8 +75,8 @@ describe('components', function () {
75
75
  }]
76
76
  };
77
77
  var updatedPatchCheckboxes = (0, _cleanHiddenNestedData.default)(patchCheckboxes, pageCheckboxes);
78
- expect(updatedPatchCheckboxes['nested1']).toBeFalsy();
79
- expect(updatedPatchCheckboxes['nested2']).toBeTruthy();
78
+ expect(updatedPatchCheckboxes.nested1).toBeFalsy();
79
+ expect(updatedPatchCheckboxes.nested2).toBeTruthy();
80
80
  });
81
81
  it('remove data corresponding to hidden nested components within the active collection entry', function () {
82
82
  var patch = {
@@ -121,10 +121,10 @@ describe('components', function () {
121
121
  }]
122
122
  };
123
123
  var updatedPatch = (0, _cleanHiddenNestedData.default)(patch, page);
124
- expect(updatedPatch['collectionName'][0]['nested1']).toBeTruthy();
125
- expect(updatedPatch['collectionName'][0]['nested2']).toBeTruthy();
126
- expect(updatedPatch['collectionName'][1]['nested1']).toBeFalsy();
127
- expect(updatedPatch['collectionName'][1]['nested2']).toBeTruthy();
124
+ expect(updatedPatch.collectionName[0].nested1).toBeTruthy();
125
+ expect(updatedPatch.collectionName[0].nested2).toBeTruthy();
126
+ expect(updatedPatch.collectionName[1].nested1).toBeFalsy();
127
+ expect(updatedPatch.collectionName[1].nested2).toBeTruthy();
128
128
  });
129
129
  });
130
130
  });
@@ -20,9 +20,12 @@ var getCYA = function getCYA(pageId, pages, hub) {
20
20
  return {
21
21
  title: ''
22
22
  };
23
- } else if (pageId === _models.FormPages.CYA) {
23
+ }
24
+ ;
25
+ if (pageId === _models.FormPages.CYA) {
24
26
  return {};
25
27
  }
28
+ ;
26
29
  var currentPage = pages === null || pages === void 0 ? void 0 : pages.find(function (p) {
27
30
  return p.id === pageId;
28
31
  });
@@ -34,6 +37,7 @@ var getCYA = function getCYA(pageId, pages, hub) {
34
37
  hideGroupActions: pageWithConditionals.hideGroupActions
35
38
  };
36
39
  }
40
+ ;
37
41
  return undefined;
38
42
  };
39
43
  var _default = getCYA;
@@ -18,11 +18,14 @@ var getNextHubPageId = function getNextHubPageId(action, currentPageId, pages, f
18
18
  if ((currentPage === null || currentPage === void 0 ? void 0 : currentPage.type) === 'pre-task-list') {
19
19
  return currentPage.id;
20
20
  }
21
+ ;
21
22
  return _models.FormPages.HUB;
22
23
  }
24
+ ;
23
25
  return pages.length > 0 ? pages[0].id : undefined;
24
26
  }
25
- var nextPage = undefined;
27
+ ;
28
+ var nextPage;
26
29
  action === null || action === void 0 ? void 0 : (_action$pages = action.pages) === null || _action$pages === void 0 ? void 0 : _action$pages.forEach(function (page) {
27
30
  if (_FormPage.default.show({
28
31
  show_when: page.show_when
@@ -33,9 +36,6 @@ var getNextHubPageId = function getNextHubPageId(action, currentPageId, pages, f
33
36
  });
34
37
  return nextPage || (action === null || action === void 0 ? void 0 : action.page) || _models.FormPages.HUB;
35
38
  };
36
- var getNextCYAPageId = function getNextCYAPageId(pages, currentPageId, formData) {
37
- return getNextWizardPageId(pages, currentPageId, formData) || _models.FormPages.CYA;
38
- };
39
39
  var getNextWizardPageId = function getNextWizardPageId(pages, currentPageId, formData) {
40
40
  var _page;
41
41
  var nextIndex = pages.findIndex(function (p) {
@@ -43,14 +43,20 @@ var getNextWizardPageId = function getNextWizardPageId(pages, currentPageId, for
43
43
  }) + 1;
44
44
  var page = pages[nextIndex];
45
45
  while (page && !_FormPage.default.show(page, formData)) {
46
- nextIndex++;
46
+ nextIndex += 1;
47
47
  page = pages[nextIndex];
48
48
  }
49
+ ;
49
50
  return ((_page = page) === null || _page === void 0 ? void 0 : _page.id) || undefined;
50
51
  };
52
+ var getNextCYAPageId = function getNextCYAPageId(pages, currentPageId, formData) {
53
+ return getNextWizardPageId(pages, currentPageId, formData) || _models.FormPages.CYA;
54
+ };
51
55
  var getNextFormPageId = function getNextFormPageId(pages) {
52
- // A form has a single page... so always return that id.
53
- return pages.length > 0 ? pages[0].id : undefined;
56
+ return (
57
+ // A form has a single page... so always return that id.
58
+ pages.length > 0 ? pages[0].id : undefined
59
+ );
54
60
  };
55
61
  var getNextPageId = function getNextPageId(formType, pages, currentPageId, action, formData) {
56
62
  if (action) {
@@ -7,7 +7,10 @@ exports.default = void 0;
7
7
  var _models = require("../../../models");
8
8
  var slicePages = function slicePages(pages, currentPageId) {
9
9
  return pages.slice(0, pages.findIndex(function (p) {
10
- return (p === null || p === void 0 ? void 0 : p.id) === currentPageId ? true : false;
10
+ if ((p === null || p === void 0 ? void 0 : p.id) === currentPageId) {
11
+ return true;
12
+ }
13
+ return false;
11
14
  }));
12
15
  };
13
16
  var getRelevantPages = function getRelevantPages(formState, pages, currentTaskPages) {
@@ -15,7 +18,12 @@ var getRelevantPages = function getRelevantPages(formState, pages, currentTaskPa
15
18
  if (((_formState$page = formState.page) === null || _formState$page === void 0 ? void 0 : _formState$page.type) === _models.FormPages.PARTIAL_CYA) {
16
19
  return currentTaskPages ? slicePages(currentTaskPages, formState.pageId) : slicePages(pages, formState.pageId);
17
20
  }
18
- return currentTaskPages ? currentTaskPages : pages;
21
+ ;
22
+ if (currentTaskPages) {
23
+ return currentTaskPages;
24
+ }
25
+ ;
26
+ return pages;
19
27
  };
20
28
  var _default = getRelevantPages;
21
29
  exports.default = _default;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  var _models = require("../../../models");
4
- var _getRelevantPages = _interopRequireDefault(require("../helpers/getRelevantPages"));
4
+ var _getRelevantPages = _interopRequireDefault(require("./getRelevantPages"));
5
5
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
6
  // Local imports
7
7
 
@@ -45,6 +45,16 @@ var allDependentTasksComplete = function allDependentTasksComplete(tasks, mustBe
45
45
  return allComplete && ((_tasks$taskName = tasks[taskName]) === null || _tasks$taskName === void 0 ? void 0 : _tasks$taskName.complete);
46
46
  }, true);
47
47
  };
48
+ var isPreviousTaskComplete = function isPreviousTaskComplete(tasks, taskIndex) {
49
+ var lastTaskState = tasks[taskIndex - 1].state;
50
+ if (lastTaskState === _models.TaskStates.TYPES.COMPLETE) {
51
+ return true;
52
+ }
53
+ if (lastTaskState === _models.TaskStates.TYPES.SKIPPED) {
54
+ return taskIndex - 1 === 0 ? true : isPreviousTaskComplete(tasks, taskIndex - 1);
55
+ }
56
+ return false;
57
+ };
48
58
 
49
59
  /**
50
60
  * return updated task state
@@ -63,11 +73,20 @@ var updateTaskState = function updateTaskState(task, taskIndex, taskList, tasks)
63
73
  if (tasks[task.name]) {
64
74
  return getCurrentTaskState(tasks[task.name], task.state);
65
75
  }
66
- return nonSequential ? task.depends_on && !allDependentTasksComplete(tasks, task.depends_on) ? _models.TaskStates.TYPES.CANNOT_START_YET : _models.TaskStates.TYPES.NOT_STARTED : (
67
- // First task in taskList
68
- taskIndex ?
69
- // any task after a complete task in same section
70
- isPreviousTaskComplete(taskList, taskIndex) : allowFirst) ? _models.TaskStates.TYPES.NOT_STARTED : _models.TaskStates.TYPES.CANNOT_START_YET;
76
+ if (nonSequential) {
77
+ if (task.depends_on && !allDependentTasksComplete(tasks, task.depends_on)) {
78
+ return _models.TaskStates.TYPES.CANNOT_START_YET;
79
+ }
80
+ return _models.TaskStates.TYPES.NOT_STARTED;
81
+ }
82
+ var notStarted = allowFirst;
83
+ if (taskIndex) {
84
+ notStarted = isPreviousTaskComplete(taskList, taskIndex);
85
+ }
86
+ if (notStarted) {
87
+ return _models.TaskStates.TYPES.NOT_STARTED;
88
+ }
89
+ return _models.TaskStates.TYPES.CANNOT_START_YET;
71
90
  };
72
91
 
73
92
  /**
@@ -84,27 +103,20 @@ var updateTasks = function updateTasks(section, tasks, nonSequential, allowFirst
84
103
  return _objectSpread({}, a);
85
104
  });
86
105
  clone.forEach(function (task, taskIndex, taskList) {
87
- var _task$show_when;
106
+ var _currentTask$show_whe;
107
+ var currentTask = task;
88
108
  if (section.skipped) {
89
- task.state = _models.TaskStates.TYPES.SKIPPED;
90
- } else if (data && !_utils.default.Condition.met(task.show_when, data[(_task$show_when = task.show_when) === null || _task$show_when === void 0 ? void 0 : _task$show_when.field])) {
91
- task.state = _models.TaskStates.TYPES.SKIPPED;
109
+ currentTask.state = _models.TaskStates.TYPES.SKIPPED;
110
+ } else if (data && !_utils.default.Condition.met(currentTask.show_when, data[(_currentTask$show_whe = currentTask.show_when) === null || _currentTask$show_whe === void 0 ? void 0 : _currentTask$show_whe.field])) {
111
+ currentTask.state = _models.TaskStates.TYPES.SKIPPED;
92
112
  } else {
93
- task.state = updateTaskState(task, taskIndex, taskList, tasks, nonSequential, allowFirst);
113
+ var _task = task;
114
+ _task.state = updateTaskState(currentTask, taskIndex, taskList, tasks, nonSequential, allowFirst);
94
115
  }
116
+ ;
95
117
  });
96
118
  return clone;
97
119
  };
98
- var isPreviousTaskComplete = function isPreviousTaskComplete(tasks, taskIndex) {
99
- var lastTaskState = tasks[taskIndex - 1].state;
100
- if (lastTaskState === _models.TaskStates.TYPES.COMPLETE) {
101
- return true;
102
- }
103
- if (lastTaskState === _models.TaskStates.TYPES.SKIPPED) {
104
- return taskIndex - 1 === 0 ? true : isPreviousTaskComplete(tasks, taskIndex - 1);
105
- }
106
- return false;
107
- };
108
120
 
109
121
  /**
110
122
  * Checks if the previous section has been completed. If the last section
@@ -142,14 +154,16 @@ var getUpdatedSectionStates = function getUpdatedSectionStates(sections, tasks)
142
154
  return _objectSpread({}, a);
143
155
  });
144
156
  clone.forEach(function (section, sectionIndex, sectionList) {
145
- var _section$show_when;
157
+ var _currentSection$show_;
158
+ var currentSection = section;
146
159
  var allowFirst = sectionIndex === 0 || isPreviousSectionComplete(sectionList, sectionIndex);
147
160
  // Support a single show_when check on a section. Support for an
148
161
  // array of checks will have to be added if required.
149
- if (data && !_utils.default.Condition.met(section.show_when, data[(_section$show_when = section.show_when) === null || _section$show_when === void 0 ? void 0 : _section$show_when.field])) {
150
- section.skipped = true;
162
+ if (data && !_utils.default.Condition.met(currentSection.show_when, data[(_currentSection$show_ = currentSection.show_when) === null || _currentSection$show_ === void 0 ? void 0 : _currentSection$show_.field])) {
163
+ currentSection.skipped = true;
151
164
  }
152
- section.tasks = updateTasks(section, tasks, nonSequential, allowFirst, data);
165
+ ;
166
+ currentSection.tasks = updateTasks(currentSection, tasks, nonSequential, allowFirst, data);
153
167
  });
154
168
  return clone;
155
169
  };
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.helpers = exports.default = void 0;
6
+ exports.default = void 0;
7
7
  var _canActionProceed = _interopRequireDefault(require("./canActionProceed"));
8
8
  var _canCYASubmit = _interopRequireDefault(require("./canCYASubmit"));
9
9
  var _cleanHiddenNestedData = _interopRequireDefault(require("./cleanHiddenNestedData"));
@@ -27,6 +27,5 @@ var helpers = {
27
27
  getSubmissionStatus: _getSubmissionStatus.default,
28
28
  getUpdatedSectionStates: _getUpdatedSectionStates.default
29
29
  };
30
- exports.helpers = helpers;
31
30
  var _default = helpers;
32
31
  exports.default = _default;
@@ -41,7 +41,7 @@ var onCYAAction = function onCYAAction(setPagePoint, action, pages, validate, co
41
41
  }
42
42
  }
43
43
  if (action.type === _models.PageAction.TYPES.SAVE_AND_CONTINUE && hub === _models.HubFormats.TASK) {
44
- var shouldValidate = !(action.hasOwnProperty('validate') && !action.validate);
44
+ var shouldValidate = !(Object.prototype.hasOwnProperty.call(action, 'validate') && !action.validate);
45
45
  var canSubmit = shouldValidate ? _helpers.default.canCYASubmit(currentTask.fullPages, validate.pages) : true;
46
46
  if (canSubmit) {
47
47
  var _submissionData = _utils.default.Format.form({
@@ -76,7 +76,7 @@ var onCYAAction = function onCYAAction(setPagePoint, action, pages, validate, co
76
76
  }
77
77
  }
78
78
  if (action.type === _models.PageAction.TYPES.SAVE_AND_RETURN) {
79
- var _shouldValidate = !(action.hasOwnProperty('validate') && !action.validate);
79
+ var _shouldValidate = !(Object.prototype.hasOwnProperty.call(action, 'validate') && !action.validate);
80
80
  var _canSubmit = _shouldValidate ? _helpers.default.canCYASubmit(currentTask.fullPages, validate.pages) : true;
81
81
  if (_canSubmit) {
82
82
  var _submissionData3 = _utils.default.Format.form({
@@ -17,7 +17,7 @@ jest.mock('./handlers', function () {
17
17
  submissionErrorCalls: 0,
18
18
  submissionErrorArgs: [],
19
19
  submissionError: function submissionError(errors, addErrors) {
20
- this.submissionErrorCalls++;
20
+ this.submissionErrorCalls += 1;
21
21
  this.submissionErrorArgs.push(errors);
22
22
  if (typeof addErrors === 'function') {
23
23
  addErrors(errors);
@@ -34,22 +34,22 @@ jest.mock('./helpers', function () {
34
34
  canCYASubmitResult: true,
35
35
  canCYASubmitCalls: 0,
36
36
  canCYASubmit: function canCYASubmit() {
37
- this.canCYASubmitCalls++;
37
+ this.canCYASubmitCalls += 1;
38
38
  return this.canCYASubmitResult;
39
39
  },
40
40
  getNextPageIdCalls: 0,
41
41
  getNextPageId: function getNextPageId() {
42
- this.getNextPageIdCalls++;
42
+ this.getNextPageIdCalls += 1;
43
43
  return 'page2';
44
44
  },
45
45
  getFormStateCalls: 0,
46
46
  getFormState: function getFormState() {
47
- this.getFormStateCalls++;
47
+ this.getFormStateCalls += 1;
48
48
  return {};
49
49
  },
50
50
  getSubmissionStatusCalls: 0,
51
51
  getSubmissionStatus: function getSubmissionStatus() {
52
- this.getSubmissionStatusCalls++;
52
+ this.getSubmissionStatusCalls += 1;
53
53
  return 'Good to go!';
54
54
  },
55
55
  reset: function reset() {
@@ -67,7 +67,7 @@ jest.mock('../../utils', function () {
67
67
  Format: {
68
68
  formCalls: 0,
69
69
  form: function form() {
70
- this.formCalls++;
70
+ this.formCalls += 1;
71
71
  return {
72
72
  id: 'formId'
73
73
  };
@@ -83,7 +83,7 @@ describe('components.FormRenderer.onCYAAction', function () {
83
83
  onSubmitCalls: 0,
84
84
  onSubmitArgs: [],
85
85
  onSubmit: function onSubmit(type, payload, onSuccess, onError) {
86
- this.onSubmitCalls++;
86
+ this.onSubmitCalls += 1;
87
87
  this.onSubmitArgs.push({
88
88
  type: type,
89
89
  payload: payload
@@ -100,11 +100,11 @@ describe('components.FormRenderer.onCYAAction', function () {
100
100
  },
101
101
  onFormCompleteCalls: 0,
102
102
  onFormComplete: function onFormComplete() {
103
- this.onFormCompleteCalls++;
103
+ this.onFormCompleteCalls += 1;
104
104
  },
105
105
  onCancelCalls: 0,
106
106
  onCancel: function onCancel() {
107
- this.onCancelCalls++;
107
+ this.onCancelCalls += 1;
108
108
  },
109
109
  reset: function reset() {
110
110
  this.onSubmitCalls = 0;
@@ -116,25 +116,25 @@ describe('components.FormRenderer.onCYAAction', function () {
116
116
  var setPagePointCalls = 0;
117
117
  var setPagePointArgs = [];
118
118
  var mockSetPagePoint = function mockSetPagePoint(point) {
119
- setPagePointCalls++;
119
+ setPagePointCalls += 1;
120
120
  setPagePointArgs.push(point);
121
121
  };
122
122
  var setDataCalls = 0;
123
123
  var setDataArgs = [];
124
124
  var mockSetData = function mockSetData(data) {
125
- setDataCalls++;
125
+ setDataCalls += 1;
126
126
  setDataArgs.push(data);
127
127
  };
128
128
  var onPageChangeCalls = 0;
129
129
  var onPageChangeArgs = [];
130
130
  var mockOnPageChange = function mockOnPageChange(pageId) {
131
- onPageChangeCalls++;
131
+ onPageChangeCalls += 1;
132
132
  onPageChangeArgs.push(pageId);
133
133
  };
134
134
  var addErrorsCalls = 0;
135
135
  var addErrorsArgs = [];
136
136
  var mockAddErrors = function mockAddErrors(errors) {
137
- addErrorsCalls++;
137
+ addErrorsCalls += 1;
138
138
  addErrorsArgs.push(errors);
139
139
  };
140
140
  var COMPONENTS = [{
@@ -24,18 +24,25 @@ var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data,
24
24
  hooks.onCancel();
25
25
  return;
26
26
  }
27
+ ;
27
28
  // Save a copy of data in case submit errors and we need to revert
28
29
  var preSubmitData = _objectSpread({}, data);
29
30
  // Re-apply the patch to the page's formData.
30
31
  // This should normally have no effect but will prevent issues
31
32
  // with validation if formData happens to have been wiped.
32
- formState.page.formData = _objectSpread(_objectSpread({}, formState.page.formData), patch);
33
+ var form = formState;
34
+ form.page.formData = _objectSpread(_objectSpread({}, form.page.formData), patch);
33
35
  // Check to see whether the action is able to proceed, which in
34
36
  // in the case of a submission will validate the fields in the page.
35
- if (_helpers.default.canActionProceed(action, formState.page, validate.page)) {
36
- patch = _helpers.default.cleanHiddenNestedData(patch, formState.page);
37
+ if (_helpers.default.canActionProceed(action, form.page, validate.page)) {
38
+ var _patch = patch;
39
+ _patch = _helpers.default.cleanHiddenNestedData(patch, form.page);
37
40
  if (action.addToFormData) {
38
- formState.page.formData[action.addToFormData.field] = action.addToFormData.value;
41
+ var operations = Array.isArray(action.addToFormData) ? action.addToFormData : [action.addToFormData];
42
+ operations.forEach(function (op) {
43
+ _utils.default.Data.setDataItem(formState.page.formData, op.field, op.value);
44
+ });
45
+ form.page.formData[action.addToFormData.field] = action.addToFormData.value;
39
46
  }
40
47
  if (action.type === _models.PageAction.TYPES.NAVIGATE) {
41
48
  _handlers.default.navigate(action, pageId, onPageChange);
@@ -43,6 +50,7 @@ var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data,
43
50
  var pageUpdate = function pageUpdate(next) {
44
51
  return onPageChange(_helpers.default.getNextPageId(type, pages, pageId, action, next));
45
52
  };
53
+ /* eslint-disable no-case-declarations */
46
54
  switch (action.type) {
47
55
  case _models.PageAction.TYPES.SUBMIT:
48
56
  setPagePoint('submit');
@@ -54,7 +62,7 @@ var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data,
54
62
  };
55
63
  break;
56
64
  case _models.PageAction.TYPES.COLLECTION_ADD:
57
- formState.page.formData["".concat(action.collection, "ActiveId")] = Date.now().toString();
65
+ form.page.formData["".concat(action.collection, "ActiveId")] = Date.now().toString();
58
66
  pageUpdate = function pageUpdate() {
59
67
  return _handlers.default.navigate(action, pageId, onPageChange);
60
68
  };
@@ -65,17 +73,19 @@ var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data,
65
73
  return _handlers.default.navigate(action, pageId, onPageChange);
66
74
  };
67
75
  }
76
+ ;
68
77
  break;
69
78
  case _models.PageAction.TYPES.COLLECTION_REMOVE:
70
- var activeId = formState.page.formData["".concat(action.collection, "ActiveId")];
71
- formState.page.formData["".concat(action.collection)] = formState.page.formData["".concat(action.collection)].map(function (entry) {
79
+ var activeId = form.page.formData["".concat(action.collection, "ActiveId")];
80
+ form.page.formData["".concat(action.collection)] = form.page.formData["".concat(action.collection)].map(function (entry) {
72
81
  if (entry.id === activeId) {
73
82
  // Store the entry.
74
83
  if (action.recordRemoval) {
75
- formState.page.formData["".concat(action.collection, "LastRemoved")] = _objectSpread({}, entry);
84
+ form.page.formData["".concat(action.collection, "LastRemoved")] = _objectSpread({}, entry);
76
85
  }
77
86
  return null;
78
87
  }
88
+ ;
79
89
  return entry;
80
90
  }).filter(function (e) {
81
91
  return !!e;
@@ -84,24 +94,31 @@ var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data,
84
94
  default:
85
95
  break;
86
96
  }
97
+ ;
98
+ /* eslint-enable no-case-declarations */
99
+
87
100
  // Save draft or submit.
88
101
  var submissionData = _utils.default.Format.form({
89
102
  pages: pages,
90
103
  components: components
91
104
  }, _objectSpread(_objectSpread(_objectSpread({}, data), patch), formState.page.formData), _models.EventTypes.SUBMIT);
92
105
  submissionData.formStatus = _helpers.default.getSubmissionStatus(type, pages, pageId, action, submissionData, currentTask, true, hubDetails === null || hubDetails === void 0 ? void 0 : hubDetails.sections);
93
- if (patch) {
106
+ if (_patch) {
94
107
  setData(submissionData);
95
108
  }
109
+ ;
96
110
 
97
111
  // In case of hub-and-spoke if patchLabel has changed then
98
112
  // save name and value to variables for call to onSubmit hook
99
113
  var changedFieldName;
100
114
  var changedFieldValue;
101
115
  if (type === _models.FormTypes.HUB && Object.keys(patchLabel).length > 0) {
116
+ /* eslint-disable prefer-destructuring */
102
117
  changedFieldName = Object.keys(patchLabel)[0];
103
118
  changedFieldValue = Object.values(patchLabel)[0];
119
+ /* eslint-enable prefer-destructuring */
104
120
  }
121
+ ;
105
122
 
106
123
  // Now submit the data to the backend...
107
124
  hooks.onSubmit(action.type, submissionData, function (response) {
@@ -117,7 +134,9 @@ var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data,
117
134
  setData(_objectSpread({}, preSubmitData));
118
135
  }, changedFieldName, changedFieldValue, pageId);
119
136
  }
137
+ ;
120
138
  }
139
+ ;
121
140
  };
122
141
  var _default = onPageAction;
123
142
  exports.default = _default;
@@ -16,12 +16,12 @@ jest.mock('./handlers', function () {
16
16
  return {
17
17
  navigateCalls: 0,
18
18
  navigate: function navigate() {
19
- this.navigateCalls++;
19
+ this.navigateCalls += 1;
20
20
  },
21
21
  submissionErrorCalls: 0,
22
22
  submissionErrorArgs: [],
23
23
  submissionError: function submissionError(errors, addErrors) {
24
- this.submissionErrorCalls++;
24
+ this.submissionErrorCalls += 1;
25
25
  this.submissionErrorArgs.push(errors);
26
26
  if (typeof addErrors === 'function') {
27
27
  addErrors(errors);
@@ -39,7 +39,7 @@ jest.mock('./helpers', function () {
39
39
  canActionProceedCalls: 0,
40
40
  canActionProceedResult: true,
41
41
  canActionProceed: function canActionProceed(action, page, validator) {
42
- this.canActionProceedCalls++;
42
+ this.canActionProceedCalls += 1;
43
43
  if (typeof validator === 'function') {
44
44
  validator();
45
45
  }
@@ -47,17 +47,17 @@ jest.mock('./helpers', function () {
47
47
  },
48
48
  cleanHiddenNestedDataCalls: 0,
49
49
  cleanHiddenNestedData: function cleanHiddenNestedData(patch) {
50
- this.cleanHiddenNestedDataCalls++;
50
+ this.cleanHiddenNestedDataCalls += 1;
51
51
  return patch;
52
52
  },
53
53
  getNextPageIdCalls: 0,
54
54
  getNextPageId: function getNextPageId() {
55
- this.getNextPageIdCalls++;
55
+ this.getNextPageIdCalls += 1;
56
56
  return 'page2';
57
57
  },
58
58
  getSubmissionStatusCalls: 0,
59
59
  getSubmissionStatus: function getSubmissionStatus() {
60
- this.getSubmissionStatusCalls++;
60
+ this.getSubmissionStatusCalls += 1;
61
61
  return 'Good to go!';
62
62
  },
63
63
  reset: function reset() {
@@ -71,11 +71,12 @@ jest.mock('./helpers', function () {
71
71
  };
72
72
  });
73
73
  jest.mock('../../utils', function () {
74
- return {
74
+ var originalModule = jest.requireActual('../../utils');
75
+ return _objectSpread(_objectSpread({}, originalModule.default), {}, {
75
76
  Format: {
76
77
  formCalls: 0,
77
- form: function form(_form, data, eventType) {
78
- this.formCalls++;
78
+ form: function form(_form, data) {
79
+ this.formCalls += 1;
79
80
  return data;
80
81
  }
81
82
  },
@@ -83,7 +84,7 @@ jest.mock('../../utils', function () {
83
84
  duplicateActiveEntryCalls: 0,
84
85
  duplicateActiveEntryResult: true,
85
86
  duplicateActiveEntry: function duplicateActiveEntry() {
86
- this.duplicateActiveEntryCalls++;
87
+ this.duplicateActiveEntryCalls += 1;
87
88
  return this.duplicateActiveEntryResult;
88
89
  }
89
90
  },
@@ -92,14 +93,14 @@ jest.mock('../../utils', function () {
92
93
  this.CollectionPage.duplicateActiveEntryCalls = 0;
93
94
  this.duplicateActiveEntryResult = true;
94
95
  }
95
- };
96
+ });
96
97
  });
97
98
  describe('components.FormRenderer.onPageAction', function () {
98
99
  var MOCK_HOOKS = {
99
100
  onSubmitCalls: 0,
100
101
  onSubmitArgs: [],
101
102
  onSubmit: function onSubmit(type, payload, onSuccess, onError, changedFieldName, changedFieldValue) {
102
- this.onSubmitCalls++;
103
+ this.onSubmitCalls += 1;
103
104
  this.onSubmitArgs.push({
104
105
  type: type,
105
106
  payload: payload,
@@ -118,11 +119,11 @@ describe('components.FormRenderer.onPageAction', function () {
118
119
  },
119
120
  onFormCompleteCalls: 0,
120
121
  onFormComplete: function onFormComplete() {
121
- this.onFormCompleteCalls++;
122
+ this.onFormCompleteCalls += 1;
122
123
  },
123
124
  onCancelCalls: 0,
124
125
  onCancel: function onCancel() {
125
- this.onCancelCalls++;
126
+ this.onCancelCalls += 1;
126
127
  },
127
128
  reset: function reset() {
128
129
  this.onSubmitCalls = 0;
@@ -134,7 +135,7 @@ describe('components.FormRenderer.onPageAction', function () {
134
135
  var MOCK_VALIDATE = {
135
136
  pageCalls: 0,
136
137
  page: function page() {
137
- MOCK_VALIDATE.pageCalls++;
138
+ MOCK_VALIDATE.pageCalls += 1;
138
139
  },
139
140
  reset: function reset() {
140
141
  this.pageCalls = 0;
@@ -143,19 +144,19 @@ describe('components.FormRenderer.onPageAction', function () {
143
144
  var setPagePointCalls = 0;
144
145
  var setPagePointArgs = [];
145
146
  var mockSetPagePoint = function mockSetPagePoint(point) {
146
- setPagePointCalls++;
147
+ setPagePointCalls += 1;
147
148
  setPagePointArgs.push(point);
148
149
  };
149
150
  var setDataCalls = 0;
150
151
  var setDataArgs = [];
151
152
  var mockSetData = function mockSetData(data) {
152
- setDataCalls++;
153
+ setDataCalls += 1;
153
154
  setDataArgs.push(data);
154
155
  };
155
156
  var onPageChangeCalls = 0;
156
157
  var onPageChangeArgs = [];
157
158
  var mockOnPageChange = function mockOnPageChange(pageId) {
158
- onPageChangeCalls++;
159
+ onPageChangeCalls += 1;
159
160
  onPageChangeArgs.push(pageId);
160
161
  };
161
162
  var addErrorsArgs = [];
@@ -594,6 +595,41 @@ describe('components.FormRenderer.onPageAction', function () {
594
595
  alpha: '123'
595
596
  });
596
597
  });
598
+ it('should work for an array of formData', function () {
599
+ var FORM_STATE = {
600
+ page: {
601
+ formData: {
602
+ testCollection: []
603
+ }
604
+ }
605
+ };
606
+ var ACTION = {
607
+ type: _models.PageAction.TYPES.NAVIGATE,
608
+ collection: 'testCollection',
609
+ addToFormData: [{
610
+ field: 'alpha',
611
+ value: '123'
612
+ }, {
613
+ field: 'beta.gamma',
614
+ value: '456'
615
+ }]
616
+ };
617
+ var CUSTOM_ARGS = _objectSpread(_objectSpread({}, ARGS), {}, {
618
+ formState: FORM_STATE,
619
+ action: ACTION
620
+ });
621
+ _onPageAction.default.apply(void 0, Object.values(CUSTOM_ARGS));
622
+ preActionChecks();
623
+ // Not doing the usual post-action checks here
624
+ // as a navigate action should stop at calling
625
+ // hooks.navigate.
626
+ expect(FORM_STATE.page.formData).toMatchObject({
627
+ alpha: '123',
628
+ beta: {
629
+ gamma: '456'
630
+ }
631
+ });
632
+ });
597
633
  });
598
634
  describe('recording patchLabel fields correctly when it is defined', function () {
599
635
  var VALID_ACTIONS = Object.values(_models.PageAction.TYPES).filter(function (a) {