@ukhomeoffice/cop-react-form-renderer 5.18.1 → 5.19.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.
@@ -91,6 +91,17 @@ var Collection = function Collection(_ref) {
91
91
  return _ref3.apply(this, arguments);
92
92
  };
93
93
  }();
94
+ (0, _react.useEffect)(function () {
95
+ if (config.focusOnAdd && Array.isArray(value) && value.length) {
96
+ if (value.length > config.minimumEntries || !config.minimumEntries) {
97
+ var _value2, _document$getElementB, _focusable$;
98
+ var containerId = (_value2 = value[value.length - 1]) === null || _value2 === void 0 ? void 0 : _value2.id;
99
+ var container = (_document$getElementB = document.getElementById(containerId)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.childNodes[0];
100
+ var focusable = container === null || container === void 0 ? void 0 : container.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
101
+ (_focusable$ = focusable[0]) === null || _focusable$ === void 0 ? void 0 : _focusable$.focus();
102
+ }
103
+ }
104
+ }, [value.length, config.focusOnAdd, config.minimumEntries]);
94
105
  (0, _react.useEffect)(function () {
95
106
  if (config.minimumEntries && !value.length) {
96
107
  onAddAnother();
@@ -216,6 +227,7 @@ Collection.propTypes = {
216
227
  readonly: _propTypes.default.bool,
217
228
  removeLocation: _propTypes.default.string,
218
229
  subsequentItemStyle: _propTypes.default.shape({}),
230
+ focusOnAdd: _propTypes.default.bool,
219
231
  required: _propTypes.default.bool
220
232
  }).isRequired,
221
233
  formData: _propTypes.default.shape({}),
@@ -805,4 +805,163 @@ describe('components.FormComponent.Collection', function () {
805
805
  }
806
806
  }, _callee14);
807
807
  })));
