Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 176 additions & 107 deletions resources/js/tests/components/fieldtypes/DateFieldtype.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@ window.matchMedia = () => ({
addEventListener: () => {},
});

process.env.TZ = 'America/New_York';
let originalDate;
function setMockDate(dateString) {
originalDate = Date; // Store the original Date object
global.Date = class extends Date {
constructor(...args) {
if (args.length) return super(...args);
return new originalDate(dateString);
}
};
}

const makeDateField = (props = {}) => {
return mount(DateFieldtype, {
Expand Down Expand Up @@ -48,171 +57,231 @@ const makeDateField = (props = {}) => {
});
};

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

expect(dateField.vm.localValue).toMatchObject({
date: '2025-01-01',
time: '10:00',
});
});

test('date can be updated', async () => {
const dateField = makeDateField({
value: { date: '2025-01-01', time: '10:00' },
value: { date: '2025-12-25', time: '02:23' },
});

await dateField.vm.setLocalDate('2024-12-10');

expect(dateField.emitted('update:value')[0]).toEqual([
{
date: '2024-12-10',
time: '05:00',
},
]);

expect(dateField.vm.localValue).toMatchObject({
date: '2024-12-10',
time: '00:00',
date: expectedDate,
time: expectedTime,
});
});

test('date can be updated without resetting the time when time_enabled is true', async () => {
test.each([
{
tz: 'UTC',
expectedEmittedValue: { date: '2024-12-19', time: '00:00' },
expectedLocalValue: { date: '2024-12-19', time: '00:00' },
},
{
tz: 'America/New_York',
expectedEmittedValue: { date: '2024-12-19', time: '05:00' },
expectedLocalValue: { date: '2024-12-19', time: '00:00' },
},
])('date can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
process.env.TZ = tz;

const dateField = makeDateField({
config: {
earliest_date: { date: null, time: null },
latest_date: { date: null, time: null },
time_enabled: true,
},
value: { date: '2025-01-01', time: '10:00' },
value: { date: '2025-12-25', time: '02:13' },
});

await dateField.vm.setLocalDate('2024-12-10');

expect(dateField.emitted('update:value')[0]).toEqual([
{
date: '2024-12-10',
time: '10:00',
},
]);
await dateField.vm.setLocalDate('2024-12-19');

expect(dateField.vm.localValue).toMatchObject({
date: '2024-12-10',
time: '05:00',
});
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
});

test('time can be updated', async () => {
test.each([
{
tz: 'UTC',
expectedEmittedValue: { date: '2024-12-19', time: '02:13' },
expectedLocalValue: { date: '2024-12-19', time: '02:13' },
},
{
tz: 'America/New_York',
expectedEmittedValue: { date: '2024-12-20', time: '02:13' },
expectedLocalValue: { date: '2024-12-19', time: '21:13' },
},
])(
'date can be updated without resetting the time when time_enabled is true ($tz)',
async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
process.env.TZ = tz;

const dateField = makeDateField({
config: {
earliest_date: { date: null, time: null },
latest_date: { date: null, time: null },
time_enabled: true,
},
value: { date: '2025-12-25', time: '02:13' },
});

await dateField.vm.setLocalDate('2024-12-19');

expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
},
);

test.each([
{
tz: 'UTC',
expectedEmittedValue: { date: '2025-12-25', time: '23:11' },
expectedLocalValue: { date: '2025-12-25', time: '23:11' },
},
{
tz: 'America/New_York',
expectedEmittedValue: { date: '2025-12-25', time: '04:11' },
expectedLocalValue: { date: '2025-12-24', time: '23:11' },
},
])('time can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
process.env.TZ = tz;

const dateField = makeDateField({
config: {
earliest_date: { date: null, time: null },
latest_date: { date: null, time: null },
time_enabled: true,
},
value: { date: '2025-01-01', time: '15:00' },
value: { date: '2025-12-25', time: '02:13' },
});

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

expect(dateField.emitted('update:value')[0]).toEqual([
{
date: '2025-01-02',
time: '04:11',
},
]);

expect(dateField.vm.localValue).toMatchObject({
date: '2025-01-01',
time: '23:11',
});
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
});

test('time with seconds can be updated', async () => {
test.each([
{
tz: 'UTC',
expectedEmittedValue: { date: '2025-12-25', time: '23:11:29' },
expectedLocalValue: { date: '2025-12-25', time: '23:11:29' },
},
{
tz: 'America/New_York',
expectedEmittedValue: { date: '2025-12-25', time: '04:11:29' },
expectedLocalValue: { date: '2025-12-24', time: '23:11:29' },
},
])('time with seconds can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
process.env.TZ = tz;

const dateField = makeDateField({
config: {
earliest_date: { date: null, time: null },
latest_date: { date: null, time: null },
time_seconds_enabled: true,
},
value: { date: '2025-01-01', time: '15:00:00' },
value: { date: '2025-12-25', time: '02:13:00' },
});

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

expect(dateField.emitted('update:value')[0]).toEqual([
{
date: '2025-01-02',
time: '04:11:11',
},
]);
await dateField.vm.setLocalTime('23:11:29');

expect(dateField.vm.localValue).toMatchObject({
date: '2025-01-01',
time: '23:11:11',
});
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
});

test('date range can be updated', async () => {
test.each([
{
tz: 'UTC',
expectedEmittedValue: {
start: { date: '2025-01-12', time: '00:00' },
end: { date: '2025-01-14', time: '23:59' },
},
expectedLocalValue: {
start: { date: '2025-01-12', time: '00:00' },
end: { date: '2025-01-14', time: '23:59' },
},
},
{
tz: 'America/New_York',
expectedEmittedValue: {
start: { date: '2025-01-12', time: '05:00' },
end: { date: '2025-01-15', time: '04:59' },
},
expectedLocalValue: {
start: { date: '2025-01-12', time: '00:00' },
end: { date: '2025-01-14', time: '23:59' },
},
},
])('date range can be updated ($tz)', async ({ tz, expectedEmittedValue, expectedLocalValue }) => {
process.env.TZ = tz;

const dateField = makeDateField({
config: {
earliest_date: { date: null, time: null },
latest_date: { date: null, time: null },
mode: 'range',
},
value: {
start: { date: '2025-01-01', time: '05:00' },
end: { date: '2025-01-08', time: '04:59' },
start: { date: '2025-12-25', time: '02:13' },
end: { date: '2025-12-28', time: '09:04' },
},
});

await dateField.vm.setLocalDate({
start: '2025-01-01',
end: '2025-01-30',
start: '2025-01-12',
end: '2025-01-14',
});

expect(dateField.emitted('update:value')[0]).toEqual([
{
start: { date: '2025-01-01', time: '05:00' },
end: { date: '2025-01-31', time: '04:59' },
},
]);

expect(dateField.vm.localValue).toMatchObject({
start: { date: '2025-01-01', time: '00:00' },
end: { date: '2025-01-30', time: '23:59' },
});
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
});

test('required date range field with null value is automatically populated', async () => {
const dateField = makeDateField({
config: {
earliest_date: { date: null, time: null },
latest_date: { date: null, time: null },
mode: 'range',
required: true,
},
value: null,
});
test.each([
[
'UTC',
{ start: { date: '2021-12-25', time: '00:00' }, end: { date: '2021-12-25', time: '23:59' } },
{ start: { date: '2021-12-25', time: '00:00' }, end: { date: '2021-12-25', time: '23:59' } },
],
[
'America/New_York',
{ start: { date: '2021-12-25', time: '05:00' }, end: { date: '2021-12-26', time: '04:59' } },
{ start: { date: '2021-12-25', time: '00:00' }, end: { date: '2021-12-25', time: '23:59' } },
],
])(
'required date range field with null value is automatically populated (%s)',
async (tz, expectedEmittedValue, expectedLocalValue) => {
process.env.TZ = tz;

setMockDate('2021-12-25T12:13:14Z');

const dateField = makeDateField({
config: {
earliest_date: { date: null, time: null },
latest_date: { date: null, time: null },
mode: 'range',
required: true,
},
value: null,
});

const today = new Date().toISOString().split('T')[0];
await dateField.vm.$nextTick();
expect(dateField.emitted('update:value')[0][0]).toEqual(expectedEmittedValue);
expect(dateField.vm.localValue).toMatchObject(expectedLocalValue);
},
);

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

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

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

expect(dateField.vm.localValue).toMatchObject({
date: '2025-01-01',
time: '05:00',
date: expectedDate,
time: expectedTime,
});
});
Loading