@ukhomeoffice/cop-react-form-renderer 6.15.12-alpha → 6.15.12

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 (48) hide show
  1. package/dist/components/FormRenderer/FormRenderer.js +20 -15
  2. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/cop-reassign-task-to-rcc.json +1 -0
  3. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-containerised.json +1 -0
  4. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-dependent-component-nested-block.json +1 -0
  5. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-dependent-component-nested.json +1 -0
  6. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-refdata.json +1 -0
  7. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-target-component-nested.json +1 -0
  8. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens.json +1 -0
  9. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-show-whens-page-hidden.json +1 -0
  10. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-cop-airpax.json +1 -0
  11. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-cop-mandec.json +1 -0
  12. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-collection-component-dependent-on-external-data.json +1 -0
  13. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-collection-component.json +1 -0
  14. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-referring-to-collection.json +1 -0
  15. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-referring-to-hidden-collection.json +1 -0
  16. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-show-when-in-component-and-page.json +1 -0
  17. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-with-nested-questions.json +1 -0
  18. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component.json +1 -0
  19. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-containerised-component.json +1 -0
  20. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-embedded-collection-component.json +1 -0
  21. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-embedded-component.json +1 -0
  22. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-entire-collection.json +114 -0
  23. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-multilevel-containerised-component-leaf-hidden.json +1 -0
  24. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-multilevel-containerised-component.json +1 -0
  25. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-options.json +1 -0
  26. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-collection.json +1 -0
  27. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-component-used-elsewhere.json +1 -0
  28. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-same-component-reused.json +1 -0
  29. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page.json +1 -0
  30. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-nested-answers-hidden-by-option.json +1 -0
  31. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-page-nested-radio-component.json +201 -0
  32. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-page-same-component-reused-one-shown.json +1 -0
  33. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-variance-breach.json +4272 -0
  34. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-variance-breach-with-upload-files.json +1264 -0
  35. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-entire-collection.json +20 -0
  36. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-page-nested-radio-component.json +45 -0
  37. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-entire-collection-removed.json +3 -0
  38. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-page-nested-radio-component-removed.json +45 -0
  39. package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.js +15 -3
  40. package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.test.js +65 -33
  41. package/dist/components/FormRenderer/helpers/getUpdatedSectionStates.js +6 -0
  42. package/dist/components/FormRenderer/helpers/getUpdatedSectionStates.test.js +20 -0
  43. package/dist/components/FormRenderer/onCYAAction.js +3 -3
  44. package/dist/components/FormRenderer/onCYAAction.test.js +2 -1
  45. package/dist/components/FormRenderer/onPageAction.js +2 -2
  46. package/dist/components/FormRenderer/onPageAction.test.js +2 -1
  47. package/dist/utils/CollectionPage/mergeCollectionPages.js +8 -2
  48. package/package.json +2 -1
