@ukhomeoffice/cop-react-form-renderer 6.15.6-alpha → 6.15.8-alpha
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.
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-show-when-in-component-and-page.json +62 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-same-component-reused.json +61 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-airpax-change-what-happened-before.json +300 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-show-when-in-component-and-page.json +6 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page-same-component-reused.json +6 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-airpax-change-what-happened-after.json +280 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-show-when-in-component-and-page-removed.json +5 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-same-component-reused-removed.json +5 -0
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.js +84 -189
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.test.js +64 -27
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutesUtils.js +290 -0
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutesUtils.test.js +502 -0
- package/dist/components/FormRenderer/onCYAAction.js +4 -0
- package/package.json +1 -1
- package/dist/components/FormRenderer/helpers/deleteNodeByPath.js +0 -29
- package/dist/components/FormRenderer/helpers/deleteNodeByPath.test.js +0 -56
|
@@ -4,6 +4,9 @@ var _index = _interopRequireDefault(require("./index"));
|
|
|
4
4
|
var _formHiddenComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-component.json"));
|
|
5
5
|
var _dataHiddenComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-component.json"));
|
|
6
6
|
var _dataHiddenComponentRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-component-removed.json"));
|
|
7
|
+
var _formHiddenComponentShowWhenInComponentAndPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-component-show-when-in-component-and-page.json"));
|
|
8
|
+
var _dataHiddenComponentShowWhenInComponentAndPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-component-show-when-in-component-and-page.json"));
|
|
9
|
+
var _dataHiddenComponentShowWhenInComponentAndPageRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-component-show-when-in-component-and-page-removed.json"));
|
|
7
10
|
var _formHiddenEmbeddedComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-embedded-component.json"));
|
|
8
11
|
var _dataHiddenEmbeddedComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-embedded-component.json"));
|
|
9
12
|
var _dataHiddenEmbeddedComponentRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-embedded-component-removed.json"));
|
|
@@ -34,6 +37,9 @@ var _dataNestedAnswersHiddenByOptionRemoved = _interopRequireDefault(require("..
|
|
|
34
37
|
var _formHiddenPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-page.json"));
|
|
35
38
|
var _dataHiddenPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-page.json"));
|
|
36
39
|
var _dataHiddenPageRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-page-removed.json"));
|
|
40
|
+
var _formHiddenPageSameComponentReused = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-page-same-component-reused.json"));
|
|
41
|
+
var _dataHiddenPageSameComponentReused = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-page-same-component-reused.json"));
|
|
42
|
+
var _dataHiddenPageSameComponentReusedRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-page-same-component-reused-removed.json"));
|
|
37
43
|
var _formHiddenPageComponentUsedElsewhere = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-page-component-used-elsewhere.json"));
|
|
38
44
|
var _dataHiddenPageComponentUsedElsewhere = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-page-component-used-elsewhere.json"));
|
|
39
45
|
var _dataHiddenPageComponentUsedElsewhereRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-page-component-used-elsewhere-removed.json"));
|
|
@@ -79,9 +85,13 @@ var _copMandecRemoveUnspentConvictionsAfter = _interopRequireDefault(require("..
|
|
|
79
85
|
var _formCopAirpax = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-cop-airpax.json"));
|
|
80
86
|
var _copAirpaxRemovePhotosBefore = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/cop-airpax-remove-photos-before.json"));
|
|
81
87
|
var _copAirpaxRemovePhotosAfter = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/cop-airpax-remove-photos-after.json"));
|
|
88
|
+
var _copAirpaxChangeWhatHappenedBefore = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/cop-airpax-change-what-happened-before.json"));
|
|
89
|
+
var _copAirpaxChangeWhatHappenedAfter = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/cop-airpax-change-what-happened-after.json"));
|
|
82
90
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
83
91
|
// Hidden component
|
|
84
92
|
|
|
93
|
+
// Hidden component with show_when in page and component
|
|
94
|
+
|
|
85
95
|
// Hidden embedded component
|
|
86
96
|
|
|
87
97
|
// Hidden collection component
|
|
@@ -102,6 +112,8 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
102
112
|
|
|
103
113
|
// Hidden page
|
|
104
114
|
|
|
115
|
+
// Hidden page containing same component reused
|
|
116
|
+
|
|
105
117
|
// Hidden page with component used elsewhere
|
|
106
118
|
|
|
107
119
|
// Hidden component with show_when rule referring to a collection
|
|
@@ -137,85 +149,104 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
137
149
|
describe('FormRenderer', () => {
|
|
138
150
|
describe('helpers', () => {
|
|
139
151
|
describe('clearOutUncompletedRoutes', () => {
|
|
140
|
-
it('should remove hidden component', () => {
|
|
152
|
+
it('should remove hidden component.', () => {
|
|
141
153
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponent.default));
|
|
142
154
|
const form = JSON.parse(JSON.stringify(_formHiddenComponent.default));
|
|
143
155
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
144
156
|
expect(result).toEqual(_dataHiddenComponentRemoved.default);
|
|
145
157
|
});
|
|
146
|
-
it('should remove hidden component
|
|
158
|
+
it('should remove hidden component with show_when in page and component.', () => {
|
|
159
|
+
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentShowWhenInComponentAndPage.default));
|
|
160
|
+
const form = JSON.parse(JSON.stringify(_formHiddenComponentShowWhenInComponentAndPage.default));
|
|
161
|
+
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
162
|
+
expect(result).toEqual(_dataHiddenComponentShowWhenInComponentAndPageRemoved.default);
|
|
163
|
+
});
|
|
164
|
+
it('should remove hidden component embedded in page.', () => {
|
|
147
165
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenEmbeddedComponent.default));
|
|
148
166
|
const form = JSON.parse(JSON.stringify(_formHiddenEmbeddedComponent.default));
|
|
149
167
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
150
168
|
expect(result).toEqual(_dataHiddenEmbeddedComponentRemoved.default);
|
|
151
169
|
});
|
|
152
|
-
it('should remove hidden collection component', () => {
|
|
170
|
+
it('should remove hidden collection component.', () => {
|
|
153
171
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenCollectionComponent.default));
|
|
154
172
|
const form = JSON.parse(JSON.stringify(_formHiddenCollectionComponent.default));
|
|
155
173
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
156
174
|
expect(result).toEqual(_dataHiddenCollectionComponentRemoved.default);
|
|
157
175
|
});
|
|
158
|
-
it('should remove hidden embedded collection component', () => {
|
|
176
|
+
it('should remove hidden embedded collection component.', () => {
|
|
159
177
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenEmbeddedCollectionComponent.default));
|
|
160
178
|
const form = JSON.parse(JSON.stringify(_formHiddenEmbeddedCollectionComponent.default));
|
|
161
179
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
162
180
|
expect(result).toEqual(_dataHiddenEmbeddedCollectionComponentRemoved.default);
|
|
163
181
|
});
|
|
164
|
-
it('should remove hidden containerised component', () => {
|
|
182
|
+
it('should remove hidden containerised component.', () => {
|
|
165
183
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenContainerisedComponent.default));
|
|
166
184
|
const form = JSON.parse(JSON.stringify(_formHiddenContainerisedComponent.default));
|
|
167
185
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
168
186
|
expect(result).toEqual(_dataHiddenContainerisedComponentRemoved.default);
|
|
169
187
|
});
|
|
170
|
-
it('should remove hidden multi-level containerised components', () => {
|
|
188
|
+
it('should remove hidden multi-level containerised components.', () => {
|
|
171
189
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenMultilevelContainerisedComponent.default));
|
|
172
190
|
const form = JSON.parse(JSON.stringify(_formHiddenMultilevelContainerisedComponent.default));
|
|
173
191
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
174
192
|
expect(result).toEqual(_dataHiddenMultilevelContainerisedComponentRemoved.default);
|
|
175
193
|
});
|
|
176
|
-
it('should remove hidden leaf-level in a multi-level containerised component', () => {
|
|
194
|
+
it('should remove hidden leaf-level in a multi-level containerised component.', () => {
|
|
177
195
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenMultilevelContainerisedComponentLeafHidden.default));
|
|
178
196
|
const form = JSON.parse(JSON.stringify(_formHiddenMultilevelContainerisedComponentLeafHidden.default));
|
|
179
197
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
180
198
|
expect(result).toEqual(_dataHiddenMultilevelContainerisedComponentLeafHiddenRemoved.default);
|
|
181
199
|
});
|
|
182
|
-
it('should remove hidden component with options', () => {
|
|
200
|
+
it('should remove hidden component with options.', () => {
|
|
183
201
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenOptions.default));
|
|
184
202
|
const form = JSON.parse(JSON.stringify(_formHiddenOptions.default));
|
|
185
203
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
186
204
|
expect(result).toEqual(_dataHiddenOptionsRemoved.default);
|
|
187
205
|
});
|
|
188
|
-
it('should remove hidden component with nested questions in options', () => {
|
|
206
|
+
it('should remove hidden component with nested questions in options.', () => {
|
|
189
207
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentWithNestedQuestions.default));
|
|
190
208
|
const form = JSON.parse(JSON.stringify(_formHiddenComponentWithNestedQuestions.default));
|
|
191
209
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
192
210
|
expect(result).toEqual(_dataHiddenComponentWithNestedQuestionsRemoved.default);
|
|
193
211
|
});
|
|
194
|
-
it('should remove answers associated with unselected options in a containerised component', () => {
|
|
212
|
+
it('should remove answers associated with unselected options in a containerised component.', () => {
|
|
195
213
|
const submissionData = JSON.parse(JSON.stringify(_dataNestedAnswersHiddenByOption.default));
|
|
196
214
|
const form = JSON.parse(JSON.stringify(_formNestedAnswersHiddenByOption.default));
|
|
197
215
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
198
216
|
expect(result).toEqual(_dataNestedAnswersHiddenByOptionRemoved.default);
|
|
199
217
|
});
|
|
200
|
-
it('should remove hidden page', () => {
|
|
218
|
+
it('should remove hidden page.', () => {
|
|
201
219
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPage.default));
|
|
202
220
|
const form = JSON.parse(JSON.stringify(_formHiddenPage.default));
|
|
203
221
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
204
222
|
expect(result).toEqual(_dataHiddenPageRemoved.default);
|
|
205
223
|
});
|
|
206
|
-
it('should remove
|
|
224
|
+
it('should remove hidden page with same component reused.', () => {
|
|
225
|
+
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageSameComponentReused.default));
|
|
226
|
+
const form = JSON.parse(JSON.stringify(_formHiddenPageSameComponentReused.default));
|
|
227
|
+
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
228
|
+
expect(result).toEqual(_dataHiddenPageSameComponentReusedRemoved.default);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// TEST FOR 3 components with the same name, a page show_when, 1 of which is shown.
|
|
232
|
+
|
|
233
|
+
// Check the visited thing is working.
|
|
234
|
+
|
|
235
|
+
// Refactor and comment the toArray method.
|
|
236
|
+
|
|
237
|
+
it('should remove a hidden collection on a page.', () => {
|
|
207
238
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageCollection.default));
|
|
208
239
|
const form = JSON.parse(JSON.stringify(_formHiddenPageCollection.default));
|
|
209
240
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
210
241
|
expect(result).toEqual(_dataHiddenPageCollectionRemoved.default);
|
|
211
242
|
});
|
|
212
|
-
it('hidden component with show_when rule referring to a collection', () => {
|
|
243
|
+
it('hidden component with show_when rule referring to a collection.', () => {
|
|
213
244
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentReferringToCollection.default));
|
|
214
245
|
const form = JSON.parse(JSON.stringify(_formHiddenComponentReferringToCollection.default));
|
|
215
246
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
216
247
|
expect(result).toEqual(_dataHiddenComponentReferringToCollectionRemoved.default);
|
|
217
248
|
});
|
|
218
|
-
it('hidden component with show_when rule referring to a hidden collection', () => {
|
|
249
|
+
it('hidden component with show_when rule referring to a hidden collection.', () => {
|
|
219
250
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentReferringToHiddenCollection.default));
|
|
220
251
|
const form = JSON.parse(JSON.stringify(_formHiddenComponentReferringToHiddenCollection.default));
|
|
221
252
|
try {
|
|
@@ -225,84 +256,90 @@ describe('FormRenderer', () => {
|
|
|
225
256
|
expect(error.message).toContain('It is not possible to reliably clean hidden data when a component is dependent');
|
|
226
257
|
}
|
|
227
258
|
});
|
|
228
|
-
it('should remove hidden collection components whether they are dependent on data inside or outside the collection', () => {
|
|
259
|
+
it('should remove hidden collection components whether they are dependent on data inside or outside the collection.', () => {
|
|
229
260
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenCollectionComponentDependentOnExternalData.default));
|
|
230
261
|
const form = JSON.parse(JSON.stringify(_formHiddenCollectionComponentDependentOnExternalData.default));
|
|
231
262
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
232
263
|
expect(result).toEqual(_dataHiddenCollectionComponentDependentOnExternalDataRemoved.default);
|
|
233
264
|
});
|
|
234
|
-
it('should not remove component on hidden page if component used elsewhere', () => {
|
|
265
|
+
it('should not remove component on hidden page if component used elsewhere.', () => {
|
|
235
266
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageComponentUsedElsewhere.default));
|
|
236
267
|
const form = JSON.parse(JSON.stringify(_formHiddenPageComponentUsedElsewhere.default));
|
|
237
268
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
238
269
|
expect(result).toEqual(_dataHiddenPageComponentUsedElsewhereRemoved.default);
|
|
239
270
|
});
|
|
240
|
-
it('chained show_whens should be resolved from the end of the chain backup to the start', () => {
|
|
271
|
+
it('chained show_whens should be resolved from the end of the chain backup to the start.', () => {
|
|
241
272
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhens.default));
|
|
242
273
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhens.default));
|
|
243
274
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
244
275
|
expect(result).toEqual(_dataChainedComponentShowWhensRemoved.default);
|
|
245
276
|
});
|
|
246
|
-
it('chained show_whens when top level dependency is field within refdata object', () => {
|
|
277
|
+
it('chained show_whens when top level dependency is field within refdata object.', () => {
|
|
247
278
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensRefdata.default));
|
|
248
279
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensRefdata.default));
|
|
249
280
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
250
281
|
expect(result).toEqual(_dataChainedComponentShowWhensRefdataRemoved.default);
|
|
251
282
|
});
|
|
252
|
-
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', () => {
|
|
283
|
+
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.', () => {
|
|
253
284
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensContainerised.default));
|
|
254
285
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensContainerised.default));
|
|
255
286
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
256
287
|
expect(result).toEqual(_dataChainedComponentShowWhensContainerisedRemoved.default);
|
|
257
288
|
});
|
|
258
|
-
it('chained show_whens when the component at the end of the chain is hidden indirectly via page show_when', () => {
|
|
289
|
+
it('chained show_whens when the component at the end of the chain is hidden indirectly via page show_when.', () => {
|
|
259
290
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedShowWhensPageHidden.default));
|
|
260
291
|
const form = JSON.parse(JSON.stringify(_formChainedShowWhensPageHidden.default));
|
|
261
292
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
262
293
|
expect(result).toEqual(_dataChainedShowWhensPageHiddenRemoved.default);
|
|
263
294
|
});
|
|
264
|
-
it('chained show_whens when the dependent component is nested single question', () => {
|
|
295
|
+
it('chained show_whens when the dependent component is nested single question.', () => {
|
|
265
296
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensDependentComponentNested.default));
|
|
266
297
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensDependentComponentNested.default));
|
|
267
298
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
268
299
|
expect(result).toEqual(_dataChainedComponentShowWhensDependentComponentNestedRemoved.default);
|
|
269
300
|
});
|
|
270
|
-
it('chained show_whens when the target component is nested', () => {
|
|
301
|
+
it('chained show_whens when the target component is nested.', () => {
|
|
271
302
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensTargetComponentNested.default));
|
|
272
303
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensTargetComponentNested.default));
|
|
273
304
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
274
305
|
expect(result).toEqual(_dataChainedComponentShowWhensTargetComponentNestedRemoved.default);
|
|
275
306
|
});
|
|
276
|
-
it('chained show_whens when the dependent component is nested entire block', () => {
|
|
307
|
+
it('chained show_whens when the dependent component is nested entire block.', () => {
|
|
277
308
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensDependentComponentNestedBlock.default));
|
|
278
309
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensDependentComponentNestedBlock.default));
|
|
279
310
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
280
311
|
expect(result).toEqual(_dataChainedComponentShowWhensDependentComponentNestedBlockRemoved.default);
|
|
281
312
|
});
|
|
282
|
-
it('business interests removed from mandec', () => {
|
|
313
|
+
it('business interests removed from mandec.', () => {
|
|
283
314
|
const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveBusinessInterestsBefore.default));
|
|
284
315
|
const form = JSON.parse(JSON.stringify(_formCopMandec.default));
|
|
285
316
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
286
317
|
expect(result).toEqual(_copMandecRemoveBusinessInterestsAfter.default);
|
|
287
318
|
});
|
|
288
|
-
it('criminality removed from mandec', () => {
|
|
319
|
+
it('criminality removed from mandec.', () => {
|
|
289
320
|
const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveCriminalityBefore.default));
|
|
290
321
|
const form = JSON.parse(JSON.stringify(_formCopMandec.default));
|
|
291
322
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
292
323
|
expect(result).toEqual(_copMandecRemoveCriminalityAfter.default);
|
|
293
324
|
});
|
|
294
|
-
it('Unspent convictions removed from mandec', () => {
|
|
325
|
+
it('Unspent convictions removed from mandec.', () => {
|
|
295
326
|
const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveUnspentConvictionsBefore.default));
|
|
296
327
|
const form = JSON.parse(JSON.stringify(_formCopMandec.default));
|
|
297
328
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
298
329
|
expect(result).toEqual(_copMandecRemoveUnspentConvictionsAfter.default);
|
|
299
330
|
});
|
|
300
|
-
it('photos removed from airpax', () => {
|
|
331
|
+
it('photos removed from airpax.', () => {
|
|
301
332
|
const submissionData = JSON.parse(JSON.stringify(_copAirpaxRemovePhotosBefore.default));
|
|
302
333
|
const form = JSON.parse(JSON.stringify(_formCopAirpax.default));
|
|
303
334
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
304
335
|
expect(result).toEqual(_copAirpaxRemovePhotosAfter.default);
|
|
305
336
|
});
|
|
337
|
+
it('airpax change whatHappened to hide whoDecidedSelection.', () => {
|
|
338
|
+
const submissionData = JSON.parse(JSON.stringify(_copAirpaxChangeWhatHappenedBefore.default));
|
|
339
|
+
const form = JSON.parse(JSON.stringify(_formCopAirpax.default));
|
|
340
|
+
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
341
|
+
expect(result).toEqual(_copAirpaxChangeWhatHappenedAfter.default);
|
|
342
|
+
});
|
|
306
343
|
});
|
|
307
344
|
});
|
|
308
345
|
});
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.removeObjectWithSingleIdFieldInPlace = exports.removeEmptyArraysAndUnusedCollectionIDs = exports.isShowEntity = exports.getNestedQuestionPath = exports.getImmediateParent = exports.getDependencyObjectFromPath = exports.getDependencies = exports.findComponentDefinitionInForm = exports.deleteNodeByPath = exports.deleteCorrespondingMetaInfo = void 0;
|
|
7
|
+
var _Condition = _interopRequireDefault(require("../../../utils/Condition"));
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
/**
|
|
10
|
+
* Given a path, remove a node from this path within an object.
|
|
11
|
+
*
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} obj Javascript object from which the node will be deleted. Updated by the method.
|
|
14
|
+
* @param {String} path A string containing a decimal point delimited path specifying the node to delete.
|
|
15
|
+
* @return Nothing, obj above updated.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/* eslint-disable consistent-return, no-param-reassign */
|
|
19
|
+
const deleteNodeByPath = (obj, path) => {
|
|
20
|
+
if (Array.isArray(obj)) {
|
|
21
|
+
// If obj is an array, recursively call deleteNodeByPath on each element
|
|
22
|
+
for (let i = 0; i < obj.length; i += 1) {
|
|
23
|
+
deleteNodeByPath(obj[i], path);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const keys = path.split('.');
|
|
27
|
+
let current = obj;
|
|
28
|
+
for (let i = 0; i < keys.length - 1; i += 1) {
|
|
29
|
+
current = current[keys[i]];
|
|
30
|
+
if (current === undefined) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (current[keys[keys.length - 1]]) {
|
|
35
|
+
console.log("Deleting element : ".concat(keys[keys.length - 1]));
|
|
36
|
+
delete current[keys[keys.length - 1]];
|
|
37
|
+
}
|
|
38
|
+
return obj;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Pruning a collection payload may have resulted in objects that are only left with their 'id' field, which isn't data
|
|
43
|
+
* but added by the renderer to find the activeId. If so, remove these objects entirely as they have been pruned.
|
|
44
|
+
*
|
|
45
|
+
* @param {Array} array Array of objects. Each object which has only 1 remaining field called 'id' should be removed.
|
|
46
|
+
* @return Nothing, array above updated.
|
|
47
|
+
*/
|
|
48
|
+
exports.deleteNodeByPath = deleteNodeByPath;
|
|
49
|
+
const removeObjectWithSingleIdFieldInPlace = array => {
|
|
50
|
+
for (let i = array.length - 1; i >= 0; i -= 1) {
|
|
51
|
+
const obj = array[i];
|
|
52
|
+
if (Object.keys(obj).length === 1 && Object.keys(obj)[0] === 'id') {
|
|
53
|
+
array.splice(i, 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Return the immediate parent of a path string passed in.
|
|
60
|
+
* Useful for processing 'options' in a form, as nested fieldIds are placed in the payload at
|
|
61
|
+
* the same level in the heirarchy as the option question they relate to.
|
|
62
|
+
*
|
|
63
|
+
* @param {String} path Decimal point delimited path.
|
|
64
|
+
* @returns {String} Immediate parent of the path passed in.
|
|
65
|
+
*/
|
|
66
|
+
exports.removeObjectWithSingleIdFieldInPlace = removeObjectWithSingleIdFieldInPlace;
|
|
67
|
+
const getImmediateParent = path => {
|
|
68
|
+
if (typeof path !== 'string' || !path.includes('.')) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const parts = path.split('.');
|
|
72
|
+
parts.pop();
|
|
73
|
+
return parts.join('.');
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Questions can be nested within options, eg if you answer 'yes' to a radio question, this can
|
|
78
|
+
* reveal additional nested questions.
|
|
79
|
+
* The path of the fields from these nested questions are at the same level as the original option
|
|
80
|
+
* answer, so this utility derives the nested question path from the option path.
|
|
81
|
+
*
|
|
82
|
+
* @param {String} optionPath Decimal point delimited path
|
|
83
|
+
* @param {String} nestedFieldId fieldId (dataname) of the nested question within the above option
|
|
84
|
+
* @returns {String} Fully qualified path of the nested question
|
|
85
|
+
*/
|
|
86
|
+
exports.getImmediateParent = getImmediateParent;
|
|
87
|
+
const getNestedQuestionPath = (optionPath, nestedFieldId) => {
|
|
88
|
+
const parentPath = getImmediateParent(optionPath);
|
|
89
|
+
return parentPath ? "".concat(parentPath, ".").concat(nestedFieldId) : nestedFieldId;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Helper method to establish all the payload paths (dependencies) that an entity (page or component) is
|
|
94
|
+
* dependent on through its show_when rule.
|
|
95
|
+
*
|
|
96
|
+
* This will be used to build a graph of chained dependencies to establish in which order
|
|
97
|
+
* to resolve dependencies. The exact rule is not required at this point, just the dependencies.
|
|
98
|
+
*
|
|
99
|
+
* The form specification allows complex show_when blocks including 1...n levels of nesting, so
|
|
100
|
+
* recursively search through the show_when block looking for all 'field' data items.
|
|
101
|
+
*
|
|
102
|
+
* @param {Object} entity Entity whose show_when rule is to be searched for 'field' data items within.
|
|
103
|
+
* @returns {Set} Set of payload paths that the entity (page or component) is dependent on.
|
|
104
|
+
*/
|
|
105
|
+
exports.getNestedQuestionPath = getNestedQuestionPath;
|
|
106
|
+
const getDependencies = entity => {
|
|
107
|
+
const findShowWhenFields = (showWhenObject, showWhenFields) => {
|
|
108
|
+
if (typeof showWhenObject === 'object' && showWhenObject !== null) {
|
|
109
|
+
if (Array.isArray(showWhenObject)) {
|
|
110
|
+
showWhenObject.forEach(value => {
|
|
111
|
+
findShowWhenFields(value, showWhenFields);
|
|
112
|
+
});
|
|
113
|
+
} else {
|
|
114
|
+
Object.keys(showWhenObject).forEach(key => {
|
|
115
|
+
if (key === 'field') {
|
|
116
|
+
showWhenFields.push(showWhenObject[key]);
|
|
117
|
+
}
|
|
118
|
+
findShowWhenFields(showWhenObject[key], showWhenFields);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return showWhenFields;
|
|
123
|
+
};
|
|
124
|
+
return entity.show_when ? new Set(findShowWhenFields(entity.show_when, []) || []) : null;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Some show_when field values point to data items that are within objects provided by
|
|
129
|
+
* external calls to refdata, eg modeOfTransport.id. These won't map directly to the path
|
|
130
|
+
* keyed components in the allComponents map, so go back up levels in the path until we find
|
|
131
|
+
* the component that creates this field.
|
|
132
|
+
*
|
|
133
|
+
* This component might not be found at all, as the dependency might be on a field that is either
|
|
134
|
+
* provided by cop-ui (eg jobHolderStaffDetails.linemanagerEmail), or by the "addToFormData" function
|
|
135
|
+
* (eg epmsSubmitted). These will be leaf level in the dependency chain so component is not required.
|
|
136
|
+
*
|
|
137
|
+
* @param {String} optionPath Decimal point delimited path
|
|
138
|
+
* @param {String} nestedFieldId fieldId (dataname) of the nested question within the above option
|
|
139
|
+
* @returns {String} Fully qualified path of the nested question
|
|
140
|
+
*
|
|
141
|
+
*/
|
|
142
|
+
exports.getDependencies = getDependencies;
|
|
143
|
+
const getDependencyObjectFromPath = (dependencyPath, allComponents) => {
|
|
144
|
+
const segments = dependencyPath.split(".");
|
|
145
|
+
for (let i = segments.length; i > 0; i -= 1) {
|
|
146
|
+
const currentPath = segments.slice(0, i).join(".");
|
|
147
|
+
const dependencyObject = allComponents.get(currentPath);
|
|
148
|
+
if (dependencyObject) return dependencyObject;
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
*
|
|
155
|
+
* Evaluate the show_when rule to establish if the component should be shown (and the
|
|
156
|
+
* payload data should not be pruned). If there is no show_when rule, then return true.
|
|
157
|
+
*
|
|
158
|
+
* @param {*} entity A page or component that may have a show_when rule associated with it
|
|
159
|
+
* @param {*} data The payload data used to evaluate the show_when rule
|
|
160
|
+
* @returns {boolean} true if the show_when rule evaluate to true, or there is no show_when rule
|
|
161
|
+
*/
|
|
162
|
+
exports.getDependencyObjectFromPath = getDependencyObjectFromPath;
|
|
163
|
+
const isShowEntity = (entity, data) => {
|
|
164
|
+
var _entity$show_when;
|
|
165
|
+
// If there is no rule set, then the entity can be shown
|
|
166
|
+
if (!entity.show_when) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
if (((_entity$show_when = entity.show_when) === null || _entity$show_when === void 0 ? void 0 : _entity$show_when.type) === "or") {
|
|
170
|
+
return _Condition.default.meetsOne(entity, data);
|
|
171
|
+
}
|
|
172
|
+
return _Condition.default.meetsAll(entity, data);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
*
|
|
177
|
+
* Components can be assigned to pages in 2 ways in the form specification:
|
|
178
|
+
*
|
|
179
|
+
* 1 - They can be included in the page's components array with the 'use' field, e.g.
|
|
180
|
+
* {
|
|
181
|
+
* "use": "port"
|
|
182
|
+
* }
|
|
183
|
+
* This "use" value will normally match a component's id, but can match its fieldId
|
|
184
|
+
* NB. In this case, a show_when rule can be applied here, which will supercede any show_when in the component. e.g.
|
|
185
|
+
*
|
|
186
|
+
* {
|
|
187
|
+
* "use": "port",
|
|
188
|
+
* "show_when": ....
|
|
189
|
+
* }
|
|
190
|
+
*
|
|
191
|
+
* 2 - The entire component can be embedded as an entry in the page's component array.
|
|
192
|
+
*
|
|
193
|
+
*
|
|
194
|
+
* @param {*} componentId The id of the component to find in the form.
|
|
195
|
+
* @param {*} componentByIdMap A map of all the form's components keyed on Id, for better performance than searching the form.
|
|
196
|
+
* @param {*} componentByFieldIdMap A map of all the form's components keyed on fieldId, for better performance than searching the form.
|
|
197
|
+
* @returns {Object} A cloned component object, containing the full definition of that component.
|
|
198
|
+
*/
|
|
199
|
+
exports.isShowEntity = isShowEntity;
|
|
200
|
+
const findComponentDefinitionInForm = (pageComponentDef, componentByIdMap, componentByFieldIdMap) => {
|
|
201
|
+
var _ref, _componentByIdMap$get;
|
|
202
|
+
const componentInForm = (_ref = (_componentByIdMap$get = componentByIdMap.get(pageComponentDef.use)) !== null && _componentByIdMap$get !== void 0 ? _componentByIdMap$get : componentByFieldIdMap.get(pageComponentDef.use)) !== null && _ref !== void 0 ? _ref : pageComponentDef;
|
|
203
|
+
if (pageComponentDef.use && pageComponentDef.show_when) {
|
|
204
|
+
componentInForm.show_when = pageComponentDef.show_when;
|
|
205
|
+
}
|
|
206
|
+
// Retun clone of component, so subsequent processing can make changes to it without changing the form
|
|
207
|
+
return JSON.parse(JSON.stringify(componentInForm));
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
*
|
|
212
|
+
* When documents are added to the payload of type multifile, they are also added to a section of the payload
|
|
213
|
+
* 'meta', specifically an array 'documents'. When we remove the multifile elements, we need to remove
|
|
214
|
+
* the corresponding meta.document entries.
|
|
215
|
+
*
|
|
216
|
+
* @param {*} component The component definition being deleted that needs corresponding meta data also deleted
|
|
217
|
+
* @param {*} collectionDataObject The payload containing the file data being deleted (for which the corresponding meta needs deleting)
|
|
218
|
+
* @param {*} formData The entire payload, which will include the meta section
|
|
219
|
+
* @returns Nothing, as the formData will be updated in situ
|
|
220
|
+
*/
|
|
221
|
+
exports.findComponentDefinitionInForm = findComponentDefinitionInForm;
|
|
222
|
+
const deleteCorrespondingMetaInfo = (component, collectionDataObject, formData) => {
|
|
223
|
+
const {
|
|
224
|
+
meta: {
|
|
225
|
+
documents
|
|
226
|
+
}
|
|
227
|
+
} = formData;
|
|
228
|
+
const fileDataBeingDeleted = collectionDataObject[component.fieldId];
|
|
229
|
+
if (!documents || !fileDataBeingDeleted) return;
|
|
230
|
+
const fileDataAsArray = Array.isArray(fileDataBeingDeleted) ? fileDataBeingDeleted : [fileDataBeingDeleted];
|
|
231
|
+
// Iterate backwards to avoid index shifting when removing elements
|
|
232
|
+
for (let i = fileDataAsArray.length - 1; i >= 0; i -= 1) {
|
|
233
|
+
const matchIndex = documents.findIndex(metaDocument => metaDocument.url === fileDataAsArray[i].url);
|
|
234
|
+
if (matchIndex !== -1) {
|
|
235
|
+
documents.splice(matchIndex, 1);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* After the payload has been cleansed of individual data items, empty arrays and objects may remain.
|
|
241
|
+
* Removing an array (when the payload for a collection) may leave a redundant activeId field. The active Id
|
|
242
|
+
* fields are not part of the payload data, but added by the react renderer to track which collection object
|
|
243
|
+
* is currently being worked on, so can be removed.
|
|
244
|
+
*
|
|
245
|
+
* To tidy this all up, recursively empty arrays and their associated "ActiveId" fields from a nested payload.
|
|
246
|
+
*
|
|
247
|
+
* This function traverses a given payload, which can be an array or an object, and performs the following operations:
|
|
248
|
+
* 1. If an empty array is found inside an array, it is removed using `splice`.
|
|
249
|
+
* 2. If an empty array is found inside an object:
|
|
250
|
+
* - It is removed from the object.
|
|
251
|
+
* - If there is a corresponding `<key>ActiveId` field, that field is also removed.
|
|
252
|
+
* 3. The function operates recursively to handle deeply nested structures.
|
|
253
|
+
*
|
|
254
|
+
* @param {any} payload - The input data structure, which can be an array or an object.
|
|
255
|
+
*/
|
|
256
|
+
exports.deleteCorrespondingMetaInfo = deleteCorrespondingMetaInfo;
|
|
257
|
+
const removeEmptyArraysAndUnusedCollectionIDs = payload => {
|
|
258
|
+
if (Array.isArray(payload)) {
|
|
259
|
+
for (let i = payload.length - 1; i >= 0; i -= 1) {
|
|
260
|
+
if (Array.isArray(payload[i]) && payload[i].length === 0) {
|
|
261
|
+
payload.splice(i, 1);
|
|
262
|
+
} else {
|
|
263
|
+
removeEmptyArraysAndUnusedCollectionIDs(payload[i]); // Recurse for nested structures
|
|
264
|
+
}
|
|
265
|
+
// When unwinding out of the recursion, we may have emptied an object which is the remaining element of an
|
|
266
|
+
// array, in which case remove the element
|
|
267
|
+
if (typeof payload[i] === 'object' && Object.keys(payload[i]).length === 0) {
|
|
268
|
+
payload.splice(i, 1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
} else if (payload !== null && typeof payload === 'object') {
|
|
272
|
+
Object.keys(payload).forEach(key => {
|
|
273
|
+
if (Array.isArray(payload[key]) && payload[key].length === 0) {
|
|
274
|
+
// If the array being removed has an activeId associated with it, remove it
|
|
275
|
+
if (payload["".concat(key, "ActiveId")]) {
|
|
276
|
+
delete payload["".concat(key, "ActiveId")];
|
|
277
|
+
console.log("Deleted element : ".concat(key, "ActiveId}"));
|
|
278
|
+
}
|
|
279
|
+
delete payload["".concat(key, "ActiveId")];
|
|
280
|
+
if (payload[key]) {
|
|
281
|
+
delete payload[key];
|
|
282
|
+
console.log("Deleted element : ".concat(key));
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
removeEmptyArraysAndUnusedCollectionIDs(payload[key]); // Recurse for nested structures
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
exports.removeEmptyArraysAndUnusedCollectionIDs = removeEmptyArraysAndUnusedCollectionIDs;
|