@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,1130 +0,0 @@
1
- const {
2
- getAllByRole,
3
- getByText,
4
- getByRole,
5
- queryByRole,
6
- queryByText,
7
- screen,
8
- } = require("@testing-library/dom");
9
- const { userEvent } = require("@testing-library/user-event");
10
- const { configureAxe } = require("jest-axe");
11
- const dayjs = require("dayjs");
12
-
13
- require("./date-picker.js");
14
-
15
- const user = userEvent.setup();
16
- const axe = configureAxe({
17
- rules: {
18
- // disable landmark rules when testing isolated components.
19
- region: { enabled: false },
20
- },
21
- });
22
-
23
- const kebabize = (str) => {
24
- return str.replace(
25
- /[A-Z]+(?![a-z])|[A-Z]/g,
26
- ($, ofset) => (ofset ? "-" : "") + $.toLowerCase(),
27
- );
28
- };
29
-
30
- const configToDataAttributes = (config) => {
31
- let attributes = "";
32
- for (let [key, value] of Object.entries(config)) {
33
- attributes += `data-${kebabize(key)}="${value}" `;
34
- }
35
- return attributes;
36
- };
37
-
38
- const createComponent = (config = {}, html) => {
39
- const dataAttributes = configToDataAttributes(config);
40
- if (typeof html === "undefined") {
41
- html = `
42
- <div class="moj-datepicker" data-module="moj-date-picker" ${dataAttributes}>
43
- <div class="govuk-form-group">
44
- <label class="govuk-label" for="date">
45
- Date
46
- </label>
47
- <div id="date-hint" class="govuk-hint">
48
- For example, 17/5/2024.
49
- </div>
50
- <input class="govuk-input moj-js-datepicker-input " id="date" name="date" type="text" aria-describedby="date-hint" autocomplete="off">
51
- </div>
52
- </div>`;
53
- }
54
- document.body.insertAdjacentHTML("afterbegin", html);
55
-
56
- component = document.querySelector('[data-module="moj-date-picker"]');
57
- return component;
58
- };
59
-
60
- const randomIntBetween = (min, max) => {
61
- return Math.floor(Math.random() * (max - min + 1)) + min;
62
- };
63
-
64
- const padToTwoDigits = (number) => {
65
- return number.toString().padStart(2, "0");
66
- };
67
-
68
- const getFirstDayOfWeek = (dateObject, firstDayOfWeekIndex) => {
69
- const dayOfWeek = dateObject.getDay();
70
- const firstDayOfWeek = new Date(dateObject);
71
- const diff =
72
- dayOfWeek >= firstDayOfWeekIndex
73
- ? dayOfWeek - firstDayOfWeekIndex
74
- : 6 - dayOfWeek;
75
-
76
- firstDayOfWeek.setDate(dateObject.getDate() - diff);
77
- firstDayOfWeek.setHours(0, 0, 0, 0);
78
-
79
- return firstDayOfWeek;
80
- };
81
-
82
- const getLastDayOfWeek = (dateObject, lastDayOfWeekIndex) => {
83
- const dayOfWeek = dateObject.getDay();
84
- const lastDayOfWeek = new Date(dateObject);
85
- const diff =
86
- dayOfWeek <= lastDayOfWeekIndex
87
- ? lastDayOfWeekIndex - dayOfWeek
88
- : 7 - dayOfWeek;
89
-
90
- lastDayOfWeek.setDate(dateObject.getDate() - diff);
91
- lastDayOfWeek.setHours(0, 0, 0, 0);
92
-
93
- return lastDayOfWeek;
94
- };
95
-
96
- const getDateInCurrentMonth = (excluding = []) => {
97
- const today = dayjs().date();
98
- excluding.push(today);
99
- const lastDayOfMonth = dayjs().endOf("month").date();
100
- const days = range(1, lastDayOfMonth).filter((x) => !excluding.includes(x));
101
-
102
- return days[Math.floor(Math.random() * days.length)];
103
- };
104
-
105
- const getDateRangeInCurrentMonth = (startDay, endDay) => {
106
- let date = dayjs().date(startDay); // Convert the start date to a Day.js object
107
- const endDate = dayjs().date(endDay + 1);
108
- const dates = [];
109
-
110
- while (date.isBefore(endDate)) {
111
- dates.push(date);
112
- date = date.add(1, "day");
113
- }
114
-
115
- return dates;
116
- };
117
-
118
- const range = (start, end) => {
119
- return [...Array(end - start + 1).keys()].map((x) => x + start);
120
- };
121
-
122
- describe("Date picker with defaults", () => {
123
- let component;
124
- let calendarButton;
125
- let dialog;
126
-
127
- beforeEach(() => {
128
- component = createComponent();
129
- new MOJFrontend.DatePicker(component, {}).init();
130
-
131
- calendarButton = queryByText(component, "Choose date")?.closest("button");
132
- dialog = queryByRole(component, "dialog", { hidden: true });
133
- });
134
-
135
- afterEach(() => {
136
- document.body.innerHTML = "";
137
- });
138
-
139
- test("initialises calendar calendarButton and dialog", () => {
140
- expect(calendarButton).not.toBeNull();
141
- expect(dialog).not.toBeNull();
142
- expect(component).toContainElement(calendarButton);
143
- expect(component).toContainElement(dialog);
144
- expect(dialog).not.toBeVisible();
145
- });
146
-
147
- test("calendar button toggles dialog", async () => {
148
- await user.click(calendarButton);
149
- expect(dialog).toBeVisible();
150
-
151
- await user.click(calendarButton);
152
- expect(dialog).not.toBeVisible();
153
- });
154
-
155
- test("dialog has required buttons", async () => {
156
- await user.click(calendarButton);
157
- let selectButton = queryByText(dialog, "Select");
158
- let closeButton = queryByText(dialog, "Close");
159
- let prevMonthButton = queryByText(dialog, "Previous month");
160
- let prevYearButton = queryByText(dialog, "Previous year");
161
- let nextMonthButton = queryByText(dialog, "Next month");
162
- let nextYearButton = queryByText(dialog, "Next year");
163
-
164
- expect(selectButton).not.toBeNull();
165
- expect(closeButton).not.toBeNull();
166
- expect(prevMonthButton).not.toBeNull();
167
- expect(prevYearButton).not.toBeNull();
168
- expect(nextMonthButton).not.toBeNull();
169
- expect(nextYearButton).not.toBeNull();
170
- });
171
-
172
- test("calendar opens with current month and year", async () => {
173
- await user.click(calendarButton);
174
- const today = new Date();
175
- const currentMonthName = today.toLocaleString("default", { month: "long" });
176
- const currentYear = today.getFullYear();
177
- const dialogTitle = `${currentMonthName} ${currentYear}`;
178
-
179
- expect(dialog).toContainElement(screen.getByText(dialogTitle));
180
- });
181
-
182
- test("today is selected", async () => {
183
- await user.click(calendarButton);
184
- const today = new Date();
185
- const todayButton = getByRole(dialog, "button", { current: "date" });
186
-
187
- expect(todayButton).toHaveFocus();
188
- expect(todayButton).toHaveClass(
189
- "moj-datepicker__button--selected",
190
- "moj-datepicker__button--current",
191
- "moj-datepicker__button--today",
192
- );
193
- expect(todayButton.textContent).toContain(`${today.getDate()}`);
194
- });
195
-
196
- test("can navigate back in time", async () => {
197
- const today = dayjs();
198
- const previousMonth = dayjs().subtract(1, "month");
199
- const previousYear = previousMonth.subtract(1, "year");
200
-
201
- const currentTitle = `${today.format("MMMM YYYY")}`;
202
- const previousMonthTitle = `${previousMonth.format("MMMM YYYY")}`;
203
- const previousYearTitle = `${previousYear.format("MMMM YYYY")}`;
204
-
205
- await user.click(calendarButton);
206
- let prevMonthButton = getByText(dialog, "Previous month");
207
- let prevYearButton = getByText(dialog, "Previous year");
208
-
209
- expect(dialog).toContainElement(screen.getByText(currentTitle));
210
- await user.click(prevMonthButton);
211
- expect(dialog).toContainElement(screen.getByText(previousMonthTitle));
212
- await user.click(prevYearButton);
213
- expect(dialog).toContainElement(screen.getByText(previousYearTitle));
214
- });
215
-
216
- test("can navigate forward in time", async () => {
217
- const today = dayjs();
218
- const nextMonth = dayjs().add(1, "month");
219
- const nextYear = nextMonth.add(1, "year");
220
-
221
- const currentTitle = `${today.format("MMMM YYYY")}`;
222
- const nextMonthTitle = `${nextMonth.format("MMMM YYYY")}`;
223
- const nextYearTitle = `${nextYear.format("MMMM YYYY")}`;
224
-
225
- await user.click(calendarButton);
226
- let nextMonthButton = getByText(dialog, "Next month");
227
- let nextYearButton = getByText(dialog, "Next year");
228
-
229
- expect(dialog).toContainElement(screen.getByText(currentTitle));
230
- await user.click(nextMonthButton);
231
- expect(dialog).toContainElement(screen.getByText(nextMonthTitle));
232
- await user.click(nextYearButton);
233
- expect(dialog).toContainElement(screen.getByText(nextYearTitle));
234
- });
235
-
236
- test("close button closes the calendar popup", async () => {
237
- await user.click(calendarButton);
238
- let closeButton = queryByText(dialog, "Close");
239
-
240
- expect(dialog).toBeVisible();
241
- await user.click(closeButton);
242
- expect(dialog).not.toBeVisible();
243
- expect(calendarButton).toHaveFocus();
244
- });
245
-
246
- test("clicking outside closes the calendar popup", async () => {
247
- let hint = screen.getByText("For example, 17/5/2024.");
248
-
249
- await user.click(calendarButton);
250
- expect(dialog).toBeVisible();
251
- await user.click(hint);
252
- expect(dialog).not.toBeVisible();
253
- });
254
-
255
- describe("date picker with initial value", () => {
256
- let inputString;
257
- let dateString;
258
- let input;
259
- let selectedDate;
260
- let newDate;
261
-
262
- beforeEach(async () => {
263
- inputString = "19/05/2024";
264
- dateString = "2024-05-19";
265
- input = screen.getByLabelText("Date");
266
- selectedDate = new Date(dateString);
267
-
268
- while (newDate != selectedDate.getDate()) {
269
- newDate = randomIntBetween(7, 21); //outside this we could have duplicate hidden buttons from prev/next month
270
- }
271
-
272
- await user.type(input, inputString);
273
- await user.click(calendarButton);
274
- });
275
-
276
- test("opens to date in input field", async () => {
277
- const selectedDateButton = getByRole(dialog, "button", {
278
- current: "date",
279
- });
280
-
281
- expect(selectedDateButton).toHaveFocus();
282
- expect(selectedDateButton).toHaveClass(
283
- "moj-datepicker__button--selected",
284
- "moj-datepicker__button--current",
285
- );
286
- expect(selectedDateButton).not.toHaveClass(
287
- "moj-datepicker__button--today",
288
- );
289
- expect(selectedDateButton.textContent).toContain(
290
- `${selectedDate.getDate()}`,
291
- );
292
- });
293
-
294
- test("clicking a date selects it, closes dialog, and populates input", async () => {
295
- const newDateButton = queryByText(dialog, newDate)?.closest("button");
296
-
297
- await user.click(newDateButton);
298
-
299
- expect(dialog).not.toBeVisible();
300
- expect(input).toHaveValue(`${newDate}/5/2024`);
301
- expect(calendarButton).toHaveFocus();
302
- });
303
-
304
- test("clicking select, closes dialog and populates input", async () => {
305
- const selectButton = getByText(dialog, "Select");
306
-
307
- await user.keyboard("ArrowRight");
308
- await user.click(selectButton);
309
-
310
- expect(dialog).not.toBeVisible();
311
- expect(input).toHaveValue(`${newDate}/5/2024`);
312
- expect(calendarButton).toHaveFocus();
313
- });
314
- });
315
-
316
- describe("keyboard interaction", () => {
317
- let inputString;
318
- let dateString;
319
- let input;
320
- let initialDate;
321
-
322
- beforeEach(async () => {
323
- inputString = "19/5/2024";
324
- dateString = "2024-05-19";
325
- input = screen.getByLabelText("Date");
326
- initialDate = new Date(dateString);
327
-
328
- await user.type(input, inputString);
329
- });
330
-
331
- test("esc closes calendar dialog", async () => {
332
- await user.tab();
333
- expect(calendarButton).toHaveFocus();
334
- await user.keyboard("{enter}");
335
- expect(dialog).toBeVisible();
336
- await user.keyboard("{escape}");
337
- expect(dialog).not.toBeVisible();
338
- expect(calendarButton).toHaveFocus();
339
- });
340
-
341
- test("calendar dialog is a focus trap", async () => {
342
- await user.click(calendarButton);
343
- const selectedDateButton = getByRole(dialog, "button", {
344
- current: "date",
345
- });
346
- const selectButton = queryByText(dialog, "Select");
347
- const closeButton = queryByText(dialog, "Close");
348
- const prevMonthButton = getByRole(dialog, "button", {
349
- name: "Previous month",
350
- });
351
- const prevYearButton = getByRole(dialog, "button", {
352
- name: "Previous year",
353
- });
354
- const nextMonthButton = getByRole(dialog, "button", {
355
- name: "Next month",
356
- });
357
- const nextYearButton = getByRole(dialog, "button", { name: "Next year" });
358
-
359
- expect(selectedDateButton).toHaveFocus();
360
- await user.tab();
361
- expect(selectButton).toHaveFocus();
362
- await user.tab();
363
- expect(closeButton).toHaveFocus();
364
- await user.tab();
365
- expect(prevYearButton).toHaveFocus();
366
- await user.tab();
367
- expect(prevMonthButton).toHaveFocus();
368
- await user.tab();
369
- expect(nextMonthButton).toHaveFocus();
370
- await user.tab();
371
- expect(nextYearButton).toHaveFocus();
372
- await user.tab();
373
- expect(selectedDateButton).toHaveFocus();
374
- });
375
-
376
- test("rigth arrow navigates to next day", async () => {
377
- await user.click(calendarButton);
378
- const initialDateButton = getByRole(dialog, "button", {
379
- current: "date",
380
- });
381
- let selectedDateButton;
382
- let labelRegex;
383
-
384
- expect(initialDateButton).toHaveFocus();
385
-
386
- await user.keyboard("[ArrowRight]");
387
- labelRegex = new RegExp(` ${initialDate.getDate() + 1} `);
388
- selectedDateButton = getByRole(dialog, "button", { name: labelRegex });
389
- expect(selectedDateButton).toHaveClass(
390
- "moj-datepicker__button--selected",
391
- );
392
- expect(selectedDateButton).toHaveFocus();
393
- });
394
-
395
- test("left arrow navigates to next day", async () => {
396
- await user.click(calendarButton);
397
- const initialDateButton = getByRole(dialog, "button", {
398
- current: "date",
399
- });
400
- let selectedDateButton;
401
- let labelRegex;
402
-
403
- expect(initialDateButton).toHaveFocus();
404
-
405
- await user.keyboard("[ArrowLeft]");
406
- labelRegex = new RegExp(` ${initialDate.getDate() - 1} `);
407
- selectedDateButton = getByRole(dialog, "button", { name: labelRegex });
408
- expect(selectedDateButton).toHaveClass(
409
- "moj-datepicker__button--selected",
410
- );
411
- expect(selectedDateButton).toHaveFocus();
412
- });
413
-
414
- test("up arrow navigates to next day", async () => {
415
- await user.click(calendarButton);
416
- const initialDateButton = getByRole(dialog, "button", {
417
- current: "date",
418
- });
419
- let selectedDateButton;
420
- let labelRegex;
421
-
422
- expect(initialDateButton).toHaveFocus();
423
-
424
- await user.keyboard("[ArrowUp]");
425
- labelRegex = new RegExp(` ${initialDate.getDate() - 7} `);
426
- selectedDateButton = getByRole(dialog, "button", { name: labelRegex });
427
- expect(selectedDateButton).toHaveClass(
428
- "moj-datepicker__button--selected",
429
- );
430
- expect(selectedDateButton).toHaveFocus();
431
- });
432
-
433
- test("down arrow navigates to next day", async () => {
434
- await user.click(calendarButton);
435
- const initialDateButton = getByRole(dialog, "button", {
436
- current: "date",
437
- });
438
- let selectedDateButton;
439
- let labelRegex;
440
-
441
- expect(initialDateButton).toHaveFocus();
442
-
443
- await user.keyboard("[ArrowDown]");
444
- labelRegex = new RegExp(` ${initialDate.getDate() + 7} `);
445
- selectedDateButton = getByRole(dialog, "button", { name: labelRegex });
446
- expect(selectedDateButton).toHaveClass(
447
- "moj-datepicker__button--selected",
448
- );
449
- expect(selectedDateButton).toHaveFocus();
450
- });
451
-
452
- test("home key focuses first day of the week", async () => {
453
- await user.click(calendarButton);
454
- const initialDateButton = getByRole(dialog, "button", {
455
- current: "date",
456
- });
457
- const firstDayOfWeek = getFirstDayOfWeek(initialDate, 1);
458
- const labelRegex = new RegExp(` ${firstDayOfWeek.getDate()} `);
459
- const selectedDateButton = getByRole(dialog, "button", {
460
- name: labelRegex,
461
- });
462
-
463
- expect(initialDateButton).toHaveFocus();
464
- await user.keyboard("[Home]");
465
- expect(selectedDateButton).toHaveClass(
466
- "moj-datepicker__button--selected",
467
- );
468
- expect(selectedDateButton).toHaveFocus();
469
- });
470
-
471
- test("end key focuses last day of the week", async () => {
472
- await user.click(calendarButton);
473
- const initialDateButton = getByRole(dialog, "button", {
474
- current: "date",
475
- });
476
- const lastDayOfWeek = getLastDayOfWeek(initialDate, 0);
477
- const labelRegex = new RegExp(` ${lastDayOfWeek.getDate()} `);
478
- const selectedDateButton = getByRole(dialog, "button", {
479
- name: labelRegex,
480
- });
481
-
482
- expect(initialDateButton).toHaveFocus();
483
- await user.keyboard("[End]");
484
- expect(selectedDateButton).toHaveClass(
485
- "moj-datepicker__button--selected",
486
- );
487
- expect(selectedDateButton).toHaveFocus();
488
- });
489
-
490
- test("pageup focuses previous month and year", async () => {
491
- await user.click(calendarButton);
492
- const currentMonthName = initialDate.toLocaleString("default", {
493
- month: "long",
494
- });
495
- const currentYear = initialDate.getFullYear();
496
- const previousMonthName = new Date(
497
- new Date(initialDate).setMonth(initialDate.getMonth() - 1, 1),
498
- ).toLocaleString("default", { month: "long" });
499
- const previousYear = new Date(
500
- new Date(initialDate).setFullYear(initialDate.getFullYear() - 1),
501
- ).getFullYear();
502
- const currentTitle = `${currentMonthName} ${currentYear}`;
503
- const previousMonthTitle = `${previousMonthName} ${currentYear}`;
504
- const previousYearTitle = `${previousMonthName} ${previousYear}`;
505
- const dialogTitle = getByRole(dialog, "heading", { level: 2 });
506
-
507
- expect(dialogTitle.textContent).toEqual(currentTitle);
508
-
509
- await user.keyboard("{PageUp}");
510
- expect(dialogTitle.textContent).toEqual(previousMonthTitle);
511
-
512
- await user.keyboard("{Shift>}{PageUp}");
513
- expect(dialogTitle.textContent).toEqual(previousYearTitle);
514
- });
515
-
516
- test("pagedown focuses next month and year", async () => {
517
- await user.click(calendarButton);
518
- const currentMonthName = initialDate.toLocaleString("default", {
519
- month: "long",
520
- });
521
- const currentYear = initialDate.getFullYear();
522
- const nextMonthName = new Date(
523
- new Date(initialDate).setMonth(initialDate.getMonth() + 1, 1),
524
- ).toLocaleString("default", { month: "long" });
525
- const nextYear = new Date(
526
- new Date(initialDate).setFullYear(initialDate.getFullYear() + 1),
527
- ).getFullYear();
528
- const currentTitle = `${currentMonthName} ${currentYear}`;
529
- const nextMonthTitle = `${nextMonthName} ${currentYear}`;
530
- const nextYearTitle = `${nextMonthName} ${nextYear}`;
531
- const dialogTitle = getByRole(dialog, "heading", { level: 2 });
532
-
533
- expect(dialogTitle.textContent).toEqual(currentTitle);
534
-
535
- await user.keyboard("{PageDown}");
536
- expect(dialogTitle.textContent).toEqual(nextMonthTitle);
537
-
538
- await user.keyboard("{Shift>}{PageDown}");
539
- expect(dialogTitle.textContent).toEqual(nextYearTitle);
540
- });
541
-
542
- test("enter selects date and closes dialog", async () => {
543
- await user.click(calendarButton);
544
- await user.keyboard("[ArrowRight]");
545
- await user.keyboard("[Enter]");
546
-
547
- expect(dialog).not.toBeVisible();
548
- expect(input).toHaveValue(`20/5/2024`);
549
- expect(calendarButton).toHaveFocus();
550
- });
551
-
552
- test("space selects date and closes dialog", async () => {
553
- await user.click(calendarButton);
554
- await user.keyboard("[ArrowRight]");
555
- await user.keyboard("[Space]");
556
-
557
- expect(dialog).not.toBeVisible();
558
- expect(input).toHaveValue(`20/5/2024`);
559
- expect(calendarButton).toHaveFocus();
560
- });
561
-
562
- test("select button selects date and closes dialog", async () => {
563
- await user.click(calendarButton);
564
- await user.keyboard("[ArrowRight]");
565
- await user.tab();
566
- await user.keyboard("[Enter]");
567
-
568
- expect(dialog).not.toBeVisible();
569
- expect(input).toHaveValue(`20/5/2024`);
570
- expect(calendarButton).toHaveFocus();
571
- });
572
-
573
- test("close button, closes dialog", async () => {
574
- await user.click(calendarButton);
575
- await user.keyboard("[ArrowRight]");
576
- await user.tab();
577
- await user.tab();
578
- await user.keyboard("[Enter]");
579
-
580
- expect(dialog).not.toBeVisible();
581
- expect(input).toHaveValue(`19/5/2024`);
582
- expect(calendarButton).toHaveFocus();
583
- });
584
- });
585
-
586
- describe("accessibility", () => {
587
- test("component has no wcag violations", async () => {
588
- expect(await axe(document.body)).toHaveNoViolations();
589
- await user.click(calendarButton);
590
- expect(await axe(document.body)).toHaveNoViolations();
591
- });
592
- });
593
- });
594
-
595
- describe("button menu JS API", () => {
596
- let component;
597
-
598
- beforeEach(() => {
599
- component = createComponent();
600
- });
601
-
602
- afterEach(() => {
603
- document.body.innerHTML = "";
604
- });
605
-
606
- describe("config", () => {
607
- test("default config values", () => {
608
- const datePicker = new MOJFrontend.DatePicker(component, {});
609
- datePicker.init();
610
-
611
- expect(datePicker.config).toStrictEqual({
612
- leadingZeros: false,
613
- weekStartDay: "monday",
614
- });
615
- });
616
-
617
- test("leadingZeros", () => {
618
- const config = { leadingZeros: true };
619
- const datePicker = new MOJFrontend.DatePicker(component, config);
620
- datePicker.init();
621
-
622
- expect(datePicker.config.leadingZeros).toBe(true);
623
- });
624
-
625
- test("weekStartDay can be set to sunday", () => {
626
- const config = { weekStartDay: "Sunday" };
627
- const datePicker = new MOJFrontend.DatePicker(component, config);
628
- datePicker.init();
629
-
630
- expect(datePicker.config.weekStartDay).toBe("sunday");
631
- expect(datePicker.dayLabels[0]).toBe("Sunday");
632
- });
633
-
634
- test("weekStartDay can't be set to other days", () => {
635
- const config = { weekStartDay: "friday" };
636
- const datePicker = new MOJFrontend.DatePicker(component, config);
637
- datePicker.init();
638
-
639
- expect(datePicker.config.weekStartDay).toBe("monday");
640
- });
641
-
642
- test("minDate", () => {
643
- const minDate = dayjs().subtract("1", "week").startOf("day");
644
- const config = { minDate: minDate.format("D/M/YYYY") };
645
- const datePicker = new MOJFrontend.DatePicker(component, config);
646
- datePicker.init();
647
-
648
- expect(datePicker.minDate).toStrictEqual(minDate.toDate());
649
- });
650
-
651
- test("future minDate sets currentDate to minDate", () => {
652
- const minDate = dayjs().add("1", "week").startOf("day");
653
- const config = { minDate: minDate.format("D/M/YYYY") };
654
- const datePicker = new MOJFrontend.DatePicker(component, config);
655
- datePicker.init();
656
-
657
- expect(datePicker.minDate).toStrictEqual(minDate.toDate());
658
- expect(datePicker.currentDate).toStrictEqual(minDate.toDate());
659
- });
660
-
661
- test("maxDate", () => {
662
- const maxDate = dayjs().add("1", "week").startOf("day");
663
- const config = { maxDate: maxDate.format("D/M/YYYY") };
664
- const datePicker = new MOJFrontend.DatePicker(component, config);
665
- datePicker.init();
666
-
667
- expect(datePicker.maxDate).toStrictEqual(maxDate.toDate());
668
- });
669
-
670
- test("past maxDate sets currentDate to maxDate", () => {
671
- const maxDate = dayjs().subtract("1", "week").startOf("day");
672
- const config = { maxDate: maxDate.format("D/M/YYYY") };
673
- const datePicker = new MOJFrontend.DatePicker(component, config);
674
- datePicker.init();
675
-
676
- expect(datePicker.maxDate).toStrictEqual(maxDate.toDate());
677
- expect(datePicker.currentDate).toStrictEqual(maxDate.toDate());
678
- });
679
-
680
- test("excludedDays", () => {
681
- const config = { excludedDays: "sunday thursday" };
682
- const datePicker = new MOJFrontend.DatePicker(component, config);
683
- datePicker.init();
684
-
685
- expect(datePicker.excludedDays).toEqual([0, 4]);
686
- });
687
-
688
- describe("excludedDates", () => {
689
- test("excluding a day", () => {
690
- const dateToExclude = dayjs()
691
- .date(getDateInCurrentMonth())
692
- .startOf("day");
693
- config = { excludedDates: dateToExclude.format("D/M/YYYY") };
694
- const datePicker = new MOJFrontend.DatePicker(component, config);
695
- datePicker.init();
696
-
697
- expect(datePicker.excludedDates).toStrictEqual([
698
- dateToExclude.toDate(),
699
- ]);
700
- });
701
-
702
- test("excluding multiple dates", () => {
703
- const firstDateToExclude = dayjs()
704
- .date(getDateInCurrentMonth())
705
- .startOf("day");
706
- const secondDateToExclude = dayjs()
707
- .date(getDateInCurrentMonth([firstDateToExclude.date()]))
708
- .startOf("day");
709
- config = {
710
- excludedDates: `${firstDateToExclude.format("D/M/YYYY")} ${secondDateToExclude.format("D/M/YYYY")}`,
711
- };
712
- const datePicker = new MOJFrontend.DatePicker(component, config);
713
- datePicker.init();
714
-
715
- expect(datePicker.excludedDates.length).toEqual(2);
716
- expect(datePicker.excludedDates).toStrictEqual([
717
- firstDateToExclude.toDate(),
718
- secondDateToExclude.toDate(),
719
- ]);
720
- });
721
-
722
- test("excluding a range of days", () => {
723
- let datesToExclude;
724
- if (dayjs().date() < 15) {
725
- datesToExclude = getDateRangeInCurrentMonth(18, 20);
726
- } else {
727
- datesToExclude = getDateRangeInCurrentMonth(3, 5);
728
- }
729
- datesToExclude = datesToExclude.map((date) => date.startOf("day"));
730
- config = {
731
- excludedDates: `${datesToExclude[0].format("D/M/YYYY")}-${datesToExclude[datesToExclude.length - 1].format("D/M/YYYY")}`,
732
- };
733
- const datePicker = new MOJFrontend.DatePicker(component, config);
734
- datePicker.init();
735
-
736
- expect(datePicker.excludedDates.length).toEqual(3);
737
- expect(datePicker.excludedDates).toStrictEqual(
738
- datesToExclude.map((date) => date.toDate()),
739
- );
740
- });
741
-
742
- test("excluding individual dates and a range of days", () => {
743
- let datesToExclude;
744
- if (dayjs().date() < 15) {
745
- datesToExclude = getDateRangeInCurrentMonth(18, 20);
746
- datesToExclude.push(dayjs().date(22));
747
- datesToExclude.push(dayjs().date(25));
748
- } else {
749
- datesToExclude = getDateRangeInCurrentMonth(3, 5);
750
- datesToExclude.push(dayjs().date(7));
751
- datesToExclude.push(dayjs().date(11));
752
- }
753
- datesToExclude = datesToExclude.map((date) => date.startOf("day"));
754
- config = {
755
- excludedDates: `${datesToExclude[0].format("D/M/YYYY")}-${datesToExclude[2].format("D/M/YYYY")} ${datesToExclude[3].format("D/M/YYYY")} ${datesToExclude[4].format("D/M/YYYY")} `,
756
- };
757
- const datePicker = new MOJFrontend.DatePicker(component, config);
758
- datePicker.init();
759
-
760
- expect(datePicker.excludedDates.length).toEqual(5);
761
- expect(datePicker.excludedDates).toStrictEqual(
762
- datesToExclude.map((date) => date.toDate()),
763
- );
764
- });
765
- });
766
- });
767
-
768
- describe("UI", () => {
769
- let calendarButton;
770
- let input;
771
-
772
- test("with leadingZeros false", async () => {
773
- input = screen.getByLabelText("Date");
774
-
775
- const config = { leadingZeros: false };
776
- new MOJFrontend.DatePicker(component, config).init();
777
- calendarButton = screen.getByRole("button", { name: "Choose date" });
778
- const dateToSelect = dayjs().date(9);
779
- const dateButton = screen.getByTestId(dateToSelect.format("D/M/YYYY"));
780
-
781
- await user.click(calendarButton);
782
- await user.click(dateButton);
783
-
784
- expect(input).toHaveValue(dateToSelect.format("D/M/YYYY"));
785
- });
786
-
787
- test("with leadingZeros true", async () => {
788
- input = screen.getByLabelText("Date");
789
-
790
- const config = { leadingZeros: true };
791
- new MOJFrontend.DatePicker(component, config).init();
792
- calendarButton = screen.getByRole("button", { name: "Choose date" });
793
- const dateToSelect = dayjs().date(9);
794
- const dateButton = screen.getByTestId(dateToSelect.format("DD/MM/YYYY"));
795
-
796
- await user.click(calendarButton);
797
- await user.click(dateButton);
798
-
799
- expect(input).toHaveValue(dateToSelect.format("DD/MM/YYYY"));
800
- });
801
-
802
- test.skip.failing("minDate", async () => {
803
- const minDay = 3;
804
- const lastDayinMonth = dayjs().endOf("month").date();
805
- const minDate = dayjs().date(minDay);
806
- const config = { minDate: minDate.format("DD/MM/YYYY") };
807
-
808
- new MOJFrontend.DatePicker(component, config).init();
809
- calendarButton = screen.getByRole("button", { name: "Choose date" });
810
- await user.click(calendarButton);
811
-
812
- for (let i = 1; i <= lastDayinMonth; i++) {
813
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
814
- const dayButton = screen.getByTestId(testId);
815
-
816
- if (i <= minDay) {
817
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
818
- } else {
819
- expect(dayButton).not.toHaveAttribute("aria-disabled");
820
- }
821
- }
822
- });
823
-
824
- test("maxDate", async () => {
825
- const maxDay = 21;
826
- const lastDayinMonth = dayjs().endOf("month").date();
827
- const maxDate = dayjs().date(maxDay);
828
- const config = { maxDate: maxDate.format("DD/MM/YYYY") };
829
-
830
- new MOJFrontend.DatePicker(component, config).init();
831
- calendarButton = screen.getByRole("button", { name: "Choose date" });
832
- await user.click(calendarButton);
833
-
834
- for (let i = 1; i <= lastDayinMonth; i++) {
835
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
836
- const dayButton = screen.getByTestId(testId);
837
-
838
- if (i > maxDay) {
839
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
840
- } else {
841
- expect(dayButton).not.toHaveAttribute("aria-disabled");
842
- }
843
- }
844
- });
845
-
846
- describe("excludedDates", () => {
847
- test("excluding a day", async () => {
848
- const dateToExclude = dayjs()
849
- .date(getDateInCurrentMonth())
850
- .startOf("day");
851
- const excludedDay = dateToExclude.date();
852
- const config = { excludedDates: dateToExclude.format("D/M/YYYY") };
853
-
854
- const lastDayinMonth = dayjs().endOf("month").date();
855
-
856
- new MOJFrontend.DatePicker(component, config).init();
857
- calendarButton = screen.getByRole("button", { name: "Choose date" });
858
- await user.click(calendarButton);
859
-
860
- for (let i = 1; i <= lastDayinMonth; i++) {
861
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
862
- const dayButton = screen.getByTestId(testId);
863
-
864
- if (i == excludedDay) {
865
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
866
- } else {
867
- expect(dayButton).not.toHaveAttribute("aria-disabled");
868
- }
869
- }
870
- });
871
-
872
- test("excluding a range of days", async () => {
873
- let datesToExclude;
874
- if (dayjs().date() < 15) {
875
- datesToExclude = getDateRangeInCurrentMonth(18, 20);
876
- } else {
877
- datesToExclude = getDateRangeInCurrentMonth(3, 5);
878
- }
879
- datesToExclude = datesToExclude.map((date) => date.startOf("day"));
880
- let daysToExclude = datesToExclude.map((date) => date.date());
881
- const lastDayinMonth = dayjs().endOf("month").date();
882
- config = {
883
- excludedDates: `${datesToExclude[0].format("D/M/YYYY")}-${datesToExclude[datesToExclude.length - 1].format("D/M/YYYY")}`,
884
- };
885
-
886
- datePicker = new MOJFrontend.DatePicker(component, config).init();
887
- calendarButton = screen.getByRole("button", { name: "Choose date" });
888
- await user.click(calendarButton);
889
-
890
- for (let i = 1; i <= lastDayinMonth; i++) {
891
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
892
- const dayButton = screen.getByTestId(testId);
893
-
894
- if (daysToExclude.includes(i)) {
895
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
896
- } else {
897
- expect(dayButton).not.toHaveAttribute("aria-disabled");
898
- }
899
- }
900
- });
901
- });
902
-
903
- test("excludedDays", async () => {
904
- const config = { excludedDays: "sunday" };
905
- const lastDayinMonth = dayjs().endOf("month").date();
906
- let excludedDays = [];
907
- for (let i = 1; i <= lastDayinMonth; i++) {
908
- if (dayjs().date(i).day() === 0) {
909
- excludedDays.push(i);
910
- }
911
- }
912
- new MOJFrontend.DatePicker(component, config).init();
913
- calendarButton = screen.getByRole("button", { name: "Choose date" });
914
- await user.click(calendarButton);
915
-
916
- for (let i = 1; i <= lastDayinMonth; i++) {
917
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
918
- const dayButton = screen.getByTestId(testId);
919
-
920
- if (excludedDays.includes(i)) {
921
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
922
- } else {
923
- expect(dayButton).not.toHaveAttribute("aria-disabled");
924
- }
925
- }
926
- });
927
-
928
- test("default weekStartDay", async () => {
929
- new MOJFrontend.DatePicker(component, {}).init();
930
- calendarButton = screen.getByRole("button", { name: "Choose date" });
931
- await user.click(calendarButton);
932
- const headers = getAllByRole(component, "columnheader");
933
-
934
- expect(headers[0]).toHaveAccessibleName("Monday");
935
- });
936
-
937
- test("weekStartDay Sunday", async () => {
938
- new MOJFrontend.DatePicker(component, { weekStartDay: "sunday" }).init();
939
- calendarButton = screen.getByRole("button", { name: "Choose date" });
940
- await user.click(calendarButton);
941
- const headers = getAllByRole(component, "columnheader");
942
-
943
- expect(headers[0]).toHaveAccessibleName("Sunday");
944
- });
945
- });
946
- });
947
-
948
- describe("Datepicker data-attributes API", () => {
949
- let component;
950
- let calendarButton;
951
- let input;
952
-
953
- beforeEach(() => {});
954
-
955
- afterEach(() => {
956
- document.body.innerHTML = "";
957
- });
958
-
959
- test("with leadingZeros false", async () => {
960
- component = createComponent({ leadingZeros: "false" });
961
- new MOJFrontend.DatePicker(component).init();
962
-
963
- input = screen.getByLabelText("Date");
964
- calendarButton = screen.getByRole("button", { name: "Choose date" });
965
- const dateToSelect = dayjs().date(9);
966
- const dateButton = screen.getByTestId(dateToSelect.format("D/M/YYYY"));
967
-
968
- await user.click(calendarButton);
969
- await user.click(dateButton);
970
-
971
- expect(input).toHaveValue(dateToSelect.format("D/M/YYYY"));
972
- });
973
-
974
- test("with leadingZeros true", async () => {
975
- const component = createComponent({ leadingZeros: "true" });
976
- new MOJFrontend.DatePicker(component).init();
977
-
978
- input = screen.getByLabelText("Date");
979
- calendarButton = screen.getByRole("button", { name: "Choose date" });
980
- const dateToSelect = dayjs().date(9);
981
- const dateButton = screen.getByTestId(dateToSelect.format("DD/MM/YYYY"));
982
-
983
- await user.click(calendarButton);
984
- await user.click(dateButton);
985
-
986
- expect(input).toHaveValue(dateToSelect.format("DD/MM/YYYY"));
987
- });
988
-
989
- test.skip.failing("minDate", async () => {
990
- const minDay = 3;
991
- const lastDayinMonth = dayjs().endOf("month").date();
992
- const minDate = dayjs().date(minDay);
993
- const component = createComponent({
994
- minDate: minDate.format("DD/MM/YYYY"),
995
- });
996
- new MOJFrontend.DatePicker(component).init();
997
- calendarButton = screen.getByRole("button", { name: "Choose date" });
998
-
999
- await user.click(calendarButton);
1000
-
1001
- for (let i = 1; i <= lastDayinMonth; i++) {
1002
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
1003
- const dayButton = screen.getByTestId(testId);
1004
-
1005
- if (i <= minDay) {
1006
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
1007
- } else {
1008
- expect(dayButton).not.toHaveAttribute("aria-disabled");
1009
- }
1010
- }
1011
- });
1012
-
1013
- test("maxDate", async () => {
1014
- const maxDay = 21;
1015
- const lastDayinMonth = dayjs().endOf("month").date();
1016
- const maxDate = dayjs().date(maxDay);
1017
- const component = createComponent({
1018
- maxDate: maxDate.format("DD/MM/YYYY"),
1019
- });
1020
- new MOJFrontend.DatePicker(component).init();
1021
- calendarButton = screen.getByRole("button", { name: "Choose date" });
1022
-
1023
- await user.click(calendarButton);
1024
-
1025
- for (let i = 1; i <= lastDayinMonth; i++) {
1026
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
1027
- const dayButton = screen.getByTestId(testId);
1028
-
1029
- if (i > maxDay) {
1030
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
1031
- } else {
1032
- expect(dayButton).not.toHaveAttribute("aria-disabled");
1033
- }
1034
- }
1035
- });
1036
-
1037
- describe("excludedDates", () => {
1038
- test("excluding a day", async () => {
1039
- const dateToExclude = dayjs()
1040
- .date(getDateInCurrentMonth())
1041
- .startOf("day");
1042
- const excludedDay = dateToExclude.date();
1043
- const lastDayinMonth = dayjs().endOf("month").date();
1044
- const component = createComponent({
1045
- excludedDates: dateToExclude.format("D/M/YYYY"),
1046
- });
1047
- new MOJFrontend.DatePicker(component).init();
1048
- calendarButton = screen.getByRole("button", { name: "Choose date" });
1049
-
1050
- await user.click(calendarButton);
1051
-
1052
- for (let i = 1; i <= lastDayinMonth; i++) {
1053
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
1054
- const dayButton = screen.getByTestId(testId);
1055
-
1056
- if (i == excludedDay) {
1057
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
1058
- } else {
1059
- expect(dayButton).not.toHaveAttribute("aria-disabled");
1060
- }
1061
- }
1062
- });
1063
-
1064
- test("excluding a range of days", async () => {
1065
- let datesToExclude;
1066
- if (dayjs().date() < 15) {
1067
- datesToExclude = getDateRangeInCurrentMonth(18, 20);
1068
- } else {
1069
- datesToExclude = getDateRangeInCurrentMonth(3, 5);
1070
- }
1071
- datesToExclude = datesToExclude.map((date) => date.startOf("day"));
1072
- let daysToExclude = datesToExclude.map((date) => date.date());
1073
- const lastDayinMonth = dayjs().endOf("month").date();
1074
- component = createComponent({
1075
- excludedDates: `${datesToExclude[0].format("D/M/YYYY")}-${datesToExclude[datesToExclude.length - 1].format("D/M/YYYY")}`,
1076
- });
1077
- datePicker = new MOJFrontend.DatePicker(component).init();
1078
- calendarButton = screen.getByRole("button", { name: "Choose date" });
1079
-
1080
- await user.click(calendarButton);
1081
-
1082
- for (let i = 1; i <= lastDayinMonth; i++) {
1083
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
1084
- const dayButton = screen.getByTestId(testId);
1085
-
1086
- if (daysToExclude.includes(i)) {
1087
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
1088
- } else {
1089
- expect(dayButton).not.toHaveAttribute("aria-disabled");
1090
- }
1091
- }
1092
- });
1093
- });
1094
-
1095
- test("excludedDays", async () => {
1096
- const component = createComponent({ excludedDays: "sunday" });
1097
- const lastDayinMonth = dayjs().endOf("month").date();
1098
- let excludedDays = [];
1099
- for (let i = 1; i <= lastDayinMonth; i++) {
1100
- if (dayjs().date(i).day() === 0) {
1101
- excludedDays.push(i);
1102
- }
1103
- }
1104
- new MOJFrontend.DatePicker(component).init();
1105
- calendarButton = screen.getByRole("button", { name: "Choose date" });
1106
-
1107
- await user.click(calendarButton);
1108
-
1109
- for (let i = 1; i <= lastDayinMonth; i++) {
1110
- const testId = dayjs().date(i).startOf("day").format("D/M/YYYY");
1111
- const dayButton = screen.getByTestId(testId);
1112
-
1113
- if (excludedDays.includes(i)) {
1114
- expect(dayButton).toHaveAttribute("aria-disabled", "true");
1115
- } else {
1116
- expect(dayButton).not.toHaveAttribute("aria-disabled");
1117
- }
1118
- }
1119
- });
1120
-
1121
- test("weekStartDay", async () => {
1122
- component = createComponent({ weekStartDay: "sunday" });
1123
- new MOJFrontend.DatePicker(component).init();
1124
- calendarButton = screen.getByRole("button", { name: "Choose date" });
1125
- await user.click(calendarButton);
1126
- const headers = getAllByRole(component, "columnheader");
1127
-
1128
- expect(headers[0]).toHaveAccessibleName("Sunday");
1129
- });
1130
- });