@@ -0,0 +1,20 @@
1
+ {
2
+ "alpha": "alpha-value",
3
+ "itemsActiveId": "8b9b7671-d06d-447e-a907-e9215072741a",
4
+ "items": [
5
+ {
6
+ "id": "da056129-34e9-4218-8e98-574856977727",
7
+ "itemCategory": "alcohol",
8
+ "itemSubCategory": "itemSubCategory-value",
9
+ "brandText": "brandText-value",
10
+ "abvDetails": "abv-value"
11
+ },
12
+ {
13
+ "id": "da056129-34e9-4218-8e98-574856977727",
14
+ "itemCategory": "weapons",
15
+ "itemSubCategory": "ARM",
16
+ "brandText": "brandText-value",
17
+ "firearmCheck": "firearmCheck-value"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "id": "8d4674c4-1adb-11f0-a7ba-620783054865",
3
+ "businessKey": "DEV-20250416-1142",
4
+ "port": {
5
+ "id": 1639,
6
+ "name": "Dover",
7
+ "sea": true,
8
+ "air": false,
9
+ "land": false,
10
+ "rail": false,
11
+ "countryid": 234,
12
+ "iata": null,
13
+ "value": "1639",
14
+ "label": "Dover",
15
+ "hint": ""
16
+ },
17
+ "modeOfTransport": {
18
+ "id": 9,
19
+ "mode": "RoRo Tourist",
20
+ "modecode": "rorotour",
21
+ "crossingtype": [
22
+ "sea"
23
+ ],
24
+ "value": "RoRo Tourist",
25
+ "label": "RoRo Tourist"
26
+ },
27
+ "whatHappened": "peopleHidingVehicle",
28
+ "formInstanceId": "5b3b4c37-df21-4e61-bffe-3034c55d4429",
29
+ "driverOwnVehicle": "noSomeoneElseOwns",
30
+ "otherVehicleOwner": {
31
+ "vehicleOwnerAddress": "no",
32
+ "fullName": "Robert Flecher",
33
+ "telephoneNumber": "07835442994",
34
+ "emailAddress": "robrotheram@gmail.com",
35
+ "nonUkAddressText": "Dickinson St",
36
+ "country": {
37
+ "id": 211,
38
+ "name": "Sudan (the)",
39
+ "iso31661alpha3": "SDN",
40
+ "value": "211",
41
+ "label": "Sudan (the)",
42
+ "hint": ""
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "id": "8d4674c4-1adb-11f0-a7ba-620783054865",
3
+ "businessKey": "DEV-20250416-1142",
4
+ "port": {
5
+ "id": 1639,
6
+ "name": "Dover",
7
+ "sea": true,
8
+ "air": false,
9
+ "land": false,
10
+ "rail": false,
11
+ "countryid": 234,
12
+ "iata": null,
13
+ "value": "1639",
14
+ "label": "Dover",
15
+ "hint": ""
16
+ },
17
+ "modeOfTransport": {
18
+ "id": 9,
19
+ "mode": "RoRo Tourist",
20
+ "modecode": "rorotour",
21
+ "crossingtype": [
22
+ "sea"
23
+ ],
24
+ "value": "RoRo Tourist",
25
+ "label": "RoRo Tourist"
26
+ },
27
+ "whatHappened": "peopleHidingVehicle",
28
+ "formInstanceId": "5b3b4c37-df21-4e61-bffe-3034c55d4429",
29
+ "driverOwnVehicle": "noSomeoneElseOwns",
30
+ "otherVehicleOwner": {
31
+ "vehicleOwnerAddress": "no",
32
+ "fullName": "Robert Flecher",
33
+ "telephoneNumber": "07835442994",
34
+ "emailAddress": "robrotheram@gmail.com",
35
+ "nonUkAddressText": "Dickinson St",
36
+ "country": {
37
+ "id": 211,
38
+ "name": "Sudan (the)",
39
+ "iso31661alpha3": "SDN",
40
+ "value": "211",
41
+ "label": "Sudan (the)",
42
+ "hint": ""
43
+ }
44
+ }
45
+ }
@@ -7,6 +7,7 @@ exports.default = void 0;
7
7
  var _mergeCollectionPages = _interopRequireDefault(require("../../../utils/CollectionPage/mergeCollectionPages"));
8
8
  var Utils = _interopRequireWildcard(require("./clearOutUncompletedRoutesUtils"));
9
9
  var _optionIsSelected = _interopRequireDefault(require("../../../utils/Component/optionIsSelected"));
10
+ var _getSourceData = _interopRequireDefault(require("../../../utils/Data/getSourceData"));
10
11
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
12
  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 && {}.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; }
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -67,7 +68,8 @@ const createComponentMapsFromForm = (condensedPages, componentByIdMap, component
67
68
  var _component$data2;
68
69
  component === null || component === void 0 || (_component$data2 = component.data) === null || _component$data2 === void 0 || (_component$data2 = _component$data2.options) === null || _component$data2 === void 0 || _component$data2.forEach(option => {
69
70
  if (option.nested) {
70
- if (!(0, _optionIsSelected.default)(formData[component.id], option)) {
71
+ // in container need to use the JPath for the data since the field that the component is looking at is nested in the container.
72
+ if (!(0, _optionIsSelected.default)((0, _getSourceData.default)(formData, path), option)) {
71
73
  option.nested.forEach(nestedComponent => {
72
74
  // delete hidden nested question payload items when the parent option is not selected
73
75
  Utils.deleteNodeByPath(formData, Utils.getNestedQuestionPath(path, nestedComponent.fieldId));
@@ -210,7 +212,10 @@ const resolveComponentDependenciesGraph = (allDependencyRelationships, allCompon
210
212
  * rules for each payload object.
211
213
  *
212
214
  * Some of the rules may be dependent on payload items outside the collection. These will already have been cleansed
213
- * so will be in a reliable state.
215
+ * so will be in a reliable state.
216
+ *
217
+ * It is possible in the form spec to specify in the master page that the whole collection has a show_when rule.
218
+ * If this is the case, evaluate the rule and if false delete the entire collection array.
214
219
  *
215
220
  * @param {Map} allCollections A map of collection objects, which are a grouping of the pages that make up a single collection
216
221
  * @param {Object} formData The form payload
@@ -219,6 +224,11 @@ const resolveComponentDependenciesGraph = (allDependencyRelationships, allCompon
219
224
  */
220
225
  const cleanseCollectionData = (allCollections, formData, componentByIdMap, componentByFieldIdMap) => {
221
226
  allCollections === null || allCollections === void 0 || allCollections.forEach((collection, collectionName) => {
227
+ if (!Utils.isShowEntity(collection, formData)) {
228
+ // Delete the entire collection array (including activeId) if the master page has an unmet rule
229
+ delete formData[collectionName];
230
+ delete formData["".concat(collectionName, "ActiveId")];
231
+ }
222
232
  const collectionDataArray = formData[collectionName];
223
233
  collectionDataArray === null || collectionDataArray === void 0 || collectionDataArray.forEach(collectionDataEntry => {
224
234
  var _collection$childPage2;
@@ -299,7 +309,9 @@ const cleanseCollectionData = (allCollections, formData, componentByIdMap, compo
299
309
  * @param {*} formData
300
310
  * @returns {*} cleansed form data
301
311
  */
302
- const clearOutUncompletedRoutes = (form, formData) => {
312
+ const clearOutUncompletedRoutes = (cleanseHiddenData, form, formData) => {
313
+ if (!cleanseHiddenData) return formData;
314
+
303
315
  // Load components into maps keyed on id and field for subsequent performant access
304
316
  const componentByIdMap = new Map(form.components.map(c => [c.id, c]));
305
317
  const componentByFieldIdMap = new Map(form.components.map(c => [c.fieldId, c]));
@@ -75,6 +75,9 @@ var _dataChainedComponentShowWhensTargetComponentNestedRemoved = _interopRequire
75
75
  var _formHiddenPageCollection = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-page-collection.json"));
76
76
  var _dataHiddenPageCollection = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-page-collection.json"));
77
77
  var _dataHiddenPageCollectionRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-page-collection-removed.json"));
78
+ var _formHiddenEntireCollection = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-entire-collection.json"));
79
+ var _dataHiddenEntireCollection = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-entire-collection.json"));
80
+ var _dataHiddenEntireCollectionRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-entire-collection-removed.json"));
78
81
  var _formHiddenCollectionComponentDependentOnExternalData = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-collection-component-dependent-on-external-data.json"));
79
82
  var _dataHiddenCollectionComponentDependentOnExternalData = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-collection-component-dependent-on-external-data.json"));
80
83
  var _dataHiddenCollectionComponentDependentOnExternalDataRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-collection-component-dependent-on-external-data-removed.json"));
@@ -93,6 +96,11 @@ var _copAirpaxRemovePhotosAfter = _interopRequireDefault(require("../clear-uncom
93
96
  var _copAirpaxChangeWhatHappenedBefore = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/cop-airpax-change-what-happened-before.json"));
94
97
  var _copAirpaxChangeWhatHappenedAfter = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/cop-airpax-change-what-happened-after.json"));
95
98
  var _copAirpaxCarrier = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/cop-airpax-carrier.json"));
99
+ var _formPageNestedRadioComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-page-nested-radio-component.json"));
100
+ var _dataPageNestedRadioComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-page-nested-radio-component.json"));
101
+ var _dataPageNestedRadioComponentRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-page-nested-radio-component-removed.json"));
102
+ var _formVarianceBreach = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-variance-breach.json"));
103
+ var _copVarianceBreachWithUploadFiles = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/cop-variance-breach-with-upload-files.json"));
96
104
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
97
105
  // Hidden component
98
106
 
@@ -144,6 +152,8 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
144
152
 
145
153
  // Hidden page collection
146
154
 
155
+ // Should remove all collection components if show_when at the master page level
156
+
147
157
  // Hidden collection component, dependent on data external to and internal to collection payload
148
158
 
149
159
  // Mandec business interests
@@ -160,110 +170,120 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
160
170
 
161
171
  // Carrier not removed
162
172
 
173
+ // Form with no componets but componet listed in page.
174
+
175
+ // Upload files not removed from variance breach on in-flight forms with no 'cleanseHiddenData' flag.
176
+
163
177
  describe('FormRenderer', () => {
164
178
  describe('helpers', () => {
165
179
  describe('clearOutUncompletedRoutes', () => {
180
+ it('should not remove upload files from variance breach.', () => {
181
+ const submissionData = JSON.parse(JSON.stringify(_copVarianceBreachWithUploadFiles.default));
182
+ const form = JSON.parse(JSON.stringify(_formVarianceBreach.default));
183
+ const result = _index.default.clearOutUncompletedRoutes(false, form, submissionData);
184
+ expect(result).toEqual(_copVarianceBreachWithUploadFiles.default);
185
+ });
166
186
  it('should remove hidden component.', () => {
167
187
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponent.default));
168
188
  const form = JSON.parse(JSON.stringify(_formHiddenComponent.default));
169
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
189
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
170
190
  expect(result).toEqual(_dataHiddenComponentRemoved.default);
171
191
  });
172
192
  it('should remove hidden component with show_when in page and component.', () => {
173
193
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentShowWhenInComponentAndPage.default));
174
194
  const form = JSON.parse(JSON.stringify(_formHiddenComponentShowWhenInComponentAndPage.default));
175
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
195
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
176
196
  expect(result).toEqual(_dataHiddenComponentShowWhenInComponentAndPageRemoved.default);
177
197
  });
178
198
  it('should remove hidden component embedded in page.', () => {
179
199
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenEmbeddedComponent.default));
180
200
  const form = JSON.parse(JSON.stringify(_formHiddenEmbeddedComponent.default));
181
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
201
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
182
202
  expect(result).toEqual(_dataHiddenEmbeddedComponentRemoved.default);
183
203
  });
184
204
  it('should remove hidden collection component.', () => {
185
205
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenCollectionComponent.default));
186
206
  const form = JSON.parse(JSON.stringify(_formHiddenCollectionComponent.default));
187
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
207
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
188
208
  expect(result).toEqual(_dataHiddenCollectionComponentRemoved.default);
189
209
  });
190
210
  it('should remove hidden embedded collection component.', () => {
191
211
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenEmbeddedCollectionComponent.default));
192
212
  const form = JSON.parse(JSON.stringify(_formHiddenEmbeddedCollectionComponent.default));
193
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
213
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
194
214
  expect(result).toEqual(_dataHiddenEmbeddedCollectionComponentRemoved.default);
195
215
  });
196
216
  it('should remove hidden containerised component.', () => {
197
217
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenContainerisedComponent.default));
198
218
  const form = JSON.parse(JSON.stringify(_formHiddenContainerisedComponent.default));
199
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
219
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
200
220
  expect(result).toEqual(_dataHiddenContainerisedComponentRemoved.default);
201
221
  });
202
222
  it('should remove hidden multi-level containerised components.', () => {
203
223
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenMultilevelContainerisedComponent.default));
204
224
  const form = JSON.parse(JSON.stringify(_formHiddenMultilevelContainerisedComponent.default));
205
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
225
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
206
226
  expect(result).toEqual(_dataHiddenMultilevelContainerisedComponentRemoved.default);
207
227
  });
208
228
  it('should remove hidden leaf-level in a multi-level containerised component.', () => {
209
229
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenMultilevelContainerisedComponentLeafHidden.default));
210
230
  const form = JSON.parse(JSON.stringify(_formHiddenMultilevelContainerisedComponentLeafHidden.default));
211
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
231
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
212
232
  expect(result).toEqual(_dataHiddenMultilevelContainerisedComponentLeafHiddenRemoved.default);
213
233
  });
214
234
  it('should remove hidden component with options.', () => {
215
235
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenOptions.default));
216
236
  const form = JSON.parse(JSON.stringify(_formHiddenOptions.default));
217
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
237
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
218
238
  expect(result).toEqual(_dataHiddenOptionsRemoved.default);
219
239
  });
220
240
  it('should remove hidden component with nested questions in options.', () => {
221
241
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentWithNestedQuestions.default));
222
242
  const form = JSON.parse(JSON.stringify(_formHiddenComponentWithNestedQuestions.default));
223
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
243
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
224
244
  expect(result).toEqual(_dataHiddenComponentWithNestedQuestionsRemoved.default);
225
245
  });
226
246
  it('should remove answers associated with unselected options in a containerised component.', () => {
227
247
  const submissionData = JSON.parse(JSON.stringify(_dataNestedAnswersHiddenByOption.default));
228
248
  const form = JSON.parse(JSON.stringify(_formNestedAnswersHiddenByOption.default));
229
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
249
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
230
250
  expect(result).toEqual(_dataNestedAnswersHiddenByOptionRemoved.default);
231
251
  });
232
252
  it('should remove hidden page.', () => {
233
253
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenPage.default));
234
254
  const form = JSON.parse(JSON.stringify(_formHiddenPage.default));
235
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
255
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
236
256
  expect(result).toEqual(_dataHiddenPageRemoved.default);
237
257
  });
238
258
  it('should remove hidden page with same component reused.', () => {
239
259
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageSameComponentReused.default));
240
260
  const form = JSON.parse(JSON.stringify(_formHiddenPageSameComponentReused.default));
241
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
261
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
242
262
  expect(result).toEqual(_dataHiddenPageSameComponentReusedRemoved.default);
243
263
  });
244
264
  it('should show component when reused but only one show_when true.', () => {
245
265
  const submissionData = JSON.parse(JSON.stringify(_dataPageSameComponentReusedOneShown.default));
246
266
  const form = JSON.parse(JSON.stringify(_formPageSameComponentReusedOneShown.default));
247
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
267
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
248
268
  expect(result).toEqual(_dataPageSameComponentReusedOneShownRemoved.default);
249
269
  });
250
270
  it('should remove a hidden collection on a page.', () => {
251
271
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageCollection.default));
252
272
  const form = JSON.parse(JSON.stringify(_formHiddenPageCollection.default));
253
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
273
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
254
274
  expect(result).toEqual(_dataHiddenPageCollectionRemoved.default);
255
275
  });
256
276
  it('hidden component with show_when rule referring to a collection.', () => {
257
277
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentReferringToCollection.default));
258
278
  const form = JSON.parse(JSON.stringify(_formHiddenComponentReferringToCollection.default));
259
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
279
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
260
280
  expect(result).toEqual(_dataHiddenComponentReferringToCollectionRemoved.default);
261
281
  });
262
282
  it('hidden component with show_when rule referring to a hidden collection.', () => {
263
283
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentReferringToHiddenCollection.default));
264
284
  const form = JSON.parse(JSON.stringify(_formHiddenComponentReferringToHiddenCollection.default));
265
285
  try {
266
- _index.default.clearOutUncompletedRoutes(form, submissionData);
286
+ _index.default.clearOutUncompletedRoutes(true, form, submissionData);
267
287
  throw new Error('Expected myFunction to throw an error, but it did not');
268
288
  } catch (error) {
269
289
  expect(error.message).toContain('It is not possible to reliably clean hidden data when a component is dependent');
@@ -272,99 +292,111 @@ describe('FormRenderer', () => {
272
292
  it('should remove hidden collection components whether they are dependent on data inside or outside the collection.', () => {
273
293
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenCollectionComponentDependentOnExternalData.default));
274
294
  const form = JSON.parse(JSON.stringify(_formHiddenCollectionComponentDependentOnExternalData.default));
275
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
295
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
276
296
  expect(result).toEqual(_dataHiddenCollectionComponentDependentOnExternalDataRemoved.default);
277
297
  });
278
298
  it('should not remove component on hidden page if component used elsewhere.', () => {
279
299
  const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageComponentUsedElsewhere.default));
280
300
  const form = JSON.parse(JSON.stringify(_formHiddenPageComponentUsedElsewhere.default));
281
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
301
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
282
302
  expect(result).toEqual(_dataHiddenPageComponentUsedElsewhereRemoved.default);
283
303
  });
