@ministryofjustice/frontend 3.3.1 → 3.5.0

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 (83) hide show
  1. package/README.md +4 -10
  2. package/govuk-prototype-kit.config.json +5 -16
  3. package/moj/all.jquery.min.js +15 -4
  4. package/moj/all.js +2856 -2280
  5. package/moj/all.scss +2 -0
  6. package/moj/components/_all.scss +1 -0
  7. package/moj/components/action-bar/_action-bar.scss +4 -6
  8. package/moj/components/add-another/_add-another.scss +9 -7
  9. package/moj/components/add-another/add-another.js +128 -76
  10. package/moj/components/alert/README.md +0 -0
  11. package/moj/components/alert/_alert.scss +142 -0
  12. package/moj/components/alert/alert.js +482 -0
  13. package/moj/components/alert/alert.spec.helper.js +92 -0
  14. package/moj/components/alert/macro.njk +3 -0
  15. package/moj/components/alert/template.njk +83 -0
  16. package/moj/components/badge/_badge.scss +3 -4
  17. package/moj/components/banner/_banner.scss +5 -10
  18. package/moj/components/button-menu/_button-menu.scss +10 -9
  19. package/moj/components/button-menu/button-menu.js +348 -318
  20. package/moj/components/cookie-banner/_cookie-banner.scss +6 -5
  21. package/moj/components/currency-input/_currency-input.scss +4 -4
  22. package/moj/components/date-picker/README.md +14 -17
  23. package/moj/components/date-picker/_date-picker.scss +122 -106
  24. package/moj/components/date-picker/date-picker.js +927 -900
  25. package/moj/components/filter/README.md +1 -1
  26. package/moj/components/filter/_filter.scss +53 -75
  27. package/moj/components/filter-toggle-button/filter-toggle-button.js +122 -87
  28. package/moj/components/form-validator/form-validator.js +399 -156
  29. package/moj/components/header/_header.scss +17 -19
  30. package/moj/components/identity-bar/_identity-bar.scss +5 -5
  31. package/moj/components/interruption-card/_interruption-card.scss +2 -2
  32. package/moj/components/messages/_messages.scss +12 -19
  33. package/moj/components/multi-file-upload/README.md +1 -1
  34. package/moj/components/multi-file-upload/_multi-file-upload.scss +34 -30
  35. package/moj/components/multi-file-upload/multi-file-upload.js +454 -183
  36. package/moj/components/multi-select/_multi-select.scss +4 -3
  37. package/moj/components/multi-select/multi-select.js +106 -70
  38. package/moj/components/notification-badge/_notification-badge.scss +12 -12
  39. package/moj/components/organisation-switcher/_organisation-switcher.scss +1 -1
  40. package/moj/components/page-header-actions/_page-header-actions.scss +3 -2
  41. package/moj/components/pagination/_pagination.scss +26 -31
  42. package/moj/components/password-reveal/_password-reveal.scss +1 -2
  43. package/moj/components/password-reveal/password-reveal.js +63 -31
  44. package/moj/components/primary-navigation/_primary-navigation.scss +26 -29
  45. package/moj/components/progress-bar/_progress-bar.scss +21 -26
  46. package/moj/components/rich-text-editor/_rich-text-editor.scss +17 -16
  47. package/moj/components/rich-text-editor/rich-text-editor.js +186 -139
  48. package/moj/components/search/_search.scss +6 -4
  49. package/moj/components/search-toggle/search-toggle.js +83 -53
  50. package/moj/components/search-toggle/search-toggle.scss +21 -15
  51. package/moj/components/side-navigation/_side-navigation.scss +12 -21
  52. package/moj/components/sortable-table/_sortable-table.scss +25 -23
  53. package/moj/components/sortable-table/sortable-table.js +162 -119
  54. package/moj/components/sub-navigation/_sub-navigation.scss +24 -28
  55. package/moj/components/tag/_tag.scss +8 -9
  56. package/moj/components/task-list/_task-list.scss +8 -7
  57. package/moj/components/ticket-panel/_ticket-panel.scss +14 -6
  58. package/moj/components/timeline/_timeline.scss +18 -20
  59. package/moj/filters/all.js +28 -30
  60. package/moj/filters/prototype-kit-13-filters.js +2 -1
  61. package/moj/helpers/_all.scss +1 -0
  62. package/moj/helpers/_hidden.scss +1 -1
  63. package/moj/helpers/_links.scss +20 -0
  64. package/moj/helpers.js +218 -51
  65. package/moj/init.js +2 -2
  66. package/moj/moj-frontend.min.css +2 -2
  67. package/moj/moj-frontend.min.js +15 -4
  68. package/moj/objects/_filter-layout.scss +11 -10
  69. package/moj/objects/_scrollable-pane.scss +11 -14
  70. package/moj/settings/_colours.scss +5 -0
  71. package/moj/settings/_measurements.scss +0 -2
  72. package/moj/utilities/_hidden.scss +3 -3
  73. package/moj/utilities/_width-container.scss +1 -1
  74. package/moj/version.js +28 -1
  75. package/package.json +1 -1
  76. package/moj/all.spec.js +0 -22
  77. package/moj/components/button-menu/button-menu.spec.js +0 -361
  78. package/moj/components/date-picker/date-picker.spec.js +0 -1130
  79. package/moj/components/filter-toggle-button/filter-toggle-button.spec.js +0 -304
  80. package/moj/components/multi-select/multi-select.spec.js +0 -135
  81. package/moj/components/password-reveal/password-reveal.spec.js +0 -55
  82. package/moj/components/search-toggle/search-toggle.spec.js +0 -134
  83. package/moj/namespace.js +0 -1