808
+ it('should shift focus to most recent item on addition and removal of an item when focusOnAdd is true', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {
809
+ var COLLECTION, container, c, addButton, item, label, secondItem, secondItemLabel, removeButton;
810
+ return _regeneratorRuntime().wrap(function _callee16$(_context16) {
811
+ while (1) switch (_context16.prev = _context16.next) {
812
+ case 0:
813
+ COLLECTION = {
814
+ id: ID,
815
+ fieldId: ID,
816
+ type: _models.ComponentTypes.COLLECTION,
817
+ item: [TEXT_COMPONENT],
818
+ focusOnAdd: true
819
+ };
820
+ container = document.createElement('div');
821
+ document.body.appendChild(container);
822
+ _context16.next = 5;
823
+ return (0, _testUtils.act)( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15() {
824
+ return _regeneratorRuntime().wrap(function _callee15$(_context15) {
825
+ while (1) switch (_context15.prev = _context15.next) {
826
+ case 0:
827
+ (0, _setupTests.renderDomWithValidation)( /*#__PURE__*/_react2.default.createElement(_FormComponent.default, {
828
+ component: COLLECTION
829
+ }), container);
830
+ case 1:
831
+ case "end":
832
+ return _context15.stop();
833
+ }
834
+ }, _callee15);
835
+ })));
836
+ case 5:
837
+ // Check the container itself.
838
+ c = container.childNodes[0];
839
+ expect(c.tagName).toEqual('DIV');
840
+ expect(c.classList).toContain(_Collection.DEFAULT_CLASS);
841
+
842
+ // And now make sure it has no children OTHER than the button to add an item.
843
+ expect(c.childNodes.length).toEqual(1);
844
+
845
+ // Get hold of that "Add another" button and click it.
846
+ addButton = c.childNodes[0].childNodes[0];
847
+ _react.fireEvent.click(addButton, {});
848
+
849
+ // Make sure an item has been added.
850
+ expect(c.childNodes.length).toEqual(2);
851
+ item = c.childNodes[0];
852
+ label = item.childNodes[0];
853
+ expect(label.textContent).toContain(_utils.default.interpolateString(_models.CollectionLabels.item, {
854
+ index: 1
855
+ }));
856
+
857
+ // Check to see if the item's text input is in focus
858
+ expect(document.activeElement === item.childNodes[1].childNodes[0].querySelector("input")).toEqual(true);
859
+
860
+ // Add another item and check if the second item has been added and it's input is in focus
861
+ _react.fireEvent.click(addButton, {});
862
+ secondItem = c.childNodes[1];
863
+ secondItemLabel = secondItem.childNodes[0];
864
+ expect(c.childNodes.length).toEqual(3);
865
+ expect(document.activeElement === secondItem.childNodes[1].childNodes[0].querySelector("input")).toEqual(true);
866
+
867
+ // Get hold of the second item's "Remove" button.
868
+ removeButton = secondItemLabel.childNodes[1];
869
+ expect(removeButton.tagName).toEqual('BUTTON');
870
+ expect(removeButton.classList).toContain('hods-button--secondary');
871
+ expect(removeButton.textContent).toContain(_models.CollectionLabels.remove);
872
+
873
+ // Click the "Remove" button
874
+ _react.fireEvent.click(removeButton, {});
875
+
876
+ // Make sure the second item has been removed.
877
+ expect(c.childNodes.length).toEqual(2);
878
+ expect(c.childNodes[1].classList).toContain('hods-button-group');
879
+
880
+ // Check to see if the first item is now in focus
881
+ expect(document.activeElement === item.childNodes[1].childNodes[0].querySelector("input")).toEqual(true);
882
+ case 29:
883
+ case "end":
884
+ return _context16.stop();
885
+ }
886
+ }, _callee16);
887
+ })));
888
+ it('should not focus on first item when minimumEntries is 1 and focus on added item instead when focusOnAdd is true', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18() {
889
+ var COLLECTION, container, c, item, _item$childNodes6, title, itemContainer, formGroup, label, hint, input, addButton, secondItem;
890
+ return _regeneratorRuntime().wrap(function _callee18$(_context18) {
891
+ while (1) switch (_context18.prev = _context18.next) {
892
+ case 0:
893
+ COLLECTION = {
894
+ id: ID,
895
+ fieldId: ID,
896
+ type: _models.ComponentTypes.COLLECTION,
897
+ item: [TEXT_COMPONENT],
898
+ focusOnAdd: true,
899
+ minimumEntries: 1
900
+ };
901
+ container = document.createElement('div');
902
+ document.body.appendChild(container);
903
+ _context18.next = 5;
904
+ return (0, _testUtils.act)( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee17() {
905
+ return _regeneratorRuntime().wrap(function _callee17$(_context17) {
906
+ while (1) switch (_context17.prev = _context17.next) {
907
+ case 0:
908
+ (0, _setupTests.renderDomWithValidation)( /*#__PURE__*/_react2.default.createElement(_FormComponent.default, {
909
+ component: COLLECTION
910
+ }), container);
911
+ case 1:
912
+ case "end":
913
+ return _context17.stop();
914
+ }
915
+ }, _callee17);
916
+ })));
917
+ case 5:
918
+ // Check the container itself.
919
+ c = container.childNodes[0];
920
+ expect(c.tagName).toEqual('DIV');
921
+ expect(c.classList).toContain(_Collection.DEFAULT_CLASS);
922
+
923
+ // And now check the single text component within it.
924
+ item = c.childNodes[0];
925
+ expect(item.tagName).toEqual('DIV');
926
+ expect(item.classList).toContain("".concat(_Collection.DEFAULT_CLASS, "__item"));
927
+ _item$childNodes6 = _slicedToArray(item.childNodes, 2), title = _item$childNodes6[0], itemContainer = _item$childNodes6[1];
928
+ expect(title.tagName).toEqual('LABEL');
929
+ expect(title.classList).toContain("".concat(_Collection.DEFAULT_CLASS, "__item-title"));
930
+ expect(itemContainer.tagName).toEqual('DIV');
931
+ expect(itemContainer.classList).toContain(_Container.DEFAULT_CLASS);
932
+ formGroup = itemContainer.childNodes[0];
933
+ expect(formGroup.tagName).toEqual('DIV');
934
+ expect(formGroup.classList).toContain('govuk-form-group');
935
+ label = formGroup.childNodes[0];
936
+ expect(label.tagName).toEqual('LABEL');
937
+ expect(label.classList).toContain('govuk-label');
938
+ expect(label.textContent).toEqual("".concat(TEXT_COMPONENT.label, " (optional)"));
939
+ expect(label.getAttribute('for')).toEqual("".concat(ID, "[0].").concat(TEXT_ID));
940
+ hint = formGroup.childNodes[1];
941
+ expect(hint.tagName).toEqual('DIV');
942
+ expect(hint.classList).toContain('govuk-hint');
943
+ expect(hint.textContent).toEqual(TEXT_COMPONENT.hint);
944
+ input = formGroup.childNodes[2];
945
+ expect(input.tagName).toEqual('INPUT');
946
+ expect(input.classList).toContain('govuk-input');
947
+ expect(input.id).toEqual("".concat(ID, "[0].").concat(TEXT_ID));
948
+ expect(input.value).toEqual('');
949
+
950
+ // Check to see if the item's text input is not in focus
951
+ expect(document.activeElement === item.childNodes[1].childNodes[0].querySelector("input")).toEqual(false);
952
+
953
+ // Get hold of that "Add another" button and click it.
954
+ addButton = c.childNodes[1].childNodes[0];
955
+ _react.fireEvent.click(addButton, {});
956
+
957
+ // Check if the second item has been added and it's input is in focus
958
+ secondItem = c.childNodes[1];
959
+ expect(c.childNodes.length).toEqual(3);
960
+ expect(document.activeElement === secondItem.childNodes[1].childNodes[0].querySelector("input")).toEqual(true);
961
+ case 39:
962
+ case "end":
963
+ return _context18.stop();
964
+ }
965
+ }, _callee18);
966
+ })));
808
967
  });
