@ukhomeoffice/cop-react-form-renderer 4.12.0 → 4.13.1-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.
@@ -184,6 +184,7 @@ var Collection = function Collection(_ref) {
184
184
  full_path: full_path,
185
185
  components: config.item.map(function (component) {
186
186
  return _objectSpread(_objectSpread({}, component), {}, {
187
+ readonly: config.readonly ? true : component.readonly,
187
188
  label: _utils.default.interpolateString(component.label, _objectSpread(_objectSpread({}, item), {}, {
188
189
  index: labelCount
189
190
  })),
@@ -319,4 +319,63 @@ describe('components.FormComponent.Collection', function () {
319
319
  }
320
320
  }, _callee6);
321
321
  })));
322
+ it('should appropriately make child components of items readonly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() {
323
+ var COLLECTION, _renderWithValidation5, container, c, item, _item$childNodes2, title, itemContainer, formGroup, label, hint, input;
324
+
325
+ return regeneratorRuntime.wrap(function _callee7$(_context7) {
326
+ while (1) {
327
+ switch (_context7.prev = _context7.next) {
328
+ case 0:
329
+ COLLECTION = {
330
+ id: ID,
331
+ fieldId: ID,
332
+ type: _models.ComponentTypes.COLLECTION,
333
+ item: [TEXT_COMPONENT],
334
+ readonly: true
335
+ };
336
+ _renderWithValidation5 = (0, _setupTests.renderWithValidation)( /*#__PURE__*/_react2.default.createElement(_FormComponent.default, {
337
+ component: COLLECTION,
338
+ value: FORM_DATA[ID],
339
+ formData: FORM_DATA
340
+ })), container = _renderWithValidation5.container; // Check the container itself.
341
+
342
+ c = container.childNodes[0];
343
+ expect(c.tagName).toEqual('DIV');
344
+ expect(c.classList).toContain(_Collection.DEFAULT_CLASS); // And now check the single text component within it.
345
+
346
+ item = c.childNodes[0];
347
+ expect(item.tagName).toEqual('DIV');
348
+ expect(item.classList).toContain("".concat(_Collection.DEFAULT_CLASS, "__item"));
349
+ _item$childNodes2 = _slicedToArray(item.childNodes, 2), title = _item$childNodes2[0], itemContainer = _item$childNodes2[1];
350
+ expect(title.tagName).toEqual('LABEL');
351
+ expect(title.classList).toContain("".concat(_Collection.DEFAULT_CLASS, "__item-title"));
352
+ expect(itemContainer.tagName).toEqual('DIV');
353
+ expect(itemContainer.classList).toContain(_Container.DEFAULT_CLASS);
354
+ formGroup = itemContainer.childNodes[0];
355
+ expect(formGroup.tagName).toEqual('DIV');
356
+ expect(formGroup.classList).toContain('govuk-form-group');
357
+ label = formGroup.childNodes[0];
358
+ expect(label.tagName).toEqual('LABEL');
359
+ expect(label.classList).toContain('govuk-label');
360
+ expect(label.textContent).toEqual("".concat(TEXT_COMPONENT.label, " (optional)"));
361
+ expect(label.getAttribute('for')).toEqual("".concat(ID, "[0].").concat(TEXT_ID));
362
+ hint = formGroup.childNodes[1];
363
+ expect(hint.tagName).toEqual('SPAN');
364
+ expect(hint.classList).toContain('govuk-hint');
365
+ expect(hint.textContent).toEqual(TEXT_COMPONENT.hint);
366
+ input = formGroup.childNodes[2];
367
+ expect(input.tagName).toEqual('DIV'); // Now readonly, so a DIV.
368
+
369
+ expect(input.classList).toContain('hods-readonly'); // Now readonly, so hods-readonly
370
+
371
+ expect(input.id).toEqual("".concat(ID, "[0].").concat(TEXT_ID));
372
+ expect(input.textContent).toEqual(TEXT_VALUE);
373
+
374
+ case 30:
375
+ case "end":
376
+ return _context7.stop();
377
+ }
378
+ }
379
+ }, _callee7);
380
+ })));
322
381
  });
