@ukhomeoffice/cop-react-form-renderer 2.9.1 → 2.10.2

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 (47) hide show
  1. package/dist/components/CheckYourAnswers/CheckYourAnswers.js +8 -12
  2. package/dist/components/CheckYourAnswers/CheckYourAnswers.test.js +10 -8
  3. package/dist/components/FormComponent/Collection.js +244 -0
  4. package/dist/components/FormComponent/Collection.scss +23 -0
  5. package/dist/components/FormComponent/Container.js +110 -0
  6. package/dist/components/FormComponent/Container.test.js +26 -26
  7. package/dist/components/FormComponent/FormComponent.js +64 -128
  8. package/dist/components/FormComponent/FormComponent.test.js +19 -19
  9. package/dist/components/FormComponent/helpers/getComponentError.js +31 -0
  10. package/dist/components/FormComponent/helpers/getComponentError.test.js +52 -0
  11. package/dist/components/FormComponent/helpers/index.js +15 -0
  12. package/dist/components/FormPage/FormPage.js +7 -11
  13. package/dist/components/FormPage/FormPage.test.js +12 -76
  14. package/dist/components/FormRenderer/FormRenderer.js +103 -44
  15. package/dist/components/FormRenderer/helpers/canActionProceed.js +3 -12
  16. package/dist/components/FormRenderer/helpers/canActionProceed.test.js +41 -65
  17. package/dist/components/FormRenderer/helpers/canCYASubmit.js +3 -24
  18. package/dist/components/FormRenderer/helpers/canCYASubmit.test.js +72 -145
  19. package/dist/components/SummaryList/GroupAction.js +1 -1
  20. package/dist/components/SummaryList/SummaryList.js +33 -18
  21. package/dist/components/SummaryList/SummaryList.scss +12 -8
  22. package/dist/components/SummaryList/SummaryList.test.js +94 -27
  23. package/dist/components/SummaryList/SummaryListRow.js +51 -0
  24. package/dist/components/SummaryList/SummaryListTitleRow.js +30 -0
  25. package/dist/context/ValidationContext/ValidationContext.js +128 -0
  26. package/dist/context/ValidationContext/ValidationContext.test.js +98 -0
  27. package/dist/context/ValidationContext/index.js +23 -0
  28. package/dist/context/index.js +15 -0
  29. package/dist/hooks/index.js +8 -0
  30. package/dist/hooks/useValidation.js +19 -0
  31. package/dist/index.js +11 -5
  32. package/dist/models/CollectionLabels.js +14 -0
  33. package/dist/models/index.js +8 -0
  34. package/dist/setupTests.js +32 -0
  35. package/dist/utils/CheckYourAnswers/getCYARow.js +2 -0
  36. package/dist/utils/CheckYourAnswers/getCYARow.test.js +6 -10
  37. package/dist/utils/CheckYourAnswers/getCYARowsForCollection.js +89 -0
  38. package/dist/utils/CheckYourAnswers/getCYARowsForCollection.test.js +194 -0
  39. package/dist/utils/CheckYourAnswers/getCYARowsForContainer.test.js +9 -13
  40. package/dist/utils/CheckYourAnswers/getCYARowsForPage.js +11 -4
  41. package/dist/utils/CheckYourAnswers/getCYARowsForPage.test.js +58 -14
  42. package/dist/utils/Component/getDefaultValue.js +25 -0
  43. package/dist/utils/Component/getDefaultValue.test.js +53 -0
  44. package/dist/utils/Component/index.js +4 -1
  45. package/dist/utils/Data/getSourceData.js +38 -0
  46. package/dist/utils/Data/getSourceData.test.js +16 -0
  47. package/package.json +2 -2
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "getComponentError", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _getComponentError.default;
10
+ }
11
+ });
12
+
13
+ var _getComponentError = _interopRequireDefault(require("./getComponentError"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -13,6 +13,8 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
13
13
 
14
14
  var _react = _interopRequireWildcard(require("react"));
15
15
 
16
+ var _hooks = require("../../hooks");
17
+
16
18
  var _utils = _interopRequireDefault(require("../../utils"));
17
19
 
18
20
  var _FormComponent = _interopRequireDefault(require("../FormComponent"));
@@ -60,10 +62,8 @@ var FormPage = function FormPage(_ref) {
60
62
  patch = _useState2[0],
61
63
  setPatch = _useState2[1];
62
64
 
63
- var _useState3 = (0, _react.useState)([]),
64
- _useState4 = _slicedToArray(_useState3, 2),
65
- errors = _useState4[0],
66
- setErrors = _useState4[1];
65
+ var _useValidation = (0, _hooks.useValidation)(),
66
+ errors = _useValidation.errors;
67
67
  /**
68
68
  * Handle the state of the data directly within the page.
69
69
  * This is so that the overall form data isn't affected until such
@@ -79,16 +79,12 @@ var FormPage = function FormPage(_ref) {
79
79
  });
80
80
  };
81
81
 
82
- var onError = function onError(errors) {
83
- setErrors(errors);
84
- };
85
-
86
82
  var classes = _utils.default.classBuilder(classBlock, classModifiers, className);
87
83
 
88
84
  return /*#__PURE__*/_react.default.createElement("div", {
89
85
  className: classes('page'),
90
86
  key: page.id
91
- }, page.title && /*#__PURE__*/_react.default.createElement(_copReactComponents.LargeHeading, null, page.title), errors && errors.length > 0 && /*#__PURE__*/_react.default.createElement(_copReactComponents.ErrorSummary, {
87
+ }, page.title && /*#__PURE__*/_react.default.createElement(_copReactComponents.LargeHeading, null, page.title), (errors === null || errors === void 0 ? void 0 : errors.length) > 0 && /*#__PURE__*/_react.default.createElement(_copReactComponents.ErrorSummary, {
92
88
  errors: errors
93
89
  }), page.components.filter(function (c) {
94
90
  return _utils.default.Component.show(c, page.formData);
@@ -97,13 +93,13 @@ var FormPage = function FormPage(_ref) {
97
93
  key: index,
98
94
  component: component,
99
95
  onChange: onPageChange,
100
- value: page.formData[component.fieldId] || '',
96
+ value: page.formData[component.fieldId],
101
97
  formData: page.formData
102
98
  });
103
99
  }), /*#__PURE__*/_react.default.createElement(_PageActions.default, {
104
100
  actions: page.actions,
105
101
  onAction: function onAction(action) {
106
- return _onAction(action, patch, onError);
102
+ return _onAction(action, patch);
107
103
  }
108
104
  }));
109
105
  };
@@ -8,6 +8,8 @@ var _react2 = _interopRequireDefault(require("react"));
8
8
 
9
9
  var _models = require("../../models");
10
10
 
11
+ var _setupTests = require("../../setupTests");
12
+
11
13
  var _ActionButton = require("../PageActions/ActionButton");
12
14
 
13
15
  var _FormPage = _interopRequireWildcard(require("./FormPage"));
@@ -22,7 +24,7 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try
22
24
 
23
25
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
24
26
 
25
- describe('components', function () {
27
+ describe('components.FormPage', function () {
26
28
  describe('FormPage', function () {
27
29
  var TEXT = {
28
30
  id: 'text',
@@ -58,16 +60,16 @@ describe('components', function () {
58
60
  ON_ACTION_CALLS.length = 0;
59
61
  });
60
62
  it('should render a submit page correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
61
- var _render, container, page, heading, formGroup, label, hint, input, buttonGroup, button;
63
+ var _renderWithValidation, container, page, heading, formGroup, label, hint, input, buttonGroup, button;
62
64
 
63
65
  return regeneratorRuntime.wrap(function _callee$(_context) {
64
66
  while (1) {
65
67
  switch (_context.prev = _context.next) {
66
68
  case 0:
67
- _render = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_FormPage.default, {
69
+ _renderWithValidation = (0, _setupTests.renderWithValidation)( /*#__PURE__*/_react2.default.createElement(_FormPage.default, {
68
70
  page: PAGE,
69
71
  onAction: ON_ACTION
70
- })), container = _render.container;
72
+ })), container = _renderWithValidation.container;
71
73
  page = container.childNodes[0];
72
74
  expect(page.tagName).toEqual('DIV');
73
75
  expect(page.classList).toContain("".concat(_FormPage.DEFAULT_CLASS, "__page"));
@@ -107,16 +109,16 @@ describe('components', function () {
107
109
  }, _callee);
108
110
  })));
109
111
  it('should handle a page change appropriately', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
110
- var _render2, container, page, input, NEW_VALUE, EVENT;
112
+ var _renderWithValidation2, container, page, input, NEW_VALUE, EVENT;
111
113
 
112
114
  return regeneratorRuntime.wrap(function _callee2$(_context2) {
113
115
  while (1) {
114
116
  switch (_context2.prev = _context2.next) {
115
117
  case 0:
116
- _render2 = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_FormPage.default, {
118
+ _renderWithValidation2 = (0, _setupTests.renderWithValidation)( /*#__PURE__*/_react2.default.createElement(_FormPage.default, {
117
119
  page: PAGE,
118
120
  onAction: ON_ACTION
119
- })), container = _render2.container;
121
+ })), container = _renderWithValidation2.container;
120
122
  page = container.childNodes[0];
121
123
  expect(page.tagName).toEqual('DIV'); // Change the input.
122
124
 
@@ -142,16 +144,16 @@ describe('components', function () {
142
144
  }, _callee2);
143
145
  })));
144
146
  it('should handle a page action appropriately', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
145
- var _render3, container, page, input, NEW_VALUE, CHANGE_EVENT, button;
147
+ var _renderWithValidation3, container, page, input, NEW_VALUE, CHANGE_EVENT, button;
146
148
 
147
149
  return regeneratorRuntime.wrap(function _callee3$(_context3) {
148
150
  while (1) {
149
151
  switch (_context3.prev = _context3.next) {
150
152
  case 0:
151
- _render3 = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_FormPage.default, {
153
+ _renderWithValidation3 = (0, _setupTests.renderWithValidation)( /*#__PURE__*/_react2.default.createElement(_FormPage.default, {
152
154
  page: PAGE,
153
155
  onAction: ON_ACTION
154
- })), container = _render3.container;
156
+ })), container = _renderWithValidation3.container;
155
157
  page = container.childNodes[0]; // Change the input.
156
158
 
157
159
  input = page.childNodes[1].childNodes[2];
@@ -185,71 +187,5 @@ describe('components', function () {
185
187
  }
186
188
  }, _callee3);
187
189
  })));
188
- it('should display errors appropriately', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
189
- var ERRORS, THROW_ERROR_ON_ACTION, _render4, container, page, input, NEW_VALUE, CHANGE_EVENT, button, errorSummary, errorList, error, errorLink;
190
-
191
- return regeneratorRuntime.wrap(function _callee4$(_context4) {
192
- while (1) {
193
- switch (_context4.prev = _context4.next) {
194
- case 0:
195
- ERRORS = [{
196
- id: TEXT.id,
197
- error: 'Invalid value'
198
- }];
199
-
200
- THROW_ERROR_ON_ACTION = function THROW_ERROR_ON_ACTION(action, patch, onError) {
201
- ON_ACTION_CALLS.push({
202
- action: action,
203
- patch: patch,
204
- onError: onError
205
- });
206
- onError(ERRORS);
207
- };
208
-
209
- _render4 = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_FormPage.default, {
210
- page: PAGE,
211
- onAction: THROW_ERROR_ON_ACTION
212
- })), container = _render4.container;
213
- page = container.childNodes[0]; // Change the input.
214
-
215
- input = page.childNodes[1].childNodes[2];
216
- NEW_VALUE = "".concat(VALUE, ".");
217
- CHANGE_EVENT = {
218
- target: {
219
- name: TEXT.fieldId,
220
- value: NEW_VALUE
221
- }
222
- };
223
-
224
- _react.fireEvent.change(input, CHANGE_EVENT); // Then click the action button, which should call the onError callback method.
225
-
226
-
227
- button = page.childNodes[2].childNodes[0];
228
-
229
- _react.fireEvent.click(button, {}); // And confirm the page error is now displayed.
230
-
231
-
232
- errorSummary = page.childNodes[1];
233
- expect(errorSummary.tagName).toEqual('DIV');
234
- expect(errorSummary.id).toEqual('error-summary');
235
- expect(errorSummary.classList).toContain('govuk-error-summary');
236
- errorList = errorSummary.childNodes[1].childNodes[0];
237
- expect(errorList.tagName).toEqual('UL');
238
- expect(errorList.classList).toContain('govuk-error-summary__list');
239
- expect(errorList.childNodes.length).toEqual(ERRORS.length);
240
- error = errorList.childNodes[0];
241
- expect(error.tagName).toEqual('LI');
242
- errorLink = error.childNodes[0];
243
- expect(errorLink.tagName).toEqual('A');
244
- expect(errorLink.textContent).toEqual(ERRORS[0].error);
245
- expect(errorLink.getAttribute('href')).toEqual("#".concat(ERRORS[0].id));
246
-
247
- case 24:
248
- case "end":
249
- return _context4.stop();
250
- }
251
- }
252
- }, _callee4);
253
- })));
254
190
  });
