@ukhomeoffice/cop-react-form-renderer 6.6.1 → 6.11.1

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 (45) hide show
  1. package/dist/components/CheckYourAnswers/Answer.js +11 -5
  2. package/dist/components/CheckYourAnswers/Answer.test.js +67 -14
  3. package/dist/components/CheckYourAnswers/CheckYourAnswers.js +9 -5
  4. package/dist/components/CheckYourAnswers/CheckYourAnswers.test.js +156 -64
  5. package/dist/components/CollectionSummary/CollectionSummary.js +20 -3
  6. package/dist/components/CollectionSummary/CollectionSummary.test.js +66 -20
  7. package/dist/components/CollectionSummary/RenderListView.js +2 -2
  8. package/dist/components/CollectionSummary/SummaryCard.js +17 -6
  9. package/dist/components/CollectionSummary/SummaryCard.test.js +94 -37
  10. package/dist/components/CollectionSummary/SummaryCardDetails.js +78 -34
  11. package/dist/components/CollectionSummary/SummaryCardDetails.scss +9 -0
  12. package/dist/components/CollectionSummary/SummaryCardDetails.test.js +206 -10
  13. package/dist/components/FormComponent/Container.js +2 -1
  14. package/dist/components/FormComponent/Container.test.js +69 -0
  15. package/dist/components/FormComponent/helpers/getComponentFieldSet.js +1 -1
  16. package/dist/components/FormRenderer/FormRenderer.js +1 -0
  17. package/dist/components/SummaryList/SummaryList.js +8 -0
  18. package/dist/components/SummaryList/SummaryList.scss +15 -0
  19. package/dist/components/SummaryList/SummaryList.test.js +67 -7
  20. package/dist/components/SummaryList/SummaryListHeadingRowWithAction.js +53 -0
  21. package/dist/components/SummaryList/SummaryListHeadingRowWithAction.scss +38 -0
  22. package/dist/components/TaskList/TaskList.js +22 -5
  23. package/dist/components/TaskList/TaskList.scss +24 -0
  24. package/dist/components/TaskList/TaskList.test.js +160 -16
  25. package/dist/utils/CheckYourAnswers/getCYARowsForCollectionPage.js +27 -12
  26. package/dist/utils/CheckYourAnswers/getCYARowsForCollectionPage.test.js +145 -0
  27. package/dist/utils/CheckYourAnswers/{getComponentRowForCYA.js → getSummaryListRowForDetails.js} +10 -5
  28. package/dist/utils/CheckYourAnswers/getSummaryListRowForDetails.test.js +56 -0
  29. package/dist/utils/CollectionPage/getQuickEditPage.js +2 -1
  30. package/dist/utils/CollectionPage/getQuickEditPage.test.js +8 -0
  31. package/dist/utils/CollectionPage/mergeCollectionPages.js +10 -1
  32. package/dist/utils/CollectionPage/mergeCollectionPages.test.js +6 -6
  33. package/dist/utils/Component/elevateNestedComponents.js +2 -1
  34. package/dist/utils/Component/elevateNestedComponents.test.js +38 -0
  35. package/dist/utils/Component/optionIsSelected.js +5 -0
  36. package/dist/utils/Component/optionIsSelected.test.js +26 -0
  37. package/dist/utils/Operate/getLength.js +50 -0
  38. package/dist/utils/Operate/getLength.test.js +89 -0
  39. package/dist/utils/Operate/runPageOperations.js +2 -0
  40. package/dist/utils/Validate/validateComponent.js +7 -2
  41. package/dist/utils/Validate/validateComponent.test.js +31 -0
  42. package/dist/utils/Validate/validateTime.js +8 -0
  43. package/dist/utils/Validate/validateTime.test.js +46 -0
  44. package/package.json +1 -1
  45. package/dist/utils/CheckYourAnswers/getComponentRowForCYA.test.js +0 -41
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ var _getSummaryListRowForDetails = _interopRequireDefault(require("./getSummaryListRowForDetails"));
4
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
5
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
6
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
9
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
10
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
11
+ describe('utils.CheckYourAnswers.getSummaryListRowForDetails', function () {
12
+ var COMPONENT_A = {
13
+ type: 'text',
14
+ id: 'a',
15
+ fieldId: 'a',
16
+ label: 'Alpha'
17
+ };
18
+ var TITLE = {
19
+ type: 'title',
20
+ key: 'Bravo'
21
+ };
22
+ var PAGE = {
23
+ id: 'page',
24
+ components: [COMPONENT_A],
25
+ formData: {
26
+ a: 'Alpha Value'
27
+ }
28
+ };
29
+ it('should get a summary list row for a component', function () {
30
+ var row = (0, _getSummaryListRowForDetails.default)(PAGE, COMPONENT_A, null, {});
31
+ expect(row.props.row.key).toEqual(COMPONENT_A.label);
32
+ expect(row.props.row.value.props).toMatchObject({
33
+ component: COMPONENT_A,
34
+ value: PAGE.formData[COMPONENT_A.fieldId]
35
+ });
36
+ });
37
+ it('should get a summary list title row for a component with a type of title', function () {
38
+ var row = (0, _getSummaryListRowForDetails.default)(PAGE, TITLE, null, {});
39
+ expect(row.props.title).toEqual(TITLE.key);
40
+ });
41
+ it('should use a placeholder value for empty optional fields if one is provided', function () {
42
+ var CUSTOM_PAGE = _objectSpread(_objectSpread({}, PAGE), {}, {
43
+ components: [{
44
+ type: 'text',
45
+ fieldId: 'componentA',
46
+ label: 'Component A',
47
+ required: false
48
+ }]
49
+ });
50
+ var summaryListRow = (0, _getSummaryListRowForDetails.default)(CUSTOM_PAGE, CUSTOM_PAGE.components[0], null, {}, 'Not entered');
51
+ expect(summaryListRow.props.row.key).toEqual('Component A');
52
+ expect(summaryListRow.props.row.value.props).toMatchObject({
53
+ placeholder: 'Not entered'
54
+ });
55
+ });
56
+ });
@@ -55,6 +55,7 @@ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input ==
55
55
  * @returns Page suitble for rendering in a QuickEdit