304
+ it('should remove all collection components if show_when at the master page level.', () => {
305
+ const submissionData = JSON.parse(JSON.stringify(_dataHiddenEntireCollection.default));
306
+ const form = JSON.parse(JSON.stringify(_formHiddenEntireCollection.default));
307
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
308
+ expect(result).toEqual(_dataHiddenEntireCollectionRemoved.default);
309
+ });
284
310
  it('chained show_whens should be resolved from the end of the chain backup to the start.', () => {
285
311
  const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhens.default));
286
312
  const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhens.default));
287
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
313
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
288
314
  expect(result).toEqual(_dataChainedComponentShowWhensRemoved.default);
289
315
  });
290
316
  it('chained show_whens when top level dependency is field within refdata object.', () => {
291
317
  const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensRefdata.default));
292
318
  const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensRefdata.default));
293
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
319
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
294
320
  expect(result).toEqual(_dataChainedComponentShowWhensRefdataRemoved.default);
295
321
  });
296
322
  it('chained show_whens should be resolved from the end of the chain backup to the start, even if the target and dependent components are in containers thus having segmented paths.', () => {
297
323
  const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensContainerised.default));
298
324
  const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensContainerised.default));
299
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
325
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
300
326
  expect(result).toEqual(_dataChainedComponentShowWhensContainerisedRemoved.default);