255
191
  });
@@ -13,6 +13,8 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
13
13
 
14
14
  var _react = _interopRequireWildcard(require("react"));
15
15
 
16
+ var _context = require("../../context");
17
+
16
18
  var _hooks2 = require("../../hooks");
17
19
 
18
20
  var _models = require("../../models");
@@ -57,24 +59,57 @@ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Sy
57
59
 
58
60
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
59
61
 
60
- var DEFAULT_CLASS = 'hods-form';
61
- exports.DEFAULT_CLASS = DEFAULT_CLASS;
62
-
63
62
  var FormRenderer = function FormRenderer(_ref) {
64
63
  var title = _ref.title,
65
64
  type = _ref.type,
66
65
  components = _ref.components,
67
- _pages = _ref.pages,
68
- _hub = _ref.hub,
66
+ pages = _ref.pages,
67
+ hub = _ref.hub,
69
68
  cya = _ref.cya,
70
- _data = _ref.data,
71
- _hooks = _ref.hooks,
69
+ data = _ref.data,
70
+ hooks = _ref.hooks,
72
71
  classBlock = _ref.classBlock,
73
72
  classModifiers = _ref.classModifiers,
74
73
  className = _ref.className,
75
74
  hide_title = _ref.hide_title,
76
75
  summaryListClassModifiers = _ref.summaryListClassModifiers,
77
76
  noChangeAction = _ref.noChangeAction;
77
+ return /*#__PURE__*/_react.default.createElement(_context.ValidationContextProvider, null, /*#__PURE__*/_react.default.createElement(InternalFormRenderer, {
78
+ title: title,
79
+ type: type,
80
+ components: components,
81
+ pages: pages,
82
+ hub: hub,
83
+ cya: cya,
84
+ data: data,
85
+ hooks: hooks,
86
+ classBlock: classBlock,
87
+ classModifiers: classModifiers,
88
+ className: className,
89
+ hide_title: hide_title,
90
+ summaryListClassModifiers: summaryListClassModifiers,
91
+ noChangeAction: noChangeAction
92
+ }));
93
+ };
94
+
95
+ var DEFAULT_CLASS = 'hods-form';
96
+ exports.DEFAULT_CLASS = DEFAULT_CLASS;
97
+
98
+ var InternalFormRenderer = function InternalFormRenderer(_ref2) {
99
+ var title = _ref2.title,
100
+ type = _ref2.type,
101
+ components = _ref2.components,
102
+ _pages = _ref2.pages,
103
+ _hub = _ref2.hub,
104
+ cya = _ref2.cya,
105
+ _data = _ref2.data,
106
+ _hooks = _ref2.hooks,
107
+ classBlock = _ref2.classBlock,
108
+ classModifiers = _ref2.classModifiers,
109
+ className = _ref2.className,
110
+ hide_title = _ref2.hide_title,
111
+ summaryListClassModifiers = _ref2.summaryListClassModifiers,
112
+ noChangeAction = _ref2.noChangeAction;
78
113
 
79
114
  // Set up the initial states.
80
115
  var _useState = (0, _react.useState)({}),
@@ -82,35 +117,40 @@ var FormRenderer = function FormRenderer(_ref) {
82
117
  data = _useState2[0],
83
118
  setData = _useState2[1];
84
119
 
85
- var _useState3 = (0, _react.useState)([]),
120
+ var _useState3 = (0, _react.useState)(),
86
121
  _useState4 = _slicedToArray(_useState3, 2),
87
- pages = _useState4[0],
88
- setPages = _useState4[1];
122
+ submitted = _useState4[0],
123
+ setSubmitted = _useState4[1];
89
124
 
90
- var _useState5 = (0, _react.useState)(undefined),
125
+ var _useState5 = (0, _react.useState)([]),
91
126
  _useState6 = _slicedToArray(_useState5, 2),
92
- hub = _useState6[0],
93
- setHub = _useState6[1];
127
+ pages = _useState6[0],
128
+ setPages = _useState6[1];
94
129
 
95
- var _useState7 = (0, _react.useState)(_helpers.default.getNextPageId(type, _pages)),
130
+ var _useState7 = (0, _react.useState)(undefined),
96
131
  _useState8 = _slicedToArray(_useState7, 2),
97
- pageId = _useState8[0],
98
- setPageId = _useState8[1];
132
+ hub = _useState8[0],
133
+ setHub = _useState8[1];
99
134
 
100
- var _useState9 = (0, _react.useState)(_helpers.default.getFormState(pageId, pages, hub)),
135
+ var _useState9 = (0, _react.useState)(_helpers.default.getNextPageId(type, _pages)),
101
136
  _useState10 = _slicedToArray(_useState9, 2),
102
- formState = _useState10[0],
103
- setFormState = _useState10[1];
137
+ pageId = _useState10[0],
138
+ setPageId = _useState10[1];
104
139
 
105
- var _useState11 = (0, _react.useState)({}),
140
+ var _useState11 = (0, _react.useState)(_helpers.default.getFormState(pageId, pages, hub)),
106
141
  _useState12 = _slicedToArray(_useState11, 2),
107
- currentTask = _useState12[0],
108
- setCurrentTask = _useState12[1];
142
+ formState = _useState12[0],
143
+ setFormState = _useState12[1];
109
144
 
110
145
  var _useState13 = (0, _react.useState)({}),
111
146
  _useState14 = _slicedToArray(_useState13, 2),
112
- hubDetails = _useState14[0],
113
- setHubDetails = _useState14[1]; // Set up hooks.
147
+ currentTask = _useState14[0],
148
+ setCurrentTask = _useState14[1];
149
+
150
+ var _useState15 = (0, _react.useState)({}),
151
+ _useState16 = _slicedToArray(_useState15, 2),
152
+ hubDetails = _useState16[0],
153
+ setHubDetails = _useState16[1]; // Set up hooks.
114
154
 
115
155
 
116
156
  var _useHooks = (0, _hooks2.useHooks)(),
@@ -123,7 +163,13 @@ var FormRenderer = function FormRenderer(_ref) {
123
163
  addHook(key, _hooks[key]);
124
164
  });
125
165
  }