56
56
  */
57
57
  var getQuickEditPage = function getQuickEditPage(masterPage, formData, entryData) {
58
+ var _masterPage$collectio;
58
59
  if (!masterPage) {
59
60
  return null;
60
61
  }
@@ -113,7 +114,7 @@ var getQuickEditPage = function getQuickEditPage(masterPage, formData, entryData
113
114
  // Remove ID to stop overwriting top-level form ID.
114
115
  var id = entryData.id,
115
116
  entryWithNoId = _objectWithoutProperties(entryData, _excluded);
116
- pageToReturn.formData = _objectSpread(_objectSpread({}, pageToReturn.formData), entryWithNoId);
117
+ pageToReturn.formData = _objectSpread(_objectSpread(_objectSpread({}, pageToReturn.formData), entryWithNoId), {}, _defineProperty({}, "".concat((_masterPage$collectio = masterPage.collection) === null || _masterPage$collectio === void 0 || (_masterPage$collectio = _masterPage$collectio.name) === null || _masterPage$collectio === void 0 ? void 0 : _masterPage$collectio.split('.').pop(), "ActiveId"), entryData.id));
117
118
  delete pageToReturn.title;
118
119
  delete pageToReturn.collection;
119
120
  return pageToReturn;
@@ -19,6 +19,9 @@ describe('Utils.CollectionPage.getQuickEditPage', function () {
19
19
  }]
20
20
  };
21
21
  var MASTER_PAGE = {
22
+ collection: {
23
+ name: 'entries'
24
+ },
22
25
  childPages: [{
23
26
  id: 'firstPage',
24
27
  name: 'firstPage',
@@ -132,4 +135,9 @@ describe('Utils.CollectionPage.getQuickEditPage', function () {
132
135
  var createdPage = (0, _getQuickEditPage.default)(MASTER_PAGE, FORM_DATA, CUSTOM_ENTRY_DATA);
133
136
  expect(createdPage).toMatchObject(CUSTOM_OUTPUT);
134
137
  });
138
+ it('should return a quick edit page with the activeId for the current collection correctly set', function () {
139
+ var createdPage = (0, _getQuickEditPage.default)(MASTER_PAGE, FORM_DATA, ENTRY_DATA);
140
+ expect(createdPage.formData.entriesActiveId).toEqual('123');
141
+ expect(createdPage).toMatchObject(EXPECTED_OUTPUT);
142
+ });
135
143
  });
@@ -32,6 +32,7 @@ var createMasterPage = function createMasterPage(page) {
32
32
  return {
33
33
  id: page.id,
34
34
  name: page.name,
35
+ orderInForm: page.orderInForm,
35
36
  collection: _objectSpread({
36
37
  masterPage: true
37
38
  }, page.collection),
@@ -68,6 +69,12 @@ var nestUnderParent = function nestUnderParent(childPage, masterPages) {
68
69
  return false;
69
70
  }
70
71
  parentPage.childPages.push(childPage);
72
+
73
+ // Sort the pages to make sure they're in the same order
74
+ // they were in on the form.
75
+ parentPage.childPages.sort(function (a, b) {
76
+ return a.orderInForm - b.orderInForm;
77
+ });
71
78
  return true;
72
79
  };
73
80
 
@@ -84,8 +91,9 @@ var nestUnderParent = function nestUnderParent(childPage, masterPages) {
84
91
  */
85
92
  var mergeCollectionPages = function mergeCollectionPages(pages) {
86
93
  var masterPages = {};
87
- var pagesWithMasters = pages.map(function (page) {
94
+ var pagesWithMasters = pages.map(function (page, index) {
88
95
  var _page$collection;
96
+ page.orderInForm = index;
89
97
  if (page !== null && page !== void 0 && (_page$collection = page.collection) !== null && _page$collection !== void 0 && _page$collection.name) {
90
98
  if (!masterPages[page.collection.name]) {
91
99
  // If no master page exists for this collection.name, then
@@ -104,6 +112,7 @@ var mergeCollectionPages = function mergeCollectionPages(pages) {
104
112
  }).filter(function (page) {
105
113
  return !!page;
106
114
  });
115
+
107
116
  // We nest any child master pages under their parents here to
108
117
  // ensure that all parent master pages have been created by the
109
118
  // above code first.
@@ -131,7 +131,7 @@ describe('utils.CollectionPage.mergeCollectionPages', function () {
131
131
  masterPage: true
132
132
  },
133
133
  formData: {},
134
- childPages: [PAGES[2], PAGES[3], {
134
+ childPages: [{
135
135
  id: 'page1',
136
136
  collection: {
137
137
  name: 'parent.child',
@@ -139,7 +139,7 @@ describe('utils.CollectionPage.mergeCollectionPages', function () {
139
139
  },
140
140
  formData: {},
141
141
  childPages: [PAGES[0], PAGES[1]]
142
- }]
142
+ }, PAGES[2], PAGES[3]]
143
143
  });
144
144
  });
145
145
  it('should leave non-collection pages unaffected', function () {
@@ -160,7 +160,7 @@ describe('utils.CollectionPage.mergeCollectionPages', function () {
160
160
  }];
161
161
  var RESULT = (0, _mergeCollectionPages.default)(PAGES);
162
162
  expect(RESULT.length).toEqual(2);
163
- expect(RESULT[0]).toEqual({
163
+ expect(RESULT[0]).toMatchObject({
164
164
  id: 'page1',
165
165
  collection: {
166
166
  name: 'collection',
@@ -169,7 +169,7 @@ describe('utils.CollectionPage.mergeCollectionPages', function () {
169
169
  formData: {},
170
170
  childPages: [PAGES[0], PAGES[1]]
171
171
  });
172
- expect(RESULT[1]).toEqual({
172
+ expect(RESULT[1]).toMatchObject({
173
173
  id: 'page3'
174
174
  });
175
175
  });
@@ -201,7 +201,7 @@ describe('utils.CollectionPage.mergeCollectionPages', function () {
201
201
  }];
202
202
  var RESULT = (0, _mergeCollectionPages.default)(PAGES);
203
203
  expect(RESULT.length).toEqual(2);
204
- expect(RESULT[0]).toEqual({
204
+ expect(RESULT[0]).toMatchObject({
205
205
  id: 'page1',
206
206
  collection: {
207
207
  name: 'collection1',
@@ -210,7 +210,7 @@ describe('utils.CollectionPage.mergeCollectionPages', function () {
210
210
  formData: {},
211
211
  childPages: [PAGES[0], PAGES[1]]
212
212
  });
213
- expect(RESULT[1]).toEqual({
213
+ expect(RESULT[1]).toMatchObject({
214
214
  id: 'page3',
215
215
  collection: {
216
216
  name: 'collection2',
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
  var _Data = _interopRequireDefault(require("../Data"));
8
+ var _optionIsSelected = _interopRequireDefault(require("./optionIsSelected"));
8
9
  var _showComponent = _interopRequireDefault(require("./showComponent"));
9
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
11
  /**
@@ -45,7 +46,7 @@ var elevateNestedComponents = function elevateNestedComponents(components, data)
45
46
  // selected, then add its nested components to the array.
46
47
  var sourceData = (data === null || data === void 0 ? void 0 : data[component.id]) || _Data.default.getSource(data, component.full_path);
47
48
  // If the specific option wasn't shown we shouldn't elevate anything nested under it
48
- if (Array.isArray(option.nested) && sourceData === option.value && (0, _showComponent.default)(option, data)) {
49
+ if (Array.isArray(option.nested) && (0, _optionIsSelected.default)(sourceData, option) && (0, _showComponent.default)(option, data)) {
49
50
  allComponents = allComponents.concat(option.nested);
50
51
  }
51
52
  });
@@ -263,4 +263,42 @@ describe('utils.Component.elevateNestedComponents', function () {
263
263
  };
264
264
  expect((0, _elevateNestedComponents.default)(COMPONENTS, DATA)).toEqual([].concat(COMPONENTS));
265
265
  });
266
+ it('should return the original array with elevated nested components that are defined using refdata_match when they are visible', function () {
267
+ var COMPONENTS = [{
268
+ id: 'textComp'
269
+ }, {
270
+ id: 'checkboxComp',
271
+ data: {
272
+ options: [{
273
+ label: 'Yes',
274
+ value: 'yes',
275
+ id: 99
276
+ }, {
277
+ label: 'No',
278
+ value: 'no',
279
+ id: 100
280
+ }, {
281
+ nested: [{
282
+ id: 'nestedOne'
283
+ }, {
284
+ id: 'nestedTwo'
285
+ }],
286
+ refdata_match: {
287
+ id: 99
288
+ }
289
+ }]
290
+ }
291
+ }];
292
+ var DATA = {
293
+ checkboxComp: [{
294
+ value: 'yes',
295
+ id: 99
296
+ }]
297
+ };
298
+ expect((0, _elevateNestedComponents.default)(COMPONENTS, DATA)).toEqual([].concat(COMPONENTS, [{
299
+ id: 'nestedOne'
300
+ }, {
301
+ id: 'nestedTwo'
302
+ }]));
303
+ });
266
304
  });
@@ -14,6 +14,11 @@ exports.default = void 0;
14
14
  */
15
15
  var optionIsSelected = function optionIsSelected(componentValue, option) {
16
16
  if (Array.isArray(componentValue)) {
17
+ if (option.refdata_match) {
18
+ return componentValue.some(function (v) {
19
+ return v.id === option.refdata_match.id;
20
+ });
21
+ }
17
22
  return componentValue.includes(option.value);
18
23
  }
19
24
  return componentValue === option.value;
@@ -11,6 +11,20 @@ describe('utils.Component.isSelected', function () {
11
11
  value: SELECTED_VALUE
12
12
  }, {
13
13
  value: NOT_SELECTED_VALUE
14
+ }, {
15
+ refdata_match: {
16
+ id: 99
17
+ },
18
+ nested: {
19
+ value: true
20
+ }
21
+ }, {
22
+ refdata_match: {
23
+ id: 100
24
+ },
25
+ nested: {
26
+ value: true
27
+ }
14
28
  }];
15
29
  var COMPONENT = {
16
30
  id: 'a',
@@ -29,6 +43,18 @@ describe('utils.Component.isSelected', function () {
29
43
  expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[0])).toEqual(true);
30
44
  expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[1])).toEqual(false);
31
45
  });
46
+ it('should properly identify which option is selected for checkboxes using refdata_match', function () {
47
+ var PAGE = {
48
+ formData: {
49
+ a: [{
50
+ id: 99
51
+ }]
52
+ }
53
+ };
54
+ COMPONENT.type = 'checkboxes';
55
+ expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[2])).toEqual(true);
56
+ expect((0, _optionIsSelected.default)(PAGE.formData[COMPONENT.id], OPTIONS[3])).toEqual(false);
57
+ });
32
58
  it('should properly identify which option is selected for radios', function () {
33
59
  var PAGE = {
34
60
  formData: {
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _copReactComponents = require("@ukhomeoffice/cop-react-components");
8
+ var _getCollectionPageActiveIndex = _interopRequireDefault(require("../CollectionPage/getCollectionPageActiveIndex"));
9
+ var _getSourceData = _interopRequireDefault(require("../Data/getSourceData"));
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+ // Global imports.
12
+
13
+ // Local imports.
14
+
15
+ /**
16
+ * Finds a field within data and returns its length
17
+ * @param {object} config The config of the operation.
18
+ * @param {string} config.target The path to the target field. If the path
19
+ * goes through a collection this can be specified as 'collectionName[]'
20
+ * and this function will use the active entry within that collection.
21
+ * @param {object} data A page's formData.
22
+ * @returns The length of a field if found or 0
23
+ */
24
+ var getLength = function getLength(config, data) {
25
+ if (!config || !data) {
26
+ return null;
27
+ }
28
+
29
+ // Replace any instances of 'collectionName[]' with 'collectionName[activeIndex]'
30
+ var pathParts = config.target.split('.');
31
+ var updatedPath = '';
32
+ pathParts.forEach(function (part) {
33
+ if (updatedPath !== '') {
34
+ updatedPath += '.';
35
+ }
36
+ if (part.slice(-2) === '[]') {
37
+ var collectionName = part.slice(0, -2);
38
+ var activeIndex = (0, _getCollectionPageActiveIndex.default)(collectionName, data);
39
+ updatedPath += "".concat(collectionName, "[").concat(activeIndex, "]");
40
+ } else {
41
+ updatedPath += part;
42
+ }
43
+ });
44
+
45
+ // Get the field and return its length
46
+ var targetPath = _copReactComponents.Utils.interpolateString(updatedPath, data);
47
+ var target = (0, _getSourceData.default)(data, targetPath);
48
+ return (target === null || target === void 0 ? void 0 : target.length) || 0;
49
+ };
50
+ var _default = exports.default = getLength;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+
3
+ var _getLength = _interopRequireDefault(require("./getLength"));
4
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
5
+ describe('Utils.Operate.getLength', function () {
6
+ it('returns null if config is not defined', function () {
7
+ expect((0, _getLength.default)(null, {})).toEqual(null);
8
+ });
9
+ it('returns null if data is not defined', function () {
10
+ expect((0, _getLength.default)({}, null)).toEqual(null);
11
+ });
12
+ it('returns the length of a top level string', function () {
13
+ var CONFIG = {
14
+ target: 'alpha'
15
+ };
16
+ var DATA = {
17
+ alpha: 'abcdef'
18
+ };
19
+ expect((0, _getLength.default)(CONFIG, DATA)).toEqual(6);
20
+ });
21
+ it('returns the length of a top level array', function () {
22
+ var CONFIG = {
23
+ target: 'alpha'
24
+ };
25
+ var DATA = {
26
+ alpha: [{
27
+ test: 'test'
28
+ }, {
29
+ test: 'test'
30
+ }, {
31
+ test: 'test'
32
+ }, {
33
+ test: 'test'
34
+ }]
35
+ };
36
+ expect((0, _getLength.default)(CONFIG, DATA)).toEqual(4);
37
+ });
38
+ it('returns 0 if the field cannot be found', function () {
39
+ var CONFIG = {
40
+ target: 'alpha'
41
+ };
42
+ var DATA = {
43
+ beta: [{
44
+ test: 'test'
45
+ }, {
46
+ test: 'test'
47
+ }, {
48
+ test: 'test'
49
+ }, {
50
+ test: 'test'
51
+ }]
52
+ };
53
+ expect((0, _getLength.default)(CONFIG, DATA)).toEqual(0);
54
+ });
55
+ it('returns the length of a field not on the top level', function () {
56
+ var CONFIG = {
57
+ target: 'alpha.beta'
58
+ };
59
+ var DATA = {
60
+ alphaActiveId: 3,
61
+ alpha: {
62
+ beta: 'qwerty'
63
+ }
64
+ };
65
+ expect((0, _getLength.default)(CONFIG, DATA)).toEqual(6);
66
+ });
67
+ it('returns the length of an array nested under an array', function () {
68
+ var CONFIG = {
69
+ target: 'alpha[].beta'
70
+ };
71
+ var DATA = {
72
+ alphaActiveId: 3,
73
+ alpha: [{
74
+ id: 1,
75
+ beta: ['test']
76
+ }, {
77
+ id: 2,
78
+ beta: ['test', 'test']
79
+ }, {
80
+ id: 3,
81
+ beta: ['test', 'test', 'test']
82
+ }, {
83
+ id: 4,
84
+ beta: ['test', 'test', 'test', 'test']
85
+ }]
86
+ };
87
+ expect((0, _getLength.default)(CONFIG, DATA)).toEqual(3);
88
+ });
89
+ });
@@ -12,6 +12,7 @@ var _setValueInFormData = _interopRequireDefault(require("./setValueInFormData")
12
12
  var _shouldRun = _interopRequireDefault(require("./shouldRun"));
13
13
  var _setDataItem = _interopRequireDefault(require("../Data/setDataItem"));
14
14
  var _getFirstOf = _interopRequireDefault(require("./getFirstOf"));
15
+ var _getLength = _interopRequireDefault(require("./getLength"));
15
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17
  // Global imports.
17
18
 
@@ -22,6 +23,7 @@ var functions = {
22
23
  getIndexOfMatchingValueIn: _getIndexOfMatchingValueIn.default,
23
24
  persistValueInFormData: _persistValueInFormData.default,
24
25
  setValueInFormData: _setValueInFormData.default,
26
+ getLength: _getLength.default,
25
27
  getFirstOf: _getFirstOf.default
26
28
  };
27
29
  var doOperation = function doOperation(config, data, onChange) {
@@ -19,7 +19,12 @@ var _validateRequired = _interopRequireDefault(require("./validateRequired"));
19
19
  var _validateTextArea = _interopRequireDefault(require("./validateTextArea"));
20
20
  var _validateTime = _interopRequireDefault(require("./validateTime"));
21
21
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } // Local imports
22
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
23
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
24
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
25
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
26
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
27
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } // Local imports
23
28
  /**
24
29
  * Validates a single component.
25
30
  * @param {object} component The component to validate.
@@ -29,7 +34,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
29
34
  */
30
35
  var validateComponent = function validateComponent(component, outerData, formData) {
31
36
  var fd = formData || outerData;
32
- if (!(0, _showComponent.default)(component, fd)) {
37
+ if (!(0, _showComponent.default)(component, _objectSpread(_objectSpread({}, fd), outerData))) {
33
38
  return undefined;
34
39
  }
35
40
  if (component.type === _models.ComponentTypes.CONTAINER) {
@@ -182,6 +182,37 @@ describe('utils.Validate.Component', function () {
182
182
  var DATA = _defineProperty({}, ID, _defineProperty({}, EMAIL_ID, 'alpha.bravo@digital.homeoffice.gov.uk'));
183
183
  expect((0, _validateComponent.default)(CONTAINER, DATA)).toEqual([]);
184
184
  });
185
+ it('should return an empty array when the container has only valid components', function () {
186
+ var TEXT_COMPONENT = {
187
+ id: 'one',
188
+ fieldId: 'one',
189
+ type: _models.ComponentTypes.TEXT,
190
+ label: 'Text component one'
191
+ };
192
+ var TEXT_COMPONENT_TWO = {
193
+ id: 'two',
194
+ fieldId: 'two',
195
+ type: _models.ComponentTypes.TEXT,
196
+ label: 'Text component two',
197
+ required: true,
198
+ show_when: {
199
+ field: 'one',
200
+ op: '=',
201
+ value: 'other'
202
+ }
203
+ };
204
+ var ID = 'container';
205
+ var LABEL = 'field';
206
+ var CONTAINER = setup(ID, _models.ComponentTypes.CONTAINER, LABEL, false);
207
+ CONTAINER.components = [TEXT_COMPONENT, TEXT_COMPONENT_TWO];
208
+ var DATA = _defineProperty({}, ID, {
209
+ one: 'other'
210
+ });
211
+ var errors = (0, _validateComponent.default)(CONTAINER, DATA, {
212
+ colour: 'blue'
213
+ });
214
+ expect(errors.length).toEqual(1);
215
+ });
185
216
  });
186
217
  describe('when the component is a collection', function () {
187
218
  it('should return an empty array when the collection has only valid items', function () {
@@ -39,6 +39,11 @@ var validateTime = function validateTime(time) {
39
39
  var intMinute = parseInt(minute, 10);
40
40
  var badProps = [];
41
41
  var messages = [];
42
+ var numericRegex = /^\d{0,2}:\d{0,2}$/;
43
+ if (!numericRegex.test(time)) {
44
+ badProps.push('invalid');
45
+ messages.push('Enter a valid time');
46
+ }
42
47
  if (hour.length === 0) {
43
48
  badProps.push('hour');
44
49
  messages.push('Time must include a hour');
@@ -61,6 +66,9 @@ var validateTime = function validateTime(time) {
61
66
  if (badProps.includes('minute')) {
62
67
  propsInError.minute = true;
63
68
  }
69
+ if (badProps.includes('invalid')) {
70
+ propsInError.invalid = true;
71
+ }
64
72
  return {
65
73
  message: badProps.length > 1 ? 'Enter a valid time' : messages[0],
66
74
  propsInError: propsInError
@@ -64,6 +64,52 @@ describe('utils', function () {
64
64
  }
65
65
  });
66
66
  });
67
+ test('should return an error if the time string contains non-numeric characters', function () {
68
+ var output = (0, _validateTime.default)('14:3A');
69
+ expect(output).toEqual({
70
+ message: 'Enter a valid time',
71
+ propsInError: {
72
+ invalid: true,
73
+ minute: true
74
+ }
75
+ });
76
+ });
77
+ test('should return an error if the time string contains more than two digits in hour', function () {
78
+ var output = (0, _validateTime.default)('144:30');
79
+ expect(output).toEqual({
80
+ message: 'Enter a valid time',
81
+ propsInError: {
82
+ invalid: true,
83
+ hour: true
84
+ }
85
+ });
86
+ });
87
+ test('should return an error if the time string contains more than two digits in minute', function () {
88
+ var output = (0, _validateTime.default)('14:309');
89
+ expect(output).toEqual({
90
+ message: 'Enter a valid time',
91
+ propsInError: {
92
+ invalid: true,
93
+ minute: true
94
+ }
95
+ });
96
+ });
97
+ test('should return an error if there is an additional colon in the time string', function () {
98
+ var output = (0, _validateTime.default)('14:30:');
99
+ expect(output).toEqual({
100
+ message: 'Enter a valid time',
101
+ propsInError: {
102
+ invalid: true
103
+ }
104
+ });
105
+ });
106
+ test('should return no error if there is a single digit for both hour and minute', function () {
107
+ var output = (0, _validateTime.default)('1:1');
108
+ expect(output).toEqual({
109
+ message: undefined,
110
+ propsInError: undefined
111
+ });
112
+ });
67
113
  });
68
114
  });
69
115
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ukhomeoffice/cop-react-form-renderer",
3
- "version": "6.6.1",
3
+ "version": "6.11.1",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "clean": "rimraf dist",
@@ -1,41 +0,0 @@
1
- "use strict";
2
-
3
- var _getCYARowsForPage = _interopRequireDefault(require("./getCYARowsForPage"));
4
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
5
- describe('utils.CheckYourAnswers.getCYARowsForPage', function () {
6
- var COMPONENT_A = {
7
- type: 'text',
8
- id: 'a',
9
- fieldId: 'a',
10
- label: 'Alpha'
11
- };
12
- var COMPONENT_B = {
13
- type: 'text',
14
- id: 'b',
15
- fieldId: 'b',
16
- label: 'Bravo'
17
- };
18
- var PAGE = {
19
- id: 'page',
20
- components: [COMPONENT_A, COMPONENT_B],
21
- formData: {
22
- a: 'Alpha Value',
23
- b: 'Bravo Value'
24
- }
25
- };
26
- var ON_ACTION = function ON_ACTION() {};
27
- it('should get rows for a page with readonly text components', function () {
28
- var rows = (0, _getCYARowsForPage.default)(PAGE, ON_ACTION);
29
- expect(rows.length).toEqual(2);
30
- expect(rows[0]).toEqual(expect.objectContaining({
31
- fieldId: COMPONENT_A.fieldId,
32
- key: COMPONENT_A.label,
33
- value: 'Alpha Value'
34
- }));
35
- expect(rows[1]).toEqual(expect.objectContaining({
36
- fieldId: COMPONENT_B.fieldId,
37
- key: COMPONENT_B.label,
38
- value: 'Bravo Value'
39
- }));
40
- });
41
- });