301
327
  });
302
328
  it('chained show_whens when the component at the end of the chain is hidden indirectly via page show_when.', () => {
303
329
  const submissionData = JSON.parse(JSON.stringify(_dataChainedShowWhensPageHidden.default));
304
330
  const form = JSON.parse(JSON.stringify(_formChainedShowWhensPageHidden.default));
305
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
331
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
306
332
  expect(result).toEqual(_dataChainedShowWhensPageHiddenRemoved.default);
307
333
  });
308
334
  it('chained show_whens when the dependent component is nested single question.', () => {
309
335
  const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensDependentComponentNested.default));
310
336
  const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensDependentComponentNested.default));
311
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
337
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
312
338
  expect(result).toEqual(_dataChainedComponentShowWhensDependentComponentNestedRemoved.default);
313
339
  });
314
340
  it('chained show_whens when the target component is nested.', () => {
315
341
  const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensTargetComponentNested.default));
316
342
  const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensTargetComponentNested.default));
317
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
343
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
318
344
  expect(result).toEqual(_dataChainedComponentShowWhensTargetComponentNestedRemoved.default);
319
345
  });
320
346
  it('chained show_whens when the dependent component is nested entire block.', () => {
321
347
  const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensDependentComponentNestedBlock.default));
322
348
  const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensDependentComponentNestedBlock.default));
323
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
349
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
324
350
  expect(result).toEqual(_dataChainedComponentShowWhensDependentComponentNestedBlockRemoved.default);
325
351
  });
326
352
  it('business interests removed from mandec.', () => {
327
353
  const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveBusinessInterestsBefore.default));
328
354
  const form = JSON.parse(JSON.stringify(_formCopMandec.default));
329
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
355
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
330
356
  expect(result).toEqual(_copMandecRemoveBusinessInterestsAfter.default);
331
357
  });
332
358
  it('criminality removed from mandec.', () => {
333
359
  const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveCriminalityBefore.default));
334
360
  const form = JSON.parse(JSON.stringify(_formCopMandec.default));
335
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
361
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
336
362
  expect(result).toEqual(_copMandecRemoveCriminalityAfter.default);
337
363
  });
338
364
  it('Unspent convictions removed from mandec.', () => {
339
365
  const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveUnspentConvictionsBefore.default));
340
366
  const form = JSON.parse(JSON.stringify(_formCopMandec.default));
341
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
367
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
342
368
  expect(result).toEqual(_copMandecRemoveUnspentConvictionsAfter.default);
343
369
  });
344
370
  it('Reassign to RCC form, preserved fields not cleansed.', () => {
345
371
  const submissionData = JSON.parse(JSON.stringify(_reassignToRcc.default));
346
372
  const form = JSON.parse(JSON.stringify(_copReassignTaskToRcc.default));
347
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
373
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
348
374
  expect(result).toEqual(_reassignToRcc.default);
349
375
  });