@@ -1,304 +0,0 @@
1
- const {
2
- queryByRole,
3
- } = require("@testing-library/dom");
4
- const { userEvent } = require("@testing-library/user-event");
5
- const { configureAxe } = require("jest-axe");
6
- const merge = require("lodash.merge");
7
- const { setMedia } = require("mock-match-media");
8
-
9
- require("./filter-toggle-button.js");
10
-
11
- const user = userEvent.setup();
12
- const axe = configureAxe({
13
- rules: {
14
- // disable landmark rules when testing isolated components.
15
- region: { enabled: false },
16
- },
17
- });
18
-
19
- const createTemplate = () => {
20
- html = `
21
- <div class="moj-filter">
22
- <div class="moj-filter__header">
23
- <div class="moj-filter__header-title">
24
- <h2 class="govuk-heading-m">Filter</h2>
25
- </div>
26
- <div class="moj-filter__header-action"></div>
27
- </div>
28
- </div>
29
- <div class="moj-action-bar">
30
- <div class="moj-action-bar__filter"></div>
31
- </div>`;
32
- document.body.insertAdjacentHTML("afterbegin", html);
33
-
34
- const buttonContainer = document.querySelector(".moj-action-bar__filter");
35
- const closeButtonContainer = document.querySelector(
36
- ".moj-filter__header-action",
37
- );
38
- const filterContainer = document.querySelector(".moj-filter");
39
-
40
- return {
41
- buttonContainer: buttonContainer,
42
- closeButtonContainer: closeButtonContainer,
43
- filterContainer: filterContainer,
44
- };
45
- };
46
-
47
- let baseConfig;
48
-
49
- beforeEach(() => {
50
- baseConfig = {
51
- bigModeMediaQuery: "(min-width: 600px)",
52
- startHidden: true,
53
- toggleButton: {
54
- container: document.querySelector(".moj-action-bar__filter"),
55
- showText: "Show filter",
56
- hideText: "Hide filter",
57
- classes: "govuk-button--secondary",
58
- },
59
- closeButton: {
60
- container: document.querySelector(".moj-filter__header-action"),
61
- text: "Close",
62
- },
63
- filter: {
64
- container: document.querySelector(".moj-filter"),
65
- },
66
- };
67
- });
68
-
69
- describe("Filter toggle in big mode", () => {
70
- let defaultConfig, buttonContainer, closeButtonContainer, filterContainer;
71
-
72
- beforeEach(() => {
73
- setMedia({
74
- width: "800px",
75
- });
76
-
77
- ({ buttonContainer, closeButtonContainer, filterContainer } = createTemplate());
78
-
79
- defaultConfig = merge(baseConfig, {
80
- toggleButton: {
81
- container: document.querySelector(".moj-action-bar__filter"),
82
- },
83
- closeButton: {
84
- container: document.querySelector(".moj-filter__header-action"),
85
- },
86
- filter: { container: document.querySelector(".moj-filter") },
87
- });
88
- });
89
-
90
- afterEach(() => {
91
- document.body.innerHTML = "";
92
- });
93
-
94
- test("creates toggle button", () => {
95
- new MOJFrontend.FilterToggleButton(defaultConfig);
96
- const toggleButton = queryByRole(buttonContainer, "button");
97
-
98
- expect(toggleButton).not.toBeNull();
99
- expect(toggleButton.innerHTML).toBe("Show filter");
100
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
101
- expect(toggleButton).toHaveClass("govuk-button--secondary");
102
-
103
- expect(filterContainer).toHaveAttribute("tabindex", "-1");
104
- expect(filterContainer).toHaveClass("moj-js-hidden");
105
- });
106
-
107
- test("toggle button reveals filters", async () => {
108
- new MOJFrontend.FilterToggleButton(defaultConfig);
109
- const toggleButton = queryByRole(buttonContainer, "button");
110
-
111
- expect(filterContainer).toHaveAttribute("tabindex", "-1");
112
- expect(filterContainer).toHaveClass("moj-js-hidden");
113
-
114
- await user.click(toggleButton);
115
-
116
- expect(toggleButton).toHaveAttribute("aria-expanded", "true");
117
- expect(toggleButton.innerHTML).toBe("Hide filter");
118
- expect(filterContainer).not.toHaveClass("moj-js-hidden");
119
- expect(filterContainer).toHaveFocus();
120
-
121
- await user.click(toggleButton);
122
-
123
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
124
- expect(toggleButton.innerHTML).toBe("Show filter");
125
- expect(filterContainer).toHaveClass("moj-js-hidden");
126
-
127
- expect(toggleButton).toHaveFocus();
128
- });
129
-
130
- test("start visible", () => {
131
- const config = merge(defaultConfig, { startHidden: false });
132
- new MOJFrontend.FilterToggleButton(config);
133
- const toggleButton = queryByRole(buttonContainer, "button");
134
-
135
- expect(toggleButton.innerHTML).toBe("Hide filter");
136
- expect(filterContainer).not.toHaveClass("moj-js-hidden");
137
- });
138
-
139
- test("custom button text", async () => {
140
- const config = merge(defaultConfig, {
141
- toggleButton: { showText: "Custom label", hideText: "Hide me" },
142
- });
143
- new MOJFrontend.FilterToggleButton(config);
144
- const toggleButton = queryByRole(buttonContainer, "button");
145
-
146
- expect(toggleButton.innerHTML).toBe("Custom label");
147
- await user.click(toggleButton);
148
- expect(toggleButton.innerHTML).toBe("Hide me");
149
- });
150
-
151
- test("custom toggle button classes", () => {
152
- const config = merge(defaultConfig, {
153
- toggleButton: { classes: "classname-1 classname-2" },
154
- });
155
- new MOJFrontend.FilterToggleButton(config);
156
- const toggleButton = queryByRole(buttonContainer, "button");
157
-
158
- expect(toggleButton).toHaveClass("classname-1 classname-2");
159
- });
160
-
161
- describe("accessibility", () => {
162
- test("component has no wcag violations", async () => {
163
- new MOJFrontend.FilterToggleButton(defaultConfig);
164
- const toggleButton = queryByRole(buttonContainer, "button");
165
- expect(await axe(document.body)).toHaveNoViolations();
166
- await user.click(toggleButton);
167
- expect(await axe(document.body)).toHaveNoViolations();
168
- });
169
- });
170
- });
171
-
172
- describe("Filter toggle in small mode", () => {
173
- let defaultConfig, buttonContainer, closeButtonContainer, filterContainer;
174
-
175
- beforeEach(() => {
176
- setMedia({
177
- width: "500px",
178
- });
179
-
180
- ({ buttonContainer, closeButtonContainer, filterContainer } = createTemplate()),
181
-
182
- defaultConfig = merge(baseConfig, {
183
- toggleButton: {
184
- container: document.querySelector(".moj-action-bar__filter"),
185
- },
186
- closeButton: {
187
- container: document.querySelector(".moj-filter__header-action"),
188
- },
189
- filter: { container: document.querySelector(".moj-filter") },
190
- });
191
- });
192
-
193
- afterEach(() => {
194
- document.body.innerHTML = "";
195
- });
196
-
197
- test("creates toggle button", () => {
198
- new MOJFrontend.FilterToggleButton(defaultConfig);
199
- const toggleButton = queryByRole(buttonContainer, "button");
200
-
201
- expect(toggleButton).not.toBeNull();
202
- expect(toggleButton.innerHTML).toBe("Show filter");
203
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
204
- expect(toggleButton).toHaveClass("govuk-button--secondary");
205
-
206
- expect(filterContainer).toHaveAttribute("tabindex", "-1");
207
- expect(filterContainer).toHaveClass("moj-js-hidden");
208
- });
209
-
210
- test("toggle button reveals filters", async () => {
211
- new MOJFrontend.FilterToggleButton(defaultConfig);
212
- const toggleButton = queryByRole(buttonContainer, "button");
213
-
214
- expect(filterContainer).toHaveAttribute("tabindex", "-1");
215
- expect(filterContainer).toHaveClass("moj-js-hidden");
216
-
217
- await user.click(toggleButton);
218
-
219
- expect(toggleButton).toHaveAttribute("aria-expanded", "true");
220
- expect(toggleButton.innerHTML).toBe("Hide filter");
221
- expect(filterContainer).not.toHaveClass("moj-js-hidden");
222
- expect(filterContainer).toHaveFocus();
223
-
224
- await user.click(toggleButton);
225
-
226
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
227
- expect(toggleButton.innerHTML).toBe("Show filter");
228
- expect(filterContainer).toHaveClass("moj-js-hidden");
229
-
230
- expect(toggleButton).toHaveFocus();
231
- });
232
-
233
- test("start visible is ignored", () => {
234
- const config = merge(defaultConfig, { startHidden: false });
235
- new MOJFrontend.FilterToggleButton(config);
236
- const toggleButton = queryByRole(buttonContainer, "button");
237
-
238
- expect(toggleButton.innerHTML).toBe("Show filter");
239
- expect(filterContainer).toHaveClass("moj-js-hidden");
240
- });
241
-
242
- test("adds a close button", async () => {
243
- const config = merge(defaultConfig, { startHidden: false });
244
- new MOJFrontend.FilterToggleButton(config);
245
- const toggleButton = queryByRole(buttonContainer, "button");
246
-
247
- await user.click(toggleButton);
248
-
249
- const closeButton = queryByRole(closeButtonContainer, "button");
250
-
251
- expect(closeButton).not.toBeNull();
252
- expect(closeButton.innerHTML).toBe("Close");
253
- });
254
-
255
- test("hides on resize from big to small", async () => {
256
- setMedia({
257
- width: "800px",
258
- });
259
-
260
- const config = merge(defaultConfig, { startHidden: false });
261
- new MOJFrontend.FilterToggleButton(config);
262
- const toggleButton = queryByRole(buttonContainer, "button");
263
-
264
- expect(toggleButton.innerHTML).toBe("Hide filter");
265
- expect(filterContainer).not.toHaveClass("moj-js-hidden");
266
-
267
- setMedia({
268
- width: "500px",
269
- });
270
-
271
- expect(toggleButton.innerHTML).toBe("Show filter");
272
- expect(filterContainer).toHaveClass("moj-js-hidden");
273
- });
274
-
275
- test("shows on resize from small to big", async () => {
276
- setMedia({
277
- width: "500px",
278
- });
279
-
280
- const config = merge(defaultConfig);
281
- new MOJFrontend.FilterToggleButton(config);
282
- const toggleButton = queryByRole(buttonContainer, "button");
283
-
284
- expect(toggleButton.innerHTML).toBe("Show filter");
285
- expect(filterContainer).toHaveClass("moj-js-hidden");
286
-
287
- setMedia({
288
- width: "800px",
289
- });
290
-
291
- expect(toggleButton.innerHTML).toBe("Hide filter");
292
- expect(filterContainer).not.toHaveClass("moj-js-hidden");
293
- });
294
-
295
- describe("accessibility", () => {
296
- test("component has no wcag violations", async () => {
297
- new MOJFrontend.FilterToggleButton(defaultConfig);
298
- const toggleButton = queryByRole(buttonContainer, "button");
299
- expect(await axe(document.body)).toHaveNoViolations();
300
- await user.click(toggleButton);
301
- expect(await axe(document.body)).toHaveNoViolations();
302
- });
303
- });
304
- });
@@ -1,135 +0,0 @@
1
- const {
2
- queryByRole,
3
- queryAllByRole,
4
- } = require("@testing-library/dom");
5
- const { userEvent } = require("@testing-library/user-event");
6
- const { configureAxe } = require("jest-axe");
7
-
8
- require("./multi-select.js");
9
-
10
- const user = userEvent.setup();
11
- const axe = configureAxe({
12
- rules: {
13
- // disable landmark rules when testing isolated components.
14
- region: { enabled: false },
15
- },
16
- });
17
-
18
- const createComponent = (id = "multi-select", idprefix = false) => {
19
- html = `
20
- <table id="${id}" class="govuk-table" data-module="moj-multi-select" data-multi-select-checkbox="#${id}-select-all" ${idprefix ? 'data-multi-select-idprefix="' + idprefix + '-"' : ""}>
21
- <thead class="govuk-table__head">
22
- <tr class="govuk-table__row">
23
- <th class="govuk-table__header" scope="col" id="${id}-select-all"></th>
24
- <th class="govuk-table__header" scope="col">Name</th>
25
- </tr>
26
- </thead>
27
- <tbody class="govuk-table__body">
28
- <tr class="govuk-table__row govuk-table__row--selected">
29
- <td class="govuk-table__cell">
30
- <div class="govuk-checkboxes__item govuk-checkboxes--small moj-multi-select__checkbox">
31
- <input type="checkbox" class="govuk-checkboxes__input" id="mountain-aconcagua">
32
- <label class="govuk-label govuk-checkboxes__label" for="mountain-aconcagua">
33
- <span class="govuk-visually-hidden">Select Aconcagua</span>
34
- </label>
35
- </div>
36
- </td>
37
- <td class="govuk-table__cell">Aconcagua</td>
38
- </tr>
39
- <tr class="govuk-table__row">
40
- <td class="govuk-table__cell">
41
- <div class="govuk-checkboxes__item govuk-checkboxes--small moj-multi-select__checkbox">
42
- <input type="checkbox" class="govuk-checkboxes__input" id="mountain-denali" value="denali">
43
- <label class="govuk-label govuk-checkboxes__label" for="mountain-denali">
44
- <span class="govuk-visually-hidden">Select Denali</span>
45
- </label>
46
- </div>
47
- </td>
48
- </td>
49
- <td class="govuk-table__cell">Denali</td>
50
- </tr>
51
- </tbody>
52
- </table>
53
- `;
54
- document.body.insertAdjacentHTML("afterbegin", html);
55
- const component = document.querySelector(`#${id}`);
56
- return component;
57
- };
58
-
59
- describe("multi select", () => {
60
- let component, container;
61
-
62
- beforeEach(() => {
63
- component = createComponent();
64
- container = component.querySelector("#multi-select-select-all");
65
- checkboxes = component.querySelectorAll("tbody input[type=checkbox]");
66
-
67
- new MOJFrontend.MultiSelect({
68
- container: container,
69
- checkboxes: checkboxes,
70
- });
71
- });
72
-
73
- afterEach(() => {
74
- document.body.innerHTML = "";
75
- component, container, (checkboxes = undefined);
76
- });
77
-
78
- test("initialises component", () => {
79
- const selectToggle = queryByRole(container, "checkbox");
80
-
81
- expect(selectToggle).not.toBeNull();
82
- expect(selectToggle).toHaveAccessibleName("Select all");
83
- });
84
-
85
- test("toggles all checkboxes", async () => {
86
- const selectToggle = queryByRole(container, "checkbox");
87
- const tbody = component.querySelector("tbody");
88
- let checkboxes = queryAllByRole(tbody, "checkbox");
89
-
90
- expect(checkboxes.length).toBe(2);
91
- checkboxes.forEach((checkbox) => {
92
- expect(checkbox).not.toBeChecked();
93
- });
94
-
95
- await user.click(selectToggle);
96
- expect(selectToggle).toBeChecked();
97
-
98
- checkboxes.forEach((checkbox) => {
99
- expect(checkbox).toBeChecked();
100
- });
101
-
102
- await user.click(selectToggle);
103
- expect(selectToggle).not.toBeChecked();
104
-
105
- checkboxes.forEach((checkbox) => {
106
- expect(checkbox).not.toBeChecked();
107
- });
108
- });
109
-
110
- test("deselcting single checkbox unchecks all checkbox", async () => {
111
- const selectToggle = queryByRole(container, "checkbox");
112
- const tbody = component.querySelector("tbody");
113
- const checkboxes = queryAllByRole(tbody, "checkbox");
114
-
115
- expect(checkboxes.length).toBe(2);
116
- checkboxes.forEach((checkbox) => {
117
- expect(checkbox).not.toBeChecked();
118
- });
119
-
120
- await user.click(selectToggle);
121
- expect(selectToggle).toBeChecked();
122
-
123
- checkboxes.forEach((checkbox) => {
124
- expect(checkbox).toBeChecked();
125
- });
126
-
127
- await user.click(checkboxes[0]);
128
- expect(checkboxes[0]).not.toBeChecked();
129
- expect(selectToggle).not.toBeChecked();
130
-
131
- await user.click(checkboxes[0]);
132
- expect(checkboxes[0]).toBeChecked();
133
- expect(selectToggle).toBeChecked();
134
- });
135
- });
@@ -1,55 +0,0 @@
1
- const { getByDisplayValue, getByText } = require("@testing-library/dom");
2
- const { userEvent } = require("@testing-library/user-event");
3
- const { configureAxe } = require("jest-axe");
4
-
5
- require("./password-reveal.js");
6
-
7
- const user = userEvent.setup();
8
- const axe = configureAxe({
9
- rules: {
10
- // disable landmark rules when testing isolated components.
11
- region: { enabled: false },
12
- },
13
- });
14
-
15
- describe("Password reveal", () => {
16
- let container;
17
-
18
- beforeEach(() => {
19
- const input = document.createElement("input");
20
- input.type = "password";
21
- input.value = "password";
22
-
23
- new MOJFrontend.PasswordReveal(input);
24
-
25
- container = input.parentNode;
26
- });
27
-
28
- test("initialises container", () => {
29
- expect(container).toHaveClass("moj-password-reveal");
30
- expect(container).toContainElement(getByText(container, "Show"));
31
- });
32
-
33
- test("toggle reveal", async () => {
34
- const input = getByDisplayValue(container, "password");
35
- const button = getByText(container, "Show");
36
-
37
- await user.click(button);
38
-
39
- expect(input).toHaveAttribute("type", "text");
40
- expect(button).toHaveTextContent("Hide");
41
-
42
- await user.click(button);
43
-
44
- expect(input).toHaveAttribute("type", "password");
45
- expect(button).toHaveTextContent("Show");
46
- });
47
-
48
- test("accessibility", async () => {
49
- const button = getByText(container, "Show");
50
-
51
- expect(await axe(document.body)).toHaveNoViolations();
52
- await user.click(button);
53
- expect(await axe(document.body)).toHaveNoViolations();
54
- });
55
- });
@@ -1,134 +0,0 @@
1
- const { queryByRole } = require("@testing-library/dom");
2
- const { userEvent } = require("@testing-library/user-event");
3
- const { configureAxe } = require("jest-axe");
4
- const $ = require("jquery");
5
-
6
- require("./search-toggle.js");
7
-
8
- const user = userEvent.setup();
9
- const axe = configureAxe({
10
- rules: {
11
- // disable landmark rules when testing isolated components.
12
- region: { enabled: false },
13
- },
14
- });
15
-
16
- const createComponent = () => {
17
- html = `
18
- <div class="moj-search-toggle" data-module="moj-search-toggle" data-moj-search-toggle-text="Find case">
19
- <div class="moj-search-toggle__toggle"></div>
20
- <div class="moj-search-toggle__search">
21
-
22
- <div class="moj-search moj-search--ondark moj-search--toggle moj-js-hidden">
23
-
24
- <form action="" method="get">
25
-
26
- <div class="govuk-form-group">
27
- <label class="govuk-label moj-search__label govuk-visually-hidden" for="search2">
28
- Search
29
- </label>
30
-
31
- <div id="search2-hint" class="govuk-hint moj-search__hint ">
32
- Enter case number, for example 123456
33
- </div>
34
-
35
- <input class="govuk-input moj-search__input " id="search2" name="search2" type="search" aria-describedby="search2-hint">
36
-
37
- </div>
38
-
39
- <button type="submit" class="govuk-button moj-search__button " data-module="govuk-button">
40
- Search
41
- </button>
42
-
43
- </form>
44
- </div>
45
-
46
- </div>
47
- </div>
48
- <a href="#">link</a>`;
49
- document.body.insertAdjacentHTML("afterbegin", html);
50
- const component = document.querySelector(".moj-search-toggle");
51
- return component;
52
- };
53
-
54
- describe("search toggle", () => {
55
- let component, buttonContainer, searchContainer;
56
-
57
- beforeEach(() => {
58
- component = createComponent();
59
- searchContainer = component.querySelector(".moj-search");
60
- buttonContainer = component.querySelector(".moj-search-toggle__toggle");
61
-
62
- new MOJFrontend.SearchToggle({
63
- toggleButton: {
64
- container: $(buttonContainer),
65
- text: component.getAttribute("data-moj-search-toggle-text"),
66
- },
67
- search: {
68
- container: $(searchContainer),
69
- },
70
- });
71
- });
72
-
73
- afterEach(() => {
74
- document.body.innerHTML = "";
75
- });
76
-
77
- test("initialises component", () => {
78
- const toggleButton = queryByRole(buttonContainer, "button");
79
-
80
- expect(toggleButton).not.toBeNull();
81
- expect(toggleButton).toHaveTextContent("Find case");
82
- expect(toggleButton).toHaveAttribute("aria-haspopup", "true");
83
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
84
-
85
- expect(searchContainer).toHaveClass("moj-js-hidden");
86
- });
87
-
88
- test("clicking button toggles search container", async () => {
89
- const toggleButton = queryByRole(buttonContainer, "button");
90
-
91
- await user.click(toggleButton);
92
-
93
- expect(toggleButton).toHaveAttribute("aria-expanded", "true");
94
- expect(searchContainer).not.toHaveClass("moj-js-hidden");
95
-
96
- const input = queryByRole(searchContainer, "searchbox");
97
- expect(input).toHaveFocus();
98
-
99
- await user.click(toggleButton);
100
-
101
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
102
- expect(searchContainer).toHaveClass("moj-js-hidden");
103
- expect(toggleButton).toHaveFocus();
104
- });
105
-
106
- test("clicking outside closes the search container", async () => {
107
- const toggleButton = queryByRole(buttonContainer, "button");
108
-
109
- await user.click(toggleButton);
110
-
111
- expect(toggleButton).toHaveAttribute("aria-expanded", "true");
112
- expect(searchContainer).not.toHaveClass("moj-js-hidden");
113
-
114
- await user.click(document.body);
115
-
116
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
117
- expect(searchContainer).toHaveClass("moj-js-hidden");
118
- });
119
-
120
- test("tabbing closes the search container", async () => {
121
- const toggleButton = queryByRole(buttonContainer, "button");
122
-
123
- await user.click(toggleButton);
124
-
125
- expect(toggleButton).toHaveAttribute("aria-expanded", "true");
126
- expect(searchContainer).not.toHaveClass("moj-js-hidden");
127
-
128
- await user.tab();
129
- await user.tab();
130
-
131
- expect(toggleButton).toHaveAttribute("aria-expanded", "false");
132
- expect(searchContainer).toHaveClass("moj-js-hidden");
133
- });
134
- });
package/moj/namespace.js DELETED
@@ -1 +0,0 @@
1
- var MOJFrontend = {};