@instructure/ui-date-time-input 8.55.1-snapshot-0 → 8.55.1-snapshot-3
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/CHANGELOG.md +1 -1
- package/es/DateTimeInput/__new-tests__/DateTimeInput.test.js +671 -190
- package/lib/DateTimeInput/__new-tests__/DateTimeInput.test.js +672 -192
- package/package.json +18 -19
- package/src/DateTimeInput/__new-tests__/DateTimeInput.test.tsx +740 -184
- package/tsconfig.build.json +0 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/DateTimeInput/__new-tests__/DateTimeInput.test.d.ts.map +1 -1
|
@@ -23,210 +23,766 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import React from 'react'
|
|
26
|
-
import { render } from '@testing-library/react'
|
|
26
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
|
27
|
+
import userEvent from '@testing-library/user-event'
|
|
27
28
|
import '@testing-library/jest-dom'
|
|
28
|
-
|
|
29
|
-
import DateTimeInput from '../index'
|
|
29
|
+
|
|
30
|
+
import { DateTimeInput } from '../index'
|
|
31
|
+
import { ApplyLocale, DateTime } from '@instructure/ui-i18n'
|
|
30
32
|
|
|
31
33
|
describe('<DateTimeInput />', () => {
|
|
32
|
-
|
|
34
|
+
let consoleErrorMock: jest.SpyInstance
|
|
35
|
+
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
// Mocking console to prevent test output pollution and expect for messages
|
|
38
|
+
consoleErrorMock = jest.spyOn(console, 'error').mockImplementation()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
consoleErrorMock.mockRestore()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should use the default value', () => {
|
|
33
46
|
const locale = 'en-US'
|
|
34
47
|
const timezone = 'US/Eastern'
|
|
48
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
49
|
+
|
|
50
|
+
render(
|
|
51
|
+
<DateTimeInput
|
|
52
|
+
description="date_time"
|
|
53
|
+
prevMonthLabel="Previous month"
|
|
54
|
+
nextMonthLabel="Next month"
|
|
55
|
+
dateRenderLabel="date-input"
|
|
56
|
+
timeRenderLabel="time-input"
|
|
57
|
+
invalidDateTimeMessage="whoops"
|
|
58
|
+
locale={locale}
|
|
59
|
+
timezone={timezone}
|
|
60
|
+
defaultValue={dateTime.toISOString()}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
64
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
65
|
+
|
|
66
|
+
expect(dateInput).toHaveValue(dateTime.format('LL'))
|
|
67
|
+
expect(timeInput).toHaveValue(dateTime.format('LT'))
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('should use the value', () => {
|
|
71
|
+
const onChange = jest.fn()
|
|
72
|
+
const locale = 'en-US'
|
|
73
|
+
const timezone = 'US/Eastern'
|
|
74
|
+
const dateTime = DateTime.parse('2017-05-01T23:30Z', locale, timezone)
|
|
75
|
+
|
|
76
|
+
render(
|
|
77
|
+
<DateTimeInput
|
|
78
|
+
description="date_time"
|
|
79
|
+
prevMonthLabel="Previous month"
|
|
80
|
+
nextMonthLabel="Next month"
|
|
81
|
+
dateRenderLabel="date-input"
|
|
82
|
+
timeRenderLabel="time-input"
|
|
83
|
+
invalidDateTimeMessage="whoops"
|
|
84
|
+
locale={locale}
|
|
85
|
+
timezone={timezone}
|
|
86
|
+
value={dateTime.toISOString()}
|
|
87
|
+
onChange={onChange}
|
|
88
|
+
/>
|
|
89
|
+
)
|
|
90
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
91
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
92
|
+
|
|
93
|
+
expect(dateInput).toHaveValue(dateTime.format('LL'))
|
|
94
|
+
expect(timeInput).toHaveValue(dateTime.format('LT'))
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('should prefer value to defaultValue', () => {
|
|
98
|
+
const locale = 'en-US'
|
|
99
|
+
const timezone = 'US/Eastern'
|
|
100
|
+
const value = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
101
|
+
const defaultValue = DateTime.parse('2016-04-01T17:00Z', locale, timezone)
|
|
102
|
+
const onChange = jest.fn()
|
|
103
|
+
|
|
104
|
+
render(
|
|
105
|
+
<DateTimeInput
|
|
106
|
+
description="date_time"
|
|
107
|
+
prevMonthLabel="Previous month"
|
|
108
|
+
nextMonthLabel="Next month"
|
|
109
|
+
dateRenderLabel="date-input"
|
|
110
|
+
timeRenderLabel="time-input"
|
|
111
|
+
invalidDateTimeMessage="whoops"
|
|
112
|
+
locale={locale}
|
|
113
|
+
timezone={timezone}
|
|
114
|
+
value={value.toISOString()}
|
|
115
|
+
defaultValue={defaultValue.toISOString()}
|
|
116
|
+
onChange={onChange}
|
|
117
|
+
/>
|
|
118
|
+
)
|
|
119
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
120
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
121
|
+
|
|
122
|
+
expect(dateInput).toHaveValue(value.format('LL'))
|
|
123
|
+
expect(timeInput).toHaveValue(value.format('LT'))
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('should set time to local midnight when only date is set', () => {
|
|
127
|
+
const locale = 'en-US'
|
|
128
|
+
const timezone = 'US/Eastern'
|
|
129
|
+
const dateObj = DateTime.parse('2017-04-01T18:30Z', locale, timezone)
|
|
130
|
+
const date = dateObj.toISOString().split('T')[0]
|
|
131
|
+
|
|
132
|
+
render(
|
|
133
|
+
<DateTimeInput
|
|
134
|
+
description="date_time"
|
|
135
|
+
dateRenderLabel="date-input"
|
|
136
|
+
prevMonthLabel="Previous month"
|
|
137
|
+
nextMonthLabel="Next month"
|
|
138
|
+
timeRenderLabel="time-input"
|
|
139
|
+
invalidDateTimeMessage="whoops"
|
|
140
|
+
locale={locale}
|
|
141
|
+
timezone={timezone}
|
|
142
|
+
defaultValue={date}
|
|
143
|
+
/>
|
|
144
|
+
)
|
|
145
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
146
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
147
|
+
|
|
148
|
+
expect(dateInput).toHaveValue(dateObj.format('LL'))
|
|
149
|
+
expect(timeInput).toHaveValue('12:00 AM')
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('should call invalidDateTimeMessage if time is set w/o a date and is required', async () => {
|
|
153
|
+
const invalidDateTimeMessage = jest.fn((_rawd) => 'whoops')
|
|
35
154
|
|
|
36
155
|
const { container } = render(
|
|
37
156
|
<DateTimeInput
|
|
38
|
-
description="
|
|
157
|
+
description="date_time"
|
|
158
|
+
dateRenderLabel="date-input"
|
|
39
159
|
prevMonthLabel="Previous month"
|
|
40
160
|
nextMonthLabel="Next month"
|
|
41
|
-
|
|
42
|
-
|
|
161
|
+
timeRenderLabel="time-input"
|
|
162
|
+
locale="en-US"
|
|
163
|
+
timezone="US/Eastern"
|
|
164
|
+
isRequired
|
|
165
|
+
invalidDateTimeMessage={invalidDateTimeMessage}
|
|
166
|
+
/>
|
|
167
|
+
)
|
|
168
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
169
|
+
|
|
170
|
+
await userEvent.type(timeInput, '1:00 PM')
|
|
171
|
+
fireEvent.blur(timeInput)
|
|
172
|
+
|
|
173
|
+
await waitFor(() => {
|
|
174
|
+
expect(container).toHaveTextContent('whoops')
|
|
175
|
+
expect(invalidDateTimeMessage).toHaveBeenCalled()
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
it('should not call invalidDateTimeMessage if time is set w/o a date', async () => {
|
|
180
|
+
const invalidDateTimeMessage = jest.fn((_rawd) => 'whoops')
|
|
181
|
+
|
|
182
|
+
render(
|
|
183
|
+
<DateTimeInput
|
|
184
|
+
description="date_time"
|
|
185
|
+
dateRenderLabel="date-input"
|
|
186
|
+
prevMonthLabel="Previous month"
|
|
187
|
+
nextMonthLabel="Next month"
|
|
188
|
+
timeRenderLabel="time-input"
|
|
189
|
+
locale="en-US"
|
|
190
|
+
timezone="US/Eastern"
|
|
191
|
+
invalidDateTimeMessage={invalidDateTimeMessage}
|
|
192
|
+
/>
|
|
193
|
+
)
|
|
194
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
195
|
+
|
|
196
|
+
await userEvent.type(timeInput, '1:00 PM{enter}')
|
|
197
|
+
|
|
198
|
+
await waitFor(() => {
|
|
199
|
+
const errorMessages = screen.queryByText('whoops')
|
|
200
|
+
|
|
201
|
+
expect(errorMessages).not.toBeInTheDocument()
|
|
202
|
+
expect(invalidDateTimeMessage).not.toHaveBeenCalled()
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
it('should fire the onChange event when TimeInput value changes', async () => {
|
|
207
|
+
const onChange = jest.fn()
|
|
208
|
+
|
|
209
|
+
const locale = 'en-US'
|
|
210
|
+
const timezone = 'US/Eastern'
|
|
211
|
+
const defaultValue = DateTime.parse('2017-05-01T17:00', locale, timezone)
|
|
212
|
+
|
|
213
|
+
render(
|
|
214
|
+
<DateTimeInput
|
|
215
|
+
description="date_time"
|
|
216
|
+
dateRenderLabel="date-input"
|
|
217
|
+
prevMonthLabel="Previous month"
|
|
218
|
+
nextMonthLabel="Next month"
|
|
219
|
+
timeRenderLabel="time-input"
|
|
43
220
|
invalidDateTimeMessage="whoops"
|
|
44
221
|
locale={locale}
|
|
45
222
|
timezone={timezone}
|
|
46
|
-
|
|
223
|
+
onChange={onChange}
|
|
224
|
+
defaultValue={defaultValue.toISOString()}
|
|
225
|
+
/>
|
|
226
|
+
)
|
|
227
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
228
|
+
|
|
229
|
+
fireEvent.change(timeInput, { target: { value: '3:00 AM' } })
|
|
230
|
+
fireEvent.keyDown(timeInput, { key: 'Enter', code: 'Enter' })
|
|
231
|
+
fireEvent.blur(timeInput)
|
|
232
|
+
|
|
233
|
+
await waitFor(() => {
|
|
234
|
+
expect(onChange).toHaveBeenCalled()
|
|
235
|
+
expect(onChange.mock.calls[0][0].target.value).toMatch('3:00 AM')
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
it('should show correct message when TimeInput value changes', () => {
|
|
240
|
+
const { container } = render(
|
|
241
|
+
<DateTimeInput
|
|
242
|
+
description="date_time"
|
|
243
|
+
dateRenderLabel="date-input"
|
|
244
|
+
prevMonthLabel="Previous month"
|
|
245
|
+
nextMonthLabel="Next month"
|
|
246
|
+
timeRenderLabel="time-input"
|
|
247
|
+
invalidDateTimeMessage="whoops"
|
|
248
|
+
locale="en-US"
|
|
249
|
+
timezone="US/Eastern"
|
|
250
|
+
defaultValue="2018-01-18T13:00"
|
|
47
251
|
/>
|
|
48
252
|
)
|
|
49
|
-
|
|
50
|
-
|
|
253
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
254
|
+
|
|
255
|
+
fireEvent.change(timeInput, { target: { value: '5:00 PM' } })
|
|
256
|
+
fireEvent.keyDown(timeInput, { key: 'Enter', code: 'Enter' })
|
|
257
|
+
fireEvent.blur(timeInput)
|
|
258
|
+
|
|
259
|
+
expect(container).toHaveTextContent('Thursday, January 18, 2018 5:00 PM')
|
|
51
260
|
})
|
|
52
261
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
262
|
+
it('should show the formatted date-time message', () => {
|
|
263
|
+
const locale = 'en-US'
|
|
264
|
+
const timezone = 'US/Eastern'
|
|
265
|
+
const defaultValue = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
266
|
+
|
|
267
|
+
const { container } = render(
|
|
268
|
+
<DateTimeInput
|
|
269
|
+
description="date_time"
|
|
270
|
+
dateRenderLabel="date-input"
|
|
271
|
+
prevMonthLabel="Previous month"
|
|
272
|
+
nextMonthLabel="Next month"
|
|
273
|
+
timeRenderLabel="time-input"
|
|
274
|
+
invalidDateTimeMessage="whoops"
|
|
275
|
+
locale={locale}
|
|
276
|
+
timezone={timezone}
|
|
277
|
+
defaultValue={defaultValue.toISOString()}
|
|
278
|
+
/>
|
|
279
|
+
)
|
|
56
280
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// invalidDateTimeMessage="whoops"
|
|
65
|
-
// locale={locale}
|
|
66
|
-
// timezone={timezone}
|
|
67
|
-
// initialTimeForNewDate="05:05"
|
|
68
|
-
// />
|
|
69
|
-
// )
|
|
281
|
+
expect(container).toHaveTextContent('Monday, May 1, 2017 1:30 PM')
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
it('should show the formatted date-time message in the proper locale', () => {
|
|
285
|
+
const timezone = 'US/Eastern'
|
|
286
|
+
const locale = 'fr'
|
|
287
|
+
const defaultValue = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
70
288
|
|
|
71
|
-
|
|
289
|
+
const { container } = render(
|
|
290
|
+
<DateTimeInput
|
|
291
|
+
description="date_time"
|
|
292
|
+
dateRenderLabel="date-input"
|
|
293
|
+
prevMonthLabel="Previous month"
|
|
294
|
+
nextMonthLabel="Next month"
|
|
295
|
+
timeRenderLabel="time-input"
|
|
296
|
+
invalidDateTimeMessage="whoops"
|
|
297
|
+
locale={locale}
|
|
298
|
+
timezone={timezone}
|
|
299
|
+
defaultValue={defaultValue.toISOString()}
|
|
300
|
+
/>
|
|
301
|
+
)
|
|
302
|
+
expect(container).toHaveTextContent('1 mai 2017 13:30')
|
|
303
|
+
})
|
|
72
304
|
|
|
73
|
-
|
|
305
|
+
it('should provide the html elements for date and time input', () => {
|
|
306
|
+
let dref
|
|
307
|
+
let tref
|
|
74
308
|
|
|
75
|
-
|
|
309
|
+
render(
|
|
310
|
+
<DateTimeInput
|
|
311
|
+
description="date_time"
|
|
312
|
+
dateRenderLabel="date-input"
|
|
313
|
+
prevMonthLabel="Previous month"
|
|
314
|
+
nextMonthLabel="Next month"
|
|
315
|
+
timeRenderLabel="time-input"
|
|
316
|
+
invalidDateTimeMessage="whoops"
|
|
317
|
+
locale="en-US"
|
|
318
|
+
timezone="US/Eastern"
|
|
319
|
+
dateInputRef={(el) => {
|
|
320
|
+
dref = el
|
|
321
|
+
}}
|
|
322
|
+
timeInputRef={(el) => {
|
|
323
|
+
tref = el
|
|
324
|
+
}}
|
|
325
|
+
/>
|
|
326
|
+
)
|
|
327
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
328
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
76
329
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
330
|
+
expect(dateInput).toEqual(dref)
|
|
331
|
+
expect(timeInput).toEqual(tref)
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
it('should update message when value prop changes', () => {
|
|
335
|
+
const onChange = jest.fn()
|
|
336
|
+
const locale = 'en-US'
|
|
337
|
+
const timezone = 'US/Eastern'
|
|
338
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
339
|
+
|
|
340
|
+
const props = {
|
|
341
|
+
description: 'date_time',
|
|
342
|
+
prevMonthLabel: 'Previous month',
|
|
343
|
+
nextMonthLabel: 'Next month',
|
|
344
|
+
dateRenderLabel: 'date',
|
|
345
|
+
timeRenderLabel: 'time',
|
|
346
|
+
invalidDateTimeMessage: 'whoops',
|
|
347
|
+
locale,
|
|
348
|
+
timezone,
|
|
349
|
+
value: dateTime.toISOString(),
|
|
350
|
+
onChange
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const { container, rerender } = render(<DateTimeInput {...props} />)
|
|
354
|
+
expect(container).toHaveTextContent('May 1, 2017 1:30 PM')
|
|
355
|
+
|
|
356
|
+
rerender(<DateTimeInput {...props} value="2018-03-29T16:30Z" />)
|
|
357
|
+
expect(container).toHaveTextContent('March 29, 2018 12:30 PM')
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it('should update message when locale changed', () => {
|
|
361
|
+
const onChange = jest.fn()
|
|
362
|
+
const locale = 'en-US'
|
|
363
|
+
const timezone = 'US/Eastern'
|
|
364
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
365
|
+
|
|
366
|
+
const props = {
|
|
367
|
+
description: 'date_time',
|
|
368
|
+
dateRenderLabel: 'date-input',
|
|
369
|
+
prevMonthLabel: 'Previous month',
|
|
370
|
+
nextMonthLabel: 'Next month',
|
|
371
|
+
timeRenderLabel: 'time-input',
|
|
372
|
+
invalidDateTimeMessage: 'whoops',
|
|
373
|
+
locale,
|
|
374
|
+
timezone,
|
|
375
|
+
onChange,
|
|
376
|
+
value: dateTime.toISOString()
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const { container, rerender } = render(<DateTimeInput {...props} />)
|
|
380
|
+
expect(container).toHaveTextContent('May 1, 2017 1:30 PM')
|
|
381
|
+
|
|
382
|
+
rerender(<DateTimeInput {...props} locale="fr" />)
|
|
383
|
+
expect(container).toHaveTextContent('1 mai 2017 13:30')
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('should update message when timezone changed', () => {
|
|
387
|
+
const onChange = jest.fn()
|
|
388
|
+
const locale = 'en-US'
|
|
389
|
+
const timezone = 'US/Eastern'
|
|
390
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
391
|
+
const props = {
|
|
392
|
+
description: 'date_time',
|
|
393
|
+
dateRenderLabel: 'date-input',
|
|
394
|
+
prevMonthLabel: 'Previous month',
|
|
395
|
+
nextMonthLabel: 'Next month',
|
|
396
|
+
timeRenderLabel: 'time-input',
|
|
397
|
+
invalidDateTimeMessage: 'whoops',
|
|
398
|
+
locale,
|
|
399
|
+
timezone,
|
|
400
|
+
onChange,
|
|
401
|
+
value: dateTime.toISOString()
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const { container, rerender } = render(<DateTimeInput {...props} />)
|
|
405
|
+
expect(container).toHaveTextContent('May 1, 2017 1:30 PM')
|
|
406
|
+
|
|
407
|
+
rerender(<DateTimeInput {...props} timezone="Europe/Paris" />)
|
|
408
|
+
expect(container).toHaveTextContent('May 1, 2017 7:30 PM')
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
it('should show error message if initial value is invalid', async () => {
|
|
412
|
+
const { container } = render(
|
|
413
|
+
<DateTimeInput
|
|
414
|
+
description="date_time"
|
|
415
|
+
dateRenderLabel="date-input"
|
|
416
|
+
prevMonthLabel="Previous month"
|
|
417
|
+
nextMonthLabel="Next month"
|
|
418
|
+
timeRenderLabel="time-input"
|
|
419
|
+
invalidDateTimeMessage="whoops"
|
|
420
|
+
value="totally not a date"
|
|
421
|
+
/>
|
|
422
|
+
)
|
|
423
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
424
|
+
fireEvent.blur(dateInput)
|
|
425
|
+
|
|
426
|
+
await waitFor(() => {
|
|
427
|
+
expect(container).toHaveTextContent('whoops')
|
|
428
|
+
})
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
it('should show error message if initial defaultValue is invalid', async () => {
|
|
432
|
+
const { container } = render(
|
|
433
|
+
<DateTimeInput
|
|
434
|
+
description="date_time"
|
|
435
|
+
dateRenderLabel="date-input"
|
|
436
|
+
prevMonthLabel="Previous month"
|
|
437
|
+
nextMonthLabel="Next month"
|
|
438
|
+
timeRenderLabel="time-input"
|
|
439
|
+
invalidDateTimeMessage="whoops"
|
|
440
|
+
defaultValue="totally not a date"
|
|
441
|
+
/>
|
|
442
|
+
)
|
|
443
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
444
|
+
fireEvent.blur(dateInput)
|
|
445
|
+
|
|
446
|
+
await waitFor(() => {
|
|
447
|
+
expect(container).toHaveTextContent('whoops')
|
|
448
|
+
})
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
it('should update error message when value is invalid', async () => {
|
|
452
|
+
const locale = 'en-US'
|
|
453
|
+
const timezone = 'US/Eastern'
|
|
454
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
455
|
+
const props = {
|
|
456
|
+
description: 'date_time',
|
|
457
|
+
dateRenderLabel: 'date-input',
|
|
458
|
+
prevMonthLabel: 'Previous month',
|
|
459
|
+
nextMonthLabel: 'Next month',
|
|
460
|
+
timeRenderLabel: 'time-input',
|
|
461
|
+
invalidDateTimeMessage: 'whoops',
|
|
462
|
+
locale,
|
|
463
|
+
timezone,
|
|
464
|
+
value: dateTime.toISOString()
|
|
465
|
+
}
|
|
466
|
+
const { container, rerender } = render(<DateTimeInput {...props} />)
|
|
467
|
+
expect(container).toHaveTextContent('May 1, 2017 1:30 PM')
|
|
468
|
+
|
|
469
|
+
rerender(<DateTimeInput {...props} value="A very invalid date" />)
|
|
470
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
471
|
+
fireEvent.blur(dateInput)
|
|
472
|
+
|
|
473
|
+
await waitFor(() => {
|
|
474
|
+
expect(container).toHaveTextContent('whoops')
|
|
475
|
+
})
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
it('should show supplied message', async () => {
|
|
479
|
+
const locale = 'en-US'
|
|
480
|
+
const timezone = 'US/Eastern'
|
|
481
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
482
|
+
const props = {
|
|
483
|
+
description: 'date_time',
|
|
484
|
+
dateRenderLabel: 'date-input',
|
|
485
|
+
prevMonthLabel: 'Previous month',
|
|
486
|
+
nextMonthLabel: 'Next month',
|
|
487
|
+
timeRenderLabel: 'time-input',
|
|
488
|
+
invalidDateTimeMessage: 'whoops',
|
|
489
|
+
locale,
|
|
490
|
+
timezone,
|
|
491
|
+
value: dateTime.toISOString()
|
|
492
|
+
}
|
|
493
|
+
const { container, rerender } = render(<DateTimeInput {...props} />)
|
|
494
|
+
expect(container).toHaveTextContent('May 1, 2017 1:30 PM')
|
|
495
|
+
|
|
496
|
+
rerender(
|
|
497
|
+
<DateTimeInput
|
|
498
|
+
{...props}
|
|
499
|
+
messages={[{ text: 'message_text', type: 'success' }]}
|
|
500
|
+
/>
|
|
501
|
+
)
|
|
502
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
503
|
+
fireEvent.blur(dateInput)
|
|
504
|
+
|
|
505
|
+
await waitFor(() => {
|
|
506
|
+
expect(container).toHaveTextContent('May 1, 2017 1:30 PM')
|
|
507
|
+
expect(container).toHaveTextContent('message_text')
|
|
508
|
+
})
|
|
509
|
+
})
|
|
510
|
+
|
|
511
|
+
it('should not show built in message when `showMessages` is false', async () => {
|
|
512
|
+
const locale = 'en-US'
|
|
513
|
+
const timezone = 'US/Eastern'
|
|
514
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
515
|
+
const props = {
|
|
516
|
+
description: 'date_time',
|
|
517
|
+
dateRenderLabel: 'date-input',
|
|
518
|
+
prevMonthLabel: 'Previous month',
|
|
519
|
+
nextMonthLabel: 'Next month',
|
|
520
|
+
timeRenderLabel: 'time-input',
|
|
521
|
+
invalidDateTimeMessage: 'whoops',
|
|
522
|
+
locale,
|
|
523
|
+
timezone,
|
|
524
|
+
value: dateTime.toISOString()
|
|
525
|
+
}
|
|
526
|
+
const { container, rerender } = render(
|
|
527
|
+
<DateTimeInput {...props} showMessages={false} />
|
|
528
|
+
)
|
|
529
|
+
expect(container).not.toHaveTextContent('2017')
|
|
530
|
+
|
|
531
|
+
rerender(
|
|
532
|
+
<DateTimeInput
|
|
533
|
+
{...props}
|
|
534
|
+
showMessages={false}
|
|
535
|
+
messages={[{ text: 'message_text', type: 'success' }]}
|
|
536
|
+
/>
|
|
537
|
+
)
|
|
538
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
539
|
+
|
|
540
|
+
fireEvent.blur(dateInput)
|
|
541
|
+
|
|
542
|
+
await waitFor(() => {
|
|
543
|
+
expect(container).not.toHaveTextContent('2017')
|
|
544
|
+
expect(container).toHaveTextContent('message_text')
|
|
545
|
+
})
|
|
546
|
+
|
|
547
|
+
rerender(
|
|
548
|
+
<DateTimeInput
|
|
549
|
+
{...props}
|
|
550
|
+
messages={[{ text: 'message_text', type: 'success' }]}
|
|
551
|
+
showMessages={true}
|
|
552
|
+
/>
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
fireEvent.blur(screen.getByLabelText('date-input'))
|
|
556
|
+
|
|
557
|
+
await waitFor(() => {
|
|
558
|
+
expect(container).toHaveTextContent('2017')
|
|
559
|
+
expect(container).toHaveTextContent('message_text')
|
|
560
|
+
})
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
it('should read locale and timezone from context', () => {
|
|
564
|
+
const onChange = jest.fn()
|
|
565
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', 'en-US', 'GMT')
|
|
566
|
+
const { container } = render(
|
|
567
|
+
// Africa/Nairobi is GMT +3
|
|
568
|
+
<ApplyLocale locale="fr" timezone="Africa/Nairobi">
|
|
569
|
+
<DateTimeInput
|
|
570
|
+
description="date_time"
|
|
571
|
+
dateRenderLabel="date-input"
|
|
572
|
+
prevMonthLabel="Previous month"
|
|
573
|
+
nextMonthLabel="Next month"
|
|
574
|
+
timeRenderLabel="time-input"
|
|
575
|
+
invalidDateTimeMessage="whoops"
|
|
576
|
+
value={dateTime.toISOString()}
|
|
577
|
+
onChange={onChange}
|
|
578
|
+
/>
|
|
579
|
+
</ApplyLocale>
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
expect(container).toHaveTextContent('lundi 1 mai 2017 20:30')
|
|
583
|
+
})
|
|
584
|
+
|
|
585
|
+
it('should format date according to dateFormat', async () => {
|
|
586
|
+
const onChange = jest.fn()
|
|
587
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', 'en-US', 'GMT')
|
|
588
|
+
const props = {
|
|
589
|
+
description: 'date_time',
|
|
590
|
+
dateRenderLabel: 'date-input',
|
|
591
|
+
prevMonthLabel: 'Previous month',
|
|
592
|
+
nextMonthLabel: 'Next month',
|
|
593
|
+
timeRenderLabel: 'time-input',
|
|
594
|
+
invalidDateTimeMessage: 'whoops',
|
|
595
|
+
value: dateTime.toISOString(),
|
|
596
|
+
onChange
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const { rerender } = render(
|
|
600
|
+
<DateTimeInput
|
|
601
|
+
{...props}
|
|
602
|
+
dateFormat="l" // localized numeric date like 9/4/2017
|
|
603
|
+
/>
|
|
604
|
+
)
|
|
605
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
606
|
+
|
|
607
|
+
expect(dateInput).toHaveValue('5/1/2017')
|
|
608
|
+
|
|
609
|
+
rerender(<DateTimeInput {...props} dateFormat="yyyy MMMM" />)
|
|
610
|
+
|
|
611
|
+
fireEvent.blur(screen.getByLabelText('date-input'))
|
|
612
|
+
|
|
613
|
+
await waitFor(() => {
|
|
614
|
+
expect(dateInput).toHaveValue('2017 May')
|
|
615
|
+
})
|
|
616
|
+
})
|
|
617
|
+
|
|
618
|
+
it('should format bottom message according to messageFormat', async () => {
|
|
619
|
+
const onChange = jest.fn()
|
|
620
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', 'en-US', 'GMT')
|
|
621
|
+
const props = {
|
|
622
|
+
description: 'date_time',
|
|
623
|
+
dateRenderLabel: 'date-input',
|
|
624
|
+
prevMonthLabel: 'Previous month',
|
|
625
|
+
nextMonthLabel: 'Next month',
|
|
626
|
+
timeRenderLabel: 'time-input',
|
|
627
|
+
invalidDateTimeMessage: 'whoops',
|
|
628
|
+
value: dateTime.toISOString(),
|
|
629
|
+
onChange,
|
|
630
|
+
locale: 'en-US',
|
|
631
|
+
timezone: 'US/Eastern'
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
const { container, rerender } = render(<DateTimeInput {...props} />)
|
|
635
|
+
expect(container).toHaveTextContent('Monday, May 1, 2017 1:30 PM')
|
|
636
|
+
|
|
637
|
+
rerender(<DateTimeInput {...props} messageFormat="l, LT" />)
|
|
638
|
+
fireEvent.blur(screen.getByLabelText('date-input'))
|
|
639
|
+
|
|
640
|
+
await waitFor(() => {
|
|
641
|
+
expect(container).toHaveTextContent('5/1/2017, 1:30 PM')
|
|
642
|
+
})
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
it('should update Date and Time inputs when value prop changes', async () => {
|
|
646
|
+
const locale = 'en-US'
|
|
647
|
+
const timezone = 'US/Eastern'
|
|
648
|
+
const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone)
|
|
649
|
+
const props = {
|
|
650
|
+
description: 'date_time',
|
|
651
|
+
dateRenderLabel: 'date-input',
|
|
652
|
+
prevMonthLabel: 'Previous month',
|
|
653
|
+
nextMonthLabel: 'Next month',
|
|
654
|
+
timeRenderLabel: 'time-input',
|
|
655
|
+
invalidDateTimeMessage: 'whoops',
|
|
656
|
+
locale,
|
|
657
|
+
timezone,
|
|
658
|
+
value: dateTime.toISOString()
|
|
659
|
+
}
|
|
660
|
+
const { container, rerender } = render(<DateTimeInput {...props} />)
|
|
661
|
+
expect(container).toHaveTextContent('May 1, 2017 1:30 PM')
|
|
662
|
+
|
|
663
|
+
const newDateStr = '2022-03-29T19:00Z'
|
|
664
|
+
const newDateTime = DateTime.parse(newDateStr, locale, timezone)
|
|
665
|
+
|
|
666
|
+
rerender(<DateTimeInput {...props} value={newDateStr} />)
|
|
667
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
668
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
669
|
+
|
|
670
|
+
fireEvent.blur(dateInput)
|
|
671
|
+
|
|
672
|
+
await waitFor(() => {
|
|
673
|
+
expect(dateInput).toHaveValue(newDateTime.format('LL'))
|
|
674
|
+
expect(timeInput).toHaveValue(newDateTime.format('LT'))
|
|
675
|
+
})
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
it("should throw warning if initialTimeForNewDate prop's value is not HH:MM", async () => {
|
|
679
|
+
const initialTimeForNewDate = 'WRONG_FORMAT'
|
|
680
|
+
|
|
681
|
+
render(
|
|
682
|
+
<DateTimeInput
|
|
683
|
+
description="date_time"
|
|
684
|
+
dateRenderLabel="date-input"
|
|
685
|
+
prevMonthLabel="Previous month"
|
|
686
|
+
nextMonthLabel="Next month"
|
|
687
|
+
timeRenderLabel="time-input"
|
|
688
|
+
invalidDateTimeMessage="whoops"
|
|
689
|
+
locale={'en-US'}
|
|
690
|
+
timezone={'US/Eastern'}
|
|
691
|
+
initialTimeForNewDate={initialTimeForNewDate}
|
|
692
|
+
/>
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
expect(consoleErrorMock.mock.calls[0][2]).toEqual(
|
|
696
|
+
expect.stringContaining(
|
|
697
|
+
`Invalid prop \`initialTimeForNewDate\` \`${initialTimeForNewDate}\` supplied to \`DateTimeInput\`, expected a HH:MM formatted string.`
|
|
698
|
+
)
|
|
699
|
+
)
|
|
700
|
+
})
|
|
701
|
+
|
|
702
|
+
it("should throw warning if date select and initialTimeForNewDate prop's value is not HH:MM", async () => {
|
|
703
|
+
const initialTimeForNewDate = 'WRONG_FORMAT'
|
|
704
|
+
|
|
705
|
+
render(
|
|
706
|
+
<DateTimeInput
|
|
707
|
+
description="date_time"
|
|
708
|
+
dateRenderLabel="date-input"
|
|
709
|
+
prevMonthLabel="Previous month"
|
|
710
|
+
nextMonthLabel="Next month"
|
|
711
|
+
timeRenderLabel="time-input"
|
|
712
|
+
invalidDateTimeMessage="whoops"
|
|
713
|
+
locale={'en-US'}
|
|
714
|
+
timezone={'US/Eastern'}
|
|
715
|
+
initialTimeForNewDate={initialTimeForNewDate}
|
|
716
|
+
/>
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
720
|
+
|
|
721
|
+
fireEvent.change(dateInput, { target: { value: 'May 1, 2017' } })
|
|
722
|
+
fireEvent.keyDown(dateInput, { key: 'Enter', code: 'Enter' })
|
|
723
|
+
fireEvent.blur(dateInput)
|
|
724
|
+
|
|
725
|
+
await waitFor(() => {
|
|
726
|
+
expect(consoleErrorMock.mock.calls[0][0]).toBe(
|
|
727
|
+
`Warning: [DateTimeInput] initialTimeForNewDate prop is not in the correct format. Please use HH:MM format.`
|
|
728
|
+
)
|
|
729
|
+
})
|
|
730
|
+
})
|
|
731
|
+
|
|
732
|
+
it('should throw warning if initialTimeForNewDate prop hour and minute values are not in interval', async () => {
|
|
733
|
+
const initialTimeForNewDate = '99:99'
|
|
734
|
+
|
|
735
|
+
render(
|
|
736
|
+
<DateTimeInput
|
|
737
|
+
description="date_time"
|
|
738
|
+
dateRenderLabel="date-input"
|
|
739
|
+
prevMonthLabel="Previous month"
|
|
740
|
+
nextMonthLabel="Next month"
|
|
741
|
+
timeRenderLabel="time-input"
|
|
742
|
+
invalidDateTimeMessage="whoops"
|
|
743
|
+
locale={'en-US'}
|
|
744
|
+
timezone={'US/Eastern'}
|
|
745
|
+
initialTimeForNewDate={initialTimeForNewDate}
|
|
746
|
+
/>
|
|
747
|
+
)
|
|
748
|
+
const dateInput = screen.getByLabelText('date-input')
|
|
749
|
+
|
|
750
|
+
fireEvent.change(dateInput, { target: { value: 'May 1, 2017' } })
|
|
751
|
+
fireEvent.keyDown(dateInput, { key: 'Enter', code: 'Enter' })
|
|
752
|
+
fireEvent.blur(dateInput)
|
|
753
|
+
|
|
754
|
+
await waitFor(() => {
|
|
755
|
+
expect(consoleErrorMock.mock.calls[0][0]).toEqual(
|
|
756
|
+
expect.stringContaining(
|
|
757
|
+
`Warning: [DateTimeInput] 0 <= hour < 24 and 0 <= minute < 60 for initialTimeForNewDate prop.`
|
|
758
|
+
)
|
|
759
|
+
)
|
|
760
|
+
})
|
|
761
|
+
})
|
|
762
|
+
|
|
763
|
+
it('should initial render prefer defaultValue time over initialTimeForNewDate', async () => {
|
|
764
|
+
const locale = 'en-US'
|
|
765
|
+
const timezone = 'US/Eastern'
|
|
766
|
+
const initialTimeForNewDate = '16:16'
|
|
767
|
+
const defaultValue = '2018-01-18T13:30'
|
|
768
|
+
|
|
769
|
+
const { container } = render(
|
|
770
|
+
<DateTimeInput
|
|
771
|
+
description="date_time"
|
|
772
|
+
dateRenderLabel="date-input"
|
|
773
|
+
prevMonthLabel="Previous month"
|
|
774
|
+
nextMonthLabel="Next month"
|
|
775
|
+
timeRenderLabel="time-input"
|
|
776
|
+
invalidDateTimeMessage="whoops"
|
|
777
|
+
defaultValue={defaultValue}
|
|
778
|
+
locale={locale}
|
|
779
|
+
timezone={timezone}
|
|
780
|
+
initialTimeForNewDate={initialTimeForNewDate}
|
|
781
|
+
/>
|
|
782
|
+
)
|
|
783
|
+
const timeInput = screen.getByLabelText('time-input')
|
|
784
|
+
|
|
785
|
+
expect(timeInput).toHaveValue('1:30 PM')
|
|
786
|
+
expect(container).toHaveTextContent('Thursday, January 18, 2018 1:30 PM')
|
|
787
|
+
})
|
|
232
788
|
})
|