126
- }, [_hooks, addHook]); // Setup data.
166
+ }, [_hooks, addHook]); // Set up the useValidation hook.
167
+
168
+ var _useValidation = (0, _hooks2.useValidation)(),
169
+ addErrors = _useValidation.addErrors,
170
+ clearErrors = _useValidation.clearErrors,
171
+ validate = _useValidation.validate; // Setup data.
172
+
127
173
 
128
174
  (0, _react.useEffect)(function () {
129
175
  if (components && _pages && _data) {
@@ -160,7 +206,16 @@ var FormRenderer = function FormRenderer(_ref) {
160
206
  }, [hooks]);
161
207
  (0, _react.useEffect)(function () {
162
208
  setHubDetails(_hub);
163
- }, [_hub]); // Update task list pages with form data and update states
209
+ }, [_hub]); // Calling setData directly within the hooks.onSubmit success handler
210
+ // resulted in a sychronisation error. Handling it in a useEffect appears
211
+ // to be the way to deal with this... and it certainly seems to work.
212
+
213
+ (0, _react.useEffect)(function () {
214
+ if (submitted !== null && submitted !== void 0 && submitted.data) {
215
+ setData(submitted.data);
216
+ setSubmitted(undefined);
217
+ }
218
+ }, [submitted, setData, setSubmitted]); // Update task list pages with form data and update states
164
219
 