@@ -82,7 +82,9 @@ var Container = function Container(_ref) {
82
82
  return /*#__PURE__*/_react.default.createElement(_FormComponent.default, _extends({
83
83
  key: index
84
84
  }, attrs, {
85
- component: component,
85
+ component: _objectSpread(_objectSpread({}, component), {}, {
86
+ readonly: container.readonly ? true : component.readonly
87
+ }),
86
88
  formData: formData,
87
89
  value: val || defaultValue,
88
90
  wrap: wrap,
@@ -359,4 +359,55 @@ describe('components.FormComponent.Container', function () {
359
359
  }
360
360
  }, _callee6);
361
361
  })));
362
+ it('should appropriately make child components readonly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() {
363
+ var CONTAINER, _renderWithValidation7, container, c, formGroup, label, hint, input;
364
+
365
+ return regeneratorRuntime.wrap(function _callee7$(_context7) {
366
+ while (1) {
367
+ switch (_context7.prev = _context7.next) {
368
+ case 0:
369
+ CONTAINER = {
370
+ id: ID,
371
+ fieldId: ID,
372
+ type: _models.ComponentTypes.CONTAINER,
373
+ components: [TEXT_COMPONENT],
374
+ readonly: true
375
+ };
376
+ _renderWithValidation7 = (0, _setupTests.renderWithValidation)( /*#__PURE__*/_react2.default.createElement(_FormComponent.default, {
377
+ component: CONTAINER,
378
+ value: FORM_DATA[ID],
379
+ formData: FORM_DATA
380
+ })), container = _renderWithValidation7.container; // Check the container itself.
381
+
382
+ c = container.childNodes[0];
383
+ expect(c.tagName).toEqual('DIV');
384
+ expect(c.classList).toContain(_Container.DEFAULT_CLASS); // And now check the single text component within it.
385
+
386
+ formGroup = c.childNodes[0];
387
+ expect(formGroup.tagName).toEqual('DIV');
388
+ expect(formGroup.classList).toContain('govuk-form-group');
389
+ label = formGroup.childNodes[0];
390
+ expect(label.tagName).toEqual('LABEL');
391
+ expect(label.classList).toContain('govuk-label');
392
+ expect(label.textContent).toEqual("".concat(TEXT_COMPONENT.label, " (optional)"));
393
+ expect(label.getAttribute('for')).toEqual(TEXT_ID);
394
+ hint = formGroup.childNodes[1];
395
+ expect(hint.tagName).toEqual('SPAN');
396
+ expect(hint.classList).toContain('govuk-hint');
397
+ expect(hint.textContent).toEqual(TEXT_COMPONENT.hint);
398
+ input = formGroup.childNodes[2];
399
+ expect(input.tagName).toEqual('DIV'); // Now readonly, so a DIV.
400
+
401
+ expect(input.classList).toContain('hods-readonly'); // Now readonly, so hods-readonly
402
+
403
+ expect(input.id).toEqual(TEXT_ID);
404
+ expect(input.textContent).toEqual(TEXT_VALUE);
405
+
406
+ case 22:
407
+ case "end":
408
+ return _context7.stop();
409
+ }
410
+ }
411
+ }, _callee7);
412
+ })));
362
413
  });
@@ -25,12 +25,23 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
25
25
 
26
26
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
27
27
 
28
+ var setupChildrenJSX = function setupChildrenJSX(options, config) {
29
+ options.forEach(function (option) {
30
+ if (!Array.isArray(option.nested)) {
31
+ return;
32
+ }
33
+
34
+ option.children = getChildrenJsx(config, option.nested);
35
+ });
36
+ };
28
37
  /**
29
38
  * Separate function for each component type for the sake of
30
39
  * code clarity - having the additional bits and pieces in the
31
40
  * switch statement increases the cyclomatic complexity and
32
41
  * makes it much harder to follow what's going on.
33
42
  */
43
+
44
+
34
45
  var getAutocomplete = function getAutocomplete(config) {
35
46
  var attrs = (0, _cleanAttributes.default)(config);
36
47
 
@@ -48,6 +59,7 @@ var getCheckboxes = function getCheckboxes(config) {
48
59
  options = val;
49
60
  });
50
61
 
62
+ setupChildrenJSX(options, config);
51
63
  var attrs = (0, _cleanAttributes.default)(config);
