Skip to content

Commit b499fdc

Browse files
authored
[6.x] Improve date timezone tests (#11576)
1 parent 4cf2077 commit b499fdc

File tree

2 files changed

+212
-125
lines changed

2 files changed

+212
-125
lines changed

resources/js/tests/components/fieldtypes/DateFieldtype.test.js

+176-107
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,16 @@ window.matchMedia = () => ({
1111
addEventListener: () => {},
1212
});
1313

14-
process.env.TZ = 'America/New_York';
14+
let originalDate;
15+
function setMockDate(dateString) {
16+
originalDate = Date; // Store the original Date object
17+
global.Date = class extends Date {
18+
constructor(...args) {
19+
if (args.length) return super(...args);
20+
return new originalDate(dateString);
21+
}
22+
};
23+
}
1524

1625
const makeDateField = (props = {}) => {
1726
return mount(DateFieldtype, {
@@ -48,171 +57,231 @@ const makeDateField = (props = {}) => {
4857
});
4958
};
5059

51-
test('date and time is localized to the users timezone', async () => {
52-
const dateField = makeDateField({
53-
value: { date: '2025-01-01', time: '15:00' },
54-
});
60+
test.each([
61+
['UTC', '2025-12-25', '02:23'],
62+
['America/New_York', '2025-12-24', '21:23'],
63+
])('date and time is localized to the users timezone (%s)', async (tz, expectedDate, expectedTime) => {
64+
process.env.TZ = tz;
5565

56-
expect(dateField.vm.localValue).toMatchObject({
57-
date: '2025-01-01',
58-
time: '10:00',
59-
});
60-
});
61-
62-
test('date can be updated', async () => {
6366
const dateField = makeDateField({
64-
value: { date: '2025-01-01', time: '10:00' },
67+
value: { date: '2025-12-25', time: '02:23' },
6568
});
6669

67-
await dateField.vm.setLocalDate('2024-12-10');
68-
69-
expect(dateField.emitted('update:value')[0]).toEqual([
70-
{
71-
date: '2024-12-10',
72-
time: '05:00',
73-
},
74-
]);
75-
7670
expect(dateField.vm.localValue).toMatchObject({
77-
date: '2024-12-10',
78-
time: '00:00',
71+
date: expectedDate,
72+
time: expectedTime,
7973
});
8074
});
8175

82-
test('date can be updated without resetting the time when time_enabled is true', async () => {
76+
test.each([
77+
{
78+
tz: 'UTC',
79+
expectedEmittedValue: { date: '2024-12-19', time: '00:00' },
80+
expectedLocalValue: { date: '2024-12-19', time: '00:00' },
81+
},
82+
{
83+
tz: 'America/New_York',
84+
expectedEmittedValue: { date: '2024-12-19', time: '05:00' },
85+
expectedLocalValue: { date: '2024-12-19', time: '00:00' },
86+
},
87+
])('date can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
88+
process.env.TZ = tz;
89+
8390
const dateField = makeDateField({
84-
config: {
85-
earliest_date: { date: null, time: null },
86-
latest_date: { date: null, time: null },
87-
time_enabled: true,
88-
},
89-
value: { date: '2025-01-01', time: '10:00' },
91+
value: { date: '2025-12-25', time: '02:13' },
9092
});
9193

92-
await dateField.vm.setLocalDate('2024-12-10');
93-
94-
expect(dateField.emitted('update:value')[0]).toEqual([
95-
{
96-
date: '2024-12-10',
97-
time: '10:00',
98-
},
99-
]);
94+
await dateField.vm.setLocalDate('2024-12-19');
10095

101-
expect(dateField.vm.localValue).toMatchObject({
102-
date: '2024-12-10',
103-
time: '05:00',
104-
});
96+
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
97+
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
10598
});
10699

107-
test('time can be updated', async () => {
100+
test.each([
101+
{
102+
tz: 'UTC',
103+
expectedEmittedValue: { date: '2024-12-19', time: '02:13' },
104+
expectedLocalValue: { date: '2024-12-19', time: '02:13' },
105+
},
106+
{
107+
tz: 'America/New_York',
108+
expectedEmittedValue: { date: '2024-12-20', time: '02:13' },
109+
expectedLocalValue: { date: '2024-12-19', time: '21:13' },
110+
},
111+
])(
112+
'date can be updated without resetting the time when time_enabled is true ($tz)',
113+
async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
114+
process.env.TZ = tz;
115+
116+
const dateField = makeDateField({
117+
config: {
118+
earliest_date: { date: null, time: null },
119+
latest_date: { date: null, time: null },
120+
time_enabled: true,
121+
},
122+
value: { date: '2025-12-25', time: '02:13' },
123+
});
124+
125+
await dateField.vm.setLocalDate('2024-12-19');
126+
127+
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
128+
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
129+
},
130+
);
131+
132+
test.each([
133+
{
134+
tz: 'UTC',
135+
expectedEmittedValue: { date: '2025-12-25', time: '23:11' },
136+
expectedLocalValue: { date: '2025-12-25', time: '23:11' },
137+
},
138+
{
139+
tz: 'America/New_York',
140+
expectedEmittedValue: { date: '2025-12-25', time: '04:11' },
141+
expectedLocalValue: { date: '2025-12-24', time: '23:11' },
142+
},
143+
])('time can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
144+
process.env.TZ = tz;
145+
108146
const dateField = makeDateField({
109147
config: {
110148
earliest_date: { date: null, time: null },
111149
latest_date: { date: null, time: null },
112150
time_enabled: true,
113151
},
114-
value: { date: '2025-01-01', time: '15:00' },
152+
value: { date: '2025-12-25', time: '02:13' },
115153
});
116154

117155
await dateField.vm.setLocalTime('23:11');
118156

119-
expect(dateField.emitted('update:value')[0]).toEqual([
120-
{
121-
date: '2025-01-02',
122-
time: '04:11',
123-
},
124-
]);
125-
126-
expect(dateField.vm.localValue).toMatchObject({
127-
date: '2025-01-01',
128-
time: '23:11',
129-
});
157+
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
158+
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
130159
});
131160

132-
test('time with seconds can be updated', async () => {
161+
test.each([
162+
{
163+
tz: 'UTC',
164+
expectedEmittedValue: { date: '2025-12-25', time: '23:11:29' },
165+
expectedLocalValue: { date: '2025-12-25', time: '23:11:29' },
166+
},
167+
{
168+
tz: 'America/New_York',
169+
expectedEmittedValue: { date: '2025-12-25', time: '04:11:29' },
170+
expectedLocalValue: { date: '2025-12-24', time: '23:11:29' },
171+
},
172+
])('time with seconds can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
173+
process.env.TZ = tz;
174+
133175
const dateField = makeDateField({
134176
config: {
135177
earliest_date: { date: null, time: null },
136178
latest_date: { date: null, time: null },
137179
time_seconds_enabled: true,
138180
},
139-
value: { date: '2025-01-01', time: '15:00:00' },
181+
value: { date: '2025-12-25', time: '02:13:00' },
140182
});
141183

142-
await dateField.vm.setLocalTime('23:11:11');
143-
144-
expect(dateField.emitted('update:value')[0]).toEqual([
145-
{
146-
date: '2025-01-02',
147-
time: '04:11:11',
148-
},
149-
]);
184+
await dateField.vm.setLocalTime('23:11:29');
150185

151-
expect(dateField.vm.localValue).toMatchObject({
152-
date: '2025-01-01',
153-
time: '23:11:11',
154-
});
186+
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
187+
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
155188
});
156189

157-
test('date range can be updated', async () => {
190+
test.each([
191+
{
192+
tz: 'UTC',
193+
expectedEmittedValue: {
194+
start: { date: '2025-01-12', time: '00:00' },
195+
end: { date: '2025-01-14', time: '23:59' },
196+
},
197+
expectedLocalValue: {
198+
start: { date: '2025-01-12', time: '00:00' },
199+
end: { date: '2025-01-14', time: '23:59' },
200+
},
201+
},
202+
{
203+
tz: 'America/New_York',
204+
expectedEmittedValue: {
205+
start: { date: '2025-01-12', time: '05:00' },
206+
end: { date: '2025-01-15', time: '04:59' },
207+
},
208+
expectedLocalValue: {
209+
start: { date: '2025-01-12', time: '00:00' },
210+
end: { date: '2025-01-14', time: '23:59' },
211+
},
212+
},
213+
])('date range can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
214+
process.env.TZ = tz;
215+
158216
const dateField = makeDateField({
159217
config: {
160218
earliest_date: { date: null, time: null },
161219
latest_date: { date: null, time: null },
162220
mode: 'range',
163221
},
164222
value: {
165-
start: { date: '2025-01-01', time: '05:00' },
166-
end: { date: '2025-01-08', time: '04:59' },
223+
start: { date: '2025-12-25', time: '02:13' },
224+
end: { date: '2025-12-28', time: '09:04' },
167225
},
168226
});
169227

170228
await dateField.vm.setLocalDate({
171-
start: '2025-01-01',
172-
end: '2025-01-30',
229+
start: '2025-01-12',
230+
end: '2025-01-14',
173231
});
174232

175-
expect(dateField.emitted('update:value')[0]).toEqual([
176-
{
177-
start: { date: '2025-01-01', time: '05:00' },
178-
end: { date: '2025-01-31', time: '04:59' },
179-
},
180-
]);
181-
182-
expect(dateField.vm.localValue).toMatchObject({
183-
start: { date: '2025-01-01', time: '00:00' },
184-
end: { date: '2025-01-30', time: '23:59' },
185-
});
233+
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
234+
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
186235
});
187236

188-
test('required date range field with null value is automatically populated', async () => {
189-
const dateField = makeDateField({
190-
config: {
191-
earliest_date: { date: null, time: null },
192-
latest_date: { date: null, time: null },
193-
mode: 'range',
194-
required: true,
195-
},
196-
value: null,
197-
});
237+
test.each([
238+
[
239+
'UTC',
240+
{ start: { date: '2021-12-25', time: '00:00' }, end: { date: '2021-12-25', time: '23:59' } },
241+
{ start: { date: '2021-12-25', time: '00:00' }, end: { date: '2021-12-25', time: '23:59' } },
242+
],
243+
[
244+
'America/New_York',
245+
{ start: { date: '2021-12-25', time: '05:00' }, end: { date: '2021-12-26', time: '04:59' } },
246+
{ start: { date: '2021-12-25', time: '00:00' }, end: { date: '2021-12-25', time: '23:59' } },
247+
],
248+
])(
249+
'required date range field with null value is automatically populated (%s)',
250+
async (tz, expectedEmittedValue, expectedLocalValue) => {
251+
process.env.TZ = tz;
252+
253+
setMockDate('2021-12-25T12:13:14Z');
254+
255+
const dateField = makeDateField({
256+
config: {
257+
earliest_date: { date: null, time: null },
258+
latest_date: { date: null, time: null },
259+
mode: 'range',
260+
required: true,
261+
},
262+
value: null,
263+
});
198264

199-
const today = new Date().toISOString().split('T')[0];
265+
await dateField.vm.$nextTick();
266+
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
267+
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
268+
},
269+
);
200270

201-
expect(dateField.vm.localValue).toMatchObject({
202-
start: { date: today, time: '00:00' },
203-
end: { date: today, time: '23:59' },
204-
});
205-
});
271+
test.each([
272+
['UTC', '2025-12-25', '02:15'],
273+
['America/New_York', '2025-12-24', '21:15'],
274+
])('local time is updated when value prop is updated (%s)', async (tz, expectedDate, expectedTime) => {
275+
process.env.TZ = tz;
206276

207-
test('local time is updated when value prop is updated', async () => {
208277
const dateField = makeDateField({
209-
value: { date: '2025-01-01', time: '15:00' },
278+
value: { date: '1984-01-01', time: '15:00' },
210279
});
211280

212-
await dateField.setProps({ value: { date: '2025-01-01', time: '10:00' } });
281+
await dateField.setProps({ value: { date: '2025-12-25', time: '02:15' } });
213282

214283
expect(dateField.vm.localValue).toMatchObject({
215-
date: '2025-01-01',
216-
time: '05:00',
284+
date: expectedDate,
285+
time: expectedTime,
217286
});
218287
});

0 commit comments

Comments
 (0)