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