52
64
  return /*#__PURE__*/_react.default.createElement(_copReactComponents.Checkboxes, _extends({}, attrs, {
53
65
  options: options
@@ -106,13 +118,7 @@ var getRadios = function getRadios(config) {
106
118
  options = val;
107
119
  });
108
120
 
109
- options.forEach(function (option) {
110
- if (!Array.isArray(option.nested)) {
111
- return;
112
- }
113
-
114
- option.children = getChildrenJsx(config, option.nested);
115
- });
121
+ setupChildrenJSX(options, config);
116
122
  var attrs = (0, _cleanAttributes.default)(config);
117
123
  return /*#__PURE__*/_react.default.createElement(_copReactComponents.Radios, _extends({}, attrs, {
118
124
  options: options
@@ -79,6 +79,7 @@ var validateComponent = function validateComponent(component, outerData, formDat
79
79
  error = message;
80
80
  break;
81
81
 
82
+ case _models.ComponentTypes.CHECKBOXES:
82
83
  case _models.ComponentTypes.RADIOS:
83
84
  var nestedErrors = [];
84
85
  (_component$data$optio = component.data.options) === null || _component$data$optio === void 0 ? void 0 : _component$data$optio.forEach(function (option) {
@@ -200,19 +200,19 @@ describe('utils.Validate.Component', function () {
200
200
  });
201
201
  });
202
202
  describe('when the component has a nested component', function () {
203
- it('should return no error when the radio component contains nested components without errors', function () {
203
+ it.each([['radios', 'text'], ['checkboxes', 'text']])('should return no error when the radio component contains nested components without errors', function (parentType, nestedType) {
204
204
  var NESTED_ID = 'nestedId';
205
205
  var NESTED_VALUE = 'nestedValue';
206
206
 
207
207
  var FORMDATA = _defineProperty({}, NESTED_ID, NESTED_VALUE);
208
208
 
209
209
  var COMPONENT = {
210
- type: 'radios',
210
+ type: parentType,
211
211
  id: 'a',
212
212
  data: {
213
213
  options: [{
214
214
  nested: [{
215
- type: 'text',
215
+ type: nestedType,
216
216
  fieldId: NESTED_ID,
217
217
  id: NESTED_ID,
218
218
  required: true
@@ -222,16 +222,16 @@ describe('utils.Validate.Component', function () {
222
222
  };
223
223
  expect((0, _validateComponent.default)(COMPONENT, undefined, FORMDATA)).toBeUndefined();
224
224
  });
225
- it('should return an error when the radio component contains nested components with errors', function () {
225
+ it.each([['radios', 'text'], ['checkboxes', 'text']])('should return an error when the radio component contains nested components with errors', function (parentType, nestedType) {
226
226
  var NESTED_ID = 'nestedId';
227
227
  var FORMDATA = {};
228
228
  var COMPONENT = {
229
- type: 'radios',
229
+ type: parentType,
230
230
  id: 'a',
231
231
  data: {
232
232
  options: [{
233
233
  nested: [{
234
- type: 'text',
234
+ type: nestedType,
235
235
  fieldId: NESTED_ID,
236
236
  id: NESTED_ID,
237
237
  required: true
@@ -244,10 +244,10 @@ describe('utils.Validate.Component', function () {
244
244
  error: "Field is required"
245
245
  }]);
246
246
  });
247
- it('should return no error when a non selected radio component contains nested components with errors', function () {
247
+ it.each([['radios'], ['checkboxes']])('should return no error when a non selected radio component contains nested components with errors', function (type) {
248
248
  var NESTED_ID = 'nestedId';
249
249
  var COMPONENT = {
250
- type: 'radios',
250
+ type: type,
251
251
  id: 'a',
252
252
  data: {
253
253
  options: [{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ukhomeoffice/cop-react-form-renderer",
3
- "version": "4.12.0",
3
+ "version": "4.13.1-alpha",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "clean": "rimraf dist",
@@ -16,7 +16,7 @@
16
16
  "post-compile": "rimraf dist/*.test.* dist/**/*.test.* dist/**/*.stories.* dist/docs dist/assets"
17
17
  },
18
18
  "dependencies": {
19
- "@ukhomeoffice/cop-react-components": "2.2.2",
19
+ "@ukhomeoffice/cop-react-components": "2.2.3-alpha",
20
20
  "axios": "^0.23.0",
21
21
  "dayjs": "^1.11.0",
22
22
  "govuk-frontend": "^4.3.1",