350
376
  it('photos removed from airpax.', () => {
351
377
  const submissionData = JSON.parse(JSON.stringify(_copAirpaxRemovePhotosBefore.default));
352
378
  const form = JSON.parse(JSON.stringify(_formCopAirpax.default));
353
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
379
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
354
380
  expect(result).toEqual(_copAirpaxRemovePhotosAfter.default);
355
381
  });
356
382
  it('carrier not removed from airpax.', () => {
357
383
  const submissionData = JSON.parse(JSON.stringify(_copAirpaxCarrier.default));
358
384
  const form = JSON.parse(JSON.stringify(_formCopAirpax.default));
359
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
385
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
360
386
  expect(result).toEqual(_copAirpaxCarrier.default);
361
387
  });
362
388
  it('airpax change whatHappened to hide whoDecidedSelection.', () => {
363
389
  const submissionData = JSON.parse(JSON.stringify(_copAirpaxChangeWhatHappenedBefore.default));
364
390
  const form = JSON.parse(JSON.stringify(_formCopAirpax.default));
365
- const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
391
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
366
392
  expect(result).toEqual(_copAirpaxChangeWhatHappenedAfter.default);
367
393
  });
394
+ it('should handle nested option in container componet defined in the page.', () => {
395
+ const submissionData = JSON.parse(JSON.stringify(_dataPageNestedRadioComponent.default));
396
+ const form = JSON.parse(JSON.stringify(_formPageNestedRadioComponent.default));
397
+ const result = _index.default.clearOutUncompletedRoutes(true, form, submissionData);
398
+ expect(result).toEqual(_dataPageNestedRadioComponentRemoved.default);
399
+ });
368
400
  });