165
220
  (0, _react.useEffect)(function () {
166
221
  var pages = currentTask.fullPages;
@@ -190,15 +245,16 @@ var FormRenderer = function FormRenderer(_ref) {
190
245
  }, [currentTask.fullPages, data, hubDetails === null || hubDetails === void 0 ? void 0 : hubDetails.sections]);
191
246
 
192
247
  var onPageChange = function onPageChange(newPageId) {
248
+ clearErrors();
193
249
  setPageId(newPageId);
194
250
  hooks.onPageChange(newPageId);
195
251
  }; // Handle actions from pages.
196
252
 
197
253
 
198
- var onPageAction = function onPageAction(action, patch, onError) {
254
+ var onPageAction = function onPageAction(action, patch) {
199
255
  // Check to see whether the action is able to proceed, which in
200
256
  // in the case of a submission will validate the fields in the page.
201
- if (_helpers.default.canActionProceed(action, formState.page, onError)) {
257
+ if (_helpers.default.canActionProceed(action, formState.page, validate.page)) {
202
258
  if (action.type === _models.PageAction.TYPES.NAVIGATE) {
203
259
  _handlers.default.navigate(action, pageId, onPageChange);
204
260
  } else {
@@ -216,7 +272,9 @@ var FormRenderer = function FormRenderer(_ref) {
216
272
 
217
273
  var pageUpdate = function pageUpdate(next) {
218
274
  return onPageChange(_helpers.default.getNextPageId(type, pages, pageId, action, next));
219
- };
275
+ }; // const navigablePages = currentTask?.fullPages || pages;
276
+ // let pageUpdate = (next) => onPageChange(helpers.getNextPageId(type, navigablePages, pageId, action, next));
277
+
220
278
 
221
279
  if (action.type === _models.PageAction.TYPES.SAVE_AND_NAVIGATE) {
222
280
  pageUpdate = function pageUpdate() {
@@ -226,15 +284,16 @@ var FormRenderer = function FormRenderer(_ref) {
226
284
 
227
285
 
228
286
  hooks.onSubmit(action.type, submissionData, function (response) {
229
- // The backend response may well contain data we need so apply it.
230
- setData(function (prev) {
231
- var next = _objectSpread(_objectSpread({}, prev), response);
287
+ // The backend response may well contain data we need so apply it...
288
+ // ... but this needs to happen in a useEffect, not right away.
289
+ var sData = _objectSpread(_objectSpread({}, submissionData), response);
232
290
 
233
- pageUpdate(next);
234
- return next;
291
+ setSubmitted({
292
+ data: sData
235
293
  });
294
+ pageUpdate(sData);
236
295
  }, function (errors) {
237
- _handlers.default.submissionError(errors, onError);
296
+ _handlers.default.submissionError(errors, addErrors);
238
297
  });
239
298
  }
240
299
  }
@@ -266,11 +325,11 @@ var FormRenderer = function FormRenderer(_ref) {
266
325
  }; // Handle actions from "Check your answers".
267
326
 
268
327
 
269
- var onCYAAction = function onCYAAction(action, onError) {
328
+ var onCYAAction = function onCYAAction(action) {
270
329
  // Check to see whether the action is able to proceed, which in
271
330
  // in the case of a submission will validate the fields in the page.
272
331
  if (action.type === _models.PageAction.TYPES.SUBMIT) {
273
- if (_helpers.default.canCYASubmit(pages, onError)) {
332
+ if (_helpers.default.canCYASubmit(pages, validate.pages)) {
274
333
  // Submit.
275
334
  var submissionData = _utils.default.Format.form({
276
335
  pages: pages,
@@ -283,13 +342,13 @@ var FormRenderer = function FormRenderer(_ref) {
283
342
  hooks.onSubmit(action.type, submissionData, function () {
284
343
  return hooks.onFormComplete();
285
344
  }, function (errors) {
286
- return _handlers.default.submissionError(errors, onError);
345
+ return _handlers.default.submissionError(errors, addErrors);
287
346
  });
288
347
  }
289
348
  }
290
349
 
291
350
  if (action.type === _models.PageAction.TYPES.SAVE_AND_CONTINUE && hub === _models.HubFormats.TASK) {
292
- if (_helpers.default.canCYASubmit(currentTask.fullPages, onError)) {
351
+ if (_helpers.default.canCYASubmit(currentTask.fullPages, validate.pages)) {
293
352
  var _submissionData = _utils.default.Format.form({
294
353
  pages: pages,
295
354
  components: components
@@ -300,13 +359,13 @@ var FormRenderer = function FormRenderer(_ref) {
300
359
  hooks.onSubmit(action.type, _submissionData, function () {
301
360
  return onPageChange(_models.FormPages.HUB);
302
361
  }, function (errors) {
303
- return _handlers.default.submissionError(errors, onError);
362
+ return _handlers.default.submissionError(errors, addErrors);
304
363
  });
305
364
  }
306
365
  }
307
366
 
308
367
  if (action.type === _models.PageAction.TYPES.SAVE_AND_RETURN) {
309
- if (_helpers.default.canCYASubmit(currentTask.fullPages, onError)) {
368
+ if (_helpers.default.canCYASubmit(currentTask.fullPages, validate.pages)) {
310
369
  var _submissionData2 = _utils.default.Format.form({
311
370
  pages: pages,
312
371
  components: components
@@ -321,7 +380,7 @@ var FormRenderer = function FormRenderer(_ref) {
321
380
  onPageChange(_models.FormPages.HUB);
322
381
  }
323
382
  }, function (errors) {
324
- return _handlers.default.submissionError(errors, onError);
383
+ return _handlers.default.submissionError(errors, addErrors);
325
384
  });
326
385
  }
327
386
  }
@@ -354,7 +413,7 @@ var FormRenderer = function FormRenderer(_ref) {
354
413
  }));
355
414
  };
356
415
 
357
- FormRenderer.propTypes = {
416
+ FormRenderer.propTypes = InternalFormRenderer.propTypes = {
358
417
  title: _propTypes.default.string,
359
418
 
360
419
  /** See <a href="/?path=/docs/f-json--page#formtypes">FormTypes</a>. */
@@ -377,7 +436,7 @@ FormRenderer.propTypes = {
377
436
  summaryListClassModifiers: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.arrayOf(_propTypes.default.string)]),
378
437
  noChangeAction: _propTypes.default.bool
379
438
  };
380
- FormRenderer.defaultProps = {
439
+ FormRenderer.defaultProps = InternalFormRenderer.defaultProps = {
381
440
  type: _models.FormTypes.HUB,
382
441
  components: [],
383
442
  pages: [],
@@ -5,27 +5,18 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _utils = _interopRequireDefault(require("../../../utils"));
9
-
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
- // Local imports
13
-
14
8
  /**
15
9
  * Assesses whether the action can proceed when navigating, submitting, etc.
16
10
  * Presently, this will validate a page when submitting and, only if the page is
17
11
  * valid will it proceed. If it's simple navigation, it simply returns true.
18
12
  * @param {object} action The action object we're assessing.
19
13
  * @param {object} page The page configuration object this action relates to.
20
- * @param {Function} onError A function to call with any validation errors.
14
+ * @param {Function} pageValidator A function to validate the page.
21
15
  * @returns A boolean where `true` means the action can proceed and `false` means it cannot.
22
16
  */
23
- var canActionProceed = function canActionProceed(action, page, onError) {
17
+ var canActionProceed = function canActionProceed(action, page, pageValidator) {
24
18
  if (action.validate) {
25
- var errors = _utils.default.Validate.page(page);
26
-
27
- onError(errors);
28
- return errors.length === 0;
19
+ return pageValidator(page).length === 0;
29
20
  }
30
21
 
31
22
  return true;
@@ -1,73 +1,49 @@
1
1
  "use strict";
2
2
 
3
+ var _Validate = _interopRequireDefault(require("../../../utils/Validate"));
4
+
3
5
  var _canActionProceed = _interopRequireDefault(require("./canActionProceed"));
4
6
 
5
7
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
8
 
7
- function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
8
-
9
- function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
-
11
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
12
-
13
- function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
14
-
15
- function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
16
-
17
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
18
-
19
- describe('components', function () {
20
- describe('FormRenderer', function () {
21
- describe('helpers', function () {
22
- describe('canActionProceed', function () {
23
- it('should return true when the action does not require validation', function () {
24
- var ACTION = {
25
- validate: false
26
- };
27
- expect((0, _canActionProceed.default)(ACTION, {}, function () {})).toBeTruthy();
28
- });
29
- it('should return true when the page is valid', function () {
30
- var ACTION = {
31
- validate: true
32
- };
33
- var PAGE = {
34
- components: [{
35
- id: 'a',
36
- fieldId: 'a',
37
- label: 'Alpha',
38
- required: true
39
- }],
40
- formData: {
41
- a: 'Bravo'
42
- }
43
- };
44
- expect((0, _canActionProceed.default)(ACTION, PAGE, function () {})).toBeTruthy();
45
- });
46
- it('should return false when the page is invalid and should have called the onErrors method appropriately', function () {
47
- var ACTION = {
48
- validate: true
49
- };
50
- var PAGE = {
51
- components: [{
52
- id: 'a',
53
- fieldId: 'a',
54
- label: 'Alpha',
55
- required: true
56
- }],
57
- formData: {}
58
- };
59
- var ERRORS = [];
60
-
61
- var ON_ERROR = function ON_ERROR(errors) {
62
- ERRORS.push.apply(ERRORS, _toConsumableArray(errors));
63
- };
64
-
65
- expect((0, _canActionProceed.default)(ACTION, PAGE, ON_ERROR)).toBeFalsy();
66
- expect(ERRORS.length).toEqual(1);
67
- expect(ERRORS[0].id).toEqual('a');
68
- expect(ERRORS[0].error).toEqual('Alpha is required');
69
- });
70
- });
71
- });
9
+ // Local imports
10
+ describe('components.FormRenderer.helpers.canActionProceed', function () {
11
+ it('should return true when the action does not require validation', function () {
12
+ var ACTION = {
13
+ validate: false
14
+ };
15
+ expect((0, _canActionProceed.default)(ACTION, {}, _Validate.default.page)).toBeTruthy();
16
+ });
17
+ it('should return true when the page is valid', function () {
18
+ var ACTION = {
19
+ validate: true
20
+ };
21
+ var PAGE = {
22
+ components: [{
23
+ id: 'a',
24
+ fieldId: 'a',
25
+ label: 'Alpha',
26
+ required: true
27
+ }],
28
+ formData: {
29
+ a: 'Bravo'
30
+ }
31
+ };
32
+ expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page)).toBeTruthy();
33
+ });
34
+ it('should return false when the page is invalid', function () {
35
+ var ACTION = {
36
+ validate: true
37
+ };
38
+ var PAGE = {
39
+ components: [{
40
+ id: 'a',
41
+ fieldId: 'a',
42
+ label: 'Alpha',
43
+ required: true
44
+ }],
45
+ formData: {}
46
+ };
47
+ expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page)).toBeFalsy();
72
48
  });
73
49
  });