@@ -9,7 +9,6 @@ var _getNextPageId = _interopRequireDefault(require("./getNextPageId"));
9
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
10
  var getSubmissionStatus = function getSubmissionStatus(formType, pages, currentPageId, action, formData, currentTask, isCompleted, sections) {
11
11
  if (formType === _models.FormTypes.TASK || formType === _models.FormTypes.FORM_WITH_TASK) {
12
- var _currentTask$pages;
13
12
  var formStatus = formData.formStatus || {};
14
13
  formStatus.tasks = formStatus.tasks || {};
15
14
  formStatus.tasks[currentTask.name] = formStatus.tasks[currentTask.name] || {};
@@ -43,7 +42,7 @@ var getSubmissionStatus = function getSubmissionStatus(formType, pages, currentP
43
42
  complete: false,
44
43
  currentPage: (0, _getNextPageId.default)(formType, pages, currentPageId, action, formData)
45
44
  };
46
- } else if ((_currentTask$pages = currentTask.pages) !== null && _currentTask$pages !== void 0 && _currentTask$pages.includes(currentPageId)) {
45
+ } else {
47
46
  formStatus.tasks[currentTask.name] = {
48
47
  complete: !!(action !== null && action !== void 0 && action.complete),
49
48
  currentPage: currentPageId
@@ -275,26 +275,6 @@ describe('components', function () {
275
275
  })
276
276
  });
277
277
  });
278
- it('should not update the current task state if the current page does not belong in the task', function () {
279
- var CUSTOM_FORM_TYPE = _models.FormTypes.FORM_WITH_TASK;
280
- var ACTION = _models.PageAction.DEFAULTS.saveAndContinue;
281
- var CURRENT_TASK = {
282
- name: 'test-task',
283
- pages: ['page-a']
284
- };
285
- var CURRENT_PAGE_ID = 'page-b';
286
- var CUSTOM_FORM_DATA = {
287
- formStatus: {
288
- tasks: {
289
- 'test-task': {
290
- complete: false,
291
- currentPage: 'page-a'
292
- }
293
- }
294
- }
295
- };
296
- expect((0, _getSubmissionStatus.default)(CUSTOM_FORM_TYPE, PAGES, CURRENT_PAGE_ID, ACTION, CUSTOM_FORM_DATA, CURRENT_TASK, true, [])).toMatchObject(CUSTOM_FORM_DATA.formStatus);
297
- });
298
278
  });
299
279
  });
300
280
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ukhomeoffice/cop-react-form-renderer",
3
- "version": "5.18.1",
3
+ "version": "5.19.1",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "clean": "rimraf dist",