369
401
  });
370
402
  });
@@ -30,6 +30,12 @@ const getCurrentTaskState = function (_ref) {
30
30
  if (currentPage) {
31
31
  return _models.TaskStates.TYPES.IN_PROGRESS;
32
32
  }
33
+ // If the user has clicked on the back link (see FormRenderer.jsx window.onpopstate event handler)
34
+ // the task will be incomplete and the currentPage deleted
35
+ // and the task state should be recognised as 'In progress'.
36
+ if (complete !== undefined && !complete && currentPage === undefined) {
37
+ return _models.TaskStates.TYPES.IN_PROGRESS;
38
+ }
33
39
  return defaultState;
34
40
  };
35
41
 
@@ -115,6 +115,26 @@ describe('components.FormRenderer.helpers.getUpdatedSectionStates', () => {
115
115
  expect(updatedSections[0].tasks[0].state).toEqual(_models.TaskStates.TYPES.IN_PROGRESS);
116
116
  expect(updatedSections[0].tasks[1].state).toEqual(_models.TaskStates.TYPES.CANNOT_START_YET);
117
117
  });
118
+ it("should set tasks to '".concat(_models.TaskStates.TYPES.IN_PROGRESS, "' if they have no current page and are not complete"), () => {
119
+ const SECTIONS = [{
120
+ name: 'Add event details',
121
+ tasks: [{
122
+ name: 'Date, location and mode details',
123
+ pages: ['eventDate', 'eventMode']
124
+ }, {
125
+ name: 'Officer and agency details',
126
+ pages: ['officeDetails']
127
+ }]
128
+ }];
129
+ const TASKS = {
130
+ 'Date, location and mode details': {
131
+ complete: false
132
+ }
133
+ };
134
+ const updatedSections = (0, _getUpdatedSectionStates.default)(SECTIONS, TASKS);
135
+ expect(updatedSections[0].tasks[0].state).toEqual(_models.TaskStates.TYPES.IN_PROGRESS);
136
+ expect(updatedSections[0].tasks[1].state).toEqual(_models.TaskStates.TYPES.CANNOT_START_YET);
137
+ });
118
138
  it("should set the status of any tasks in a section with a failed show_when to '".concat(_models.TaskStates.TYPES.SKIPPED, "'"), () => {
119
139
  const SECTIONS = [{
120
140
  name: 'Add event details',
@@ -18,7 +18,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
18
18
  *
19
19
  * @param {*} action
20
20
  */
21
- const onCYAAction = (setPagePoint, action, pages, validate, components, data, setData, type, pageId, currentTask, hooks, addErrors, hub, onPageChange, formState, submitting, setSubmitting) => {
21
+ const onCYAAction = (setPagePoint, action, pages, validate, cleanseHiddenData, components, data, setData, type, pageId, currentTask, hooks, addErrors, hub, onPageChange, formState, submitting, setSubmitting) => {
22
22
  // Check to see whether the action is able to proceed, which in
23
23
  // in the case of a submission will validate the fields in the page.
24
24
  if (action.type === _models.PageAction.TYPES.SUBMIT && hub !== _models.HubFormats.TASK) {
@@ -36,7 +36,7 @@ const onCYAAction = (setPagePoint, action, pages, validate, components, data, se
36
36
  pages,
37
37
  components
38
38
  };
39
- _helpers.default.clearOutUncompletedRoutes(formPagesAndComponents, submissionData);
39
+ _helpers.default.clearOutUncompletedRoutes(cleanseHiddenData, formPagesAndComponents, submissionData);
40
40
  submissionData.formStatus = _helpers.default.getSubmissionStatus(type, pages, pageId, action, submissionData, currentTask, true);
41
41
  setData(submissionData);
42
42
  // Now submit the data to the backend...
@@ -80,7 +80,7 @@ const onCYAAction = (setPagePoint, action, pages, validate, components, data, se
80
80
  pages,
81
81
  components
82
82
  };
83
- _helpers.default.clearOutUncompletedRoutes(formPagesAndComponents, submissionData);
83
+ _helpers.default.clearOutUncompletedRoutes(cleanseHiddenData, formPagesAndComponents, submissionData);
84
84
  submissionData.formStatus = _helpers.default.getSubmissionStatus(type, pages, pageId, action, submissionData, currentTask, true);
85
85
  setData(submissionData);
86
86
  // Now submit the data to the backend...
@@ -57,7 +57,7 @@ jest.mock('./helpers', () => ({
57
57
  this.getSubmissionStatusCalls = 0;
58
58
  },
59
59
  clearOutUncompletedRoutesCalls: 0,
60
- clearOutUncompletedRoutes(formPagesAndComponents, formData) {
60
+ clearOutUncompletedRoutes(cleanseHiddenData, formPagesAndComponents, formData) {
61
61
  this.clearOutUncompletedRoutesCalls += 1;
62
62
  return formData;
63
63
  }
@@ -170,6 +170,7 @@ describe('components.FormRenderer.onCYAAction', () => {
170
170
  },
171
171
  pages: PAGES,
172
172
  validate: () => {},
173
+ cleanseHiddenData: true,
173
174
  components: COMPONENTS,
174
175
  data: {},
175
176
  setData: mockSetData,
@@ -19,7 +19,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
19
19
  // (patch captures payload-ready field name and value,
20
20
  // patchLabel captures non-ID values
21
21
  // for display purposes after submission.)
22
- const onPageAction = (action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting, existingErrors) => {
22
+ const onPageAction = (action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, cleanseHiddenData, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting, existingErrors) => {
23
23
  // Save a copy of data in case submit errors and we need to revert
24
24
  const preSubmitData = _objectSpread({}, data);
25
25
  const form = formState;
@@ -112,7 +112,7 @@ const onPageAction = (action, patch, patchLabel, hooks, data, formState, validat
112
112
  components
113
113
  };
114
114
  if (action.type === _models.PageAction.TYPES.SUBMIT) {
115
- _helpers.default.clearOutUncompletedRoutes(formPagesAndComponents, submissionData);
115
+ _helpers.default.clearOutUncompletedRoutes(cleanseHiddenData, formPagesAndComponents, submissionData);
116
116
  }
117
117
 
118
118
  // In case of hub-and-spoke if patchLabel has changed then
@@ -47,7 +47,7 @@ jest.mock('./helpers', () => ({
47
47
  return patch;
48
48
  },
49
49
  clearOutUncompletedRoutesCalls: 0,
50
- clearOutUncompletedRoutes(formPagesAndComponents, formData) {
50
+ clearOutUncompletedRoutes(cleanseHiddenData, formPagesAndComponents, formData) {
51
51
  this.clearOutUncompletedRoutesCalls += 1;
52
52
  return formData;
53
53
  },
@@ -229,6 +229,7 @@ describe('components.FormRenderer.onPageAction', () => {
229
229
  validate: MOCK_VALIDATE,
230
230
  onPageChange: mockOnPageChange,
231
231
  type: _models.FormTypes.FORM_WITH_TASK,
232
+ cleanseHiddenData: true,
232
233
  pages: PAGES,
233
234
  components: COMPONENTS,
234
235
  pageId: 'alpha',
@@ -25,11 +25,17 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
25
25
  * can be one of either:
26
26
  * - A regular form page.
27
27
  * - The master page for a child collection, with its own array of child pages.
28
+ *
29
+ * To specify that an entire collection (including labels and actions) is hidden,
30
+ * then add a show_when to the 1st collection entry in the form.
28
31
  */
29
32
 
30
- const createMasterPage = page => ({
33
+ const createMasterPage = page => _objectSpread(_objectSpread({
31
34
  id: page.id,
32
- name: page.name,
35
+ name: page.name
36
+ }, page.collection.show_when && {
37
+ show_when: page.collection.show_when
38
+ }), {}, {
33
39
  orderInForm: page.orderInForm,
34
40
  deleteCollectionWhenHidden: page.deleteCollectionWhenHidden,
35
41
  collection: _objectSpread({
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@ukhomeoffice/cop-react-form-renderer",
3
- "version": "6.15.12-alpha",
3
+ "version": "6.15.12",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "clean": "rimraf dist",
7
7
  "test": "react-scripts test",
8
8
  "test:coverage": "yarn test --coverage --watchAll=false",
9
9
  "lint": "eslint --ext .js,.jsx src",
10
+ "lint:fix": "eslint --ext .js,.jsx src --fix",
10
11
  "storybook:start": "start-storybook --docs -s src/assets --no-manager-cache -p 6007",
11
12
  "storybook:build": "build-storybook --docs -s src/assets",
12
13
  "storybook": "yarn storybook:start",