255 lines
8.4 KiB
JavaScript
255 lines
8.4 KiB
JavaScript
/**
|
|
* Static Node tests for timezone-aware date filtering in odata-helpers.js.
|
|
*
|
|
* These tests exercise buildDateFilter / localDateStringToInstant / processDateRange
|
|
* with known local dates and assert that the produced UTC ISO boundaries are correct.
|
|
*
|
|
* Run with:
|
|
* node tests/date-filter-timezone.test.js
|
|
*/
|
|
const assert = require('assert');
|
|
const {
|
|
buildDateFilter,
|
|
processDateRange,
|
|
startOfDay,
|
|
endOfDay,
|
|
localDateStringToInstant,
|
|
getEffectiveTimeZone
|
|
} = require('../utils/odata-helpers');
|
|
|
|
function assertBoundary(actualISO, expectedISO, label) {
|
|
if (actualISO !== expectedISO) {
|
|
throw new Error(`${label}: expected ${expectedISO}, got ${actualISO}`);
|
|
}
|
|
}
|
|
|
|
// We control the timezone via MS_TIMEZONE env var before requiring config.
|
|
// For these tests we set America/New_York explicitly.
|
|
assert.strictEqual(getEffectiveTimeZone('America/New_York'), 'America/New_York', 'IANA timezone should pass through');
|
|
assert.strictEqual(getEffectiveTimeZone('Eastern Standard Time'), 'America/New_York', 'Windows timezone should map to IANA');
|
|
|
|
// Test 1: dateFrom/dateTo as plain date strings in America/New_York (EDT).
|
|
// 2024-06-21 EDT is UTC-4, so local midnight is 2024-06-21T04:00:00.000Z,
|
|
// and end-of-day is 2024-06-22T03:59:59.999Z.
|
|
{
|
|
const conditions = buildDateFilter('2024-06-21', '2024-06-21', null, 'America/New_York');
|
|
console.log('Test 1 conditions (NY EDT):', conditions);
|
|
assert.strictEqual(conditions.length, 2, 'should produce two conditions');
|
|
assertBoundary(
|
|
conditions[0],
|
|
'receivedDateTime ge 2024-06-21T04:00:00.000Z',
|
|
'Test 1 start of local day in EDT'
|
|
);
|
|
assertBoundary(
|
|
conditions[1],
|
|
'receivedDateTime le 2024-06-22T03:59:59.999Z',
|
|
'Test 1 end of local day in EDT'
|
|
);
|
|
}
|
|
|
|
// Test 2: Plain date strings in America/New_York during EST (UTC-5).
|
|
{
|
|
const conditions = buildDateFilter('2024-01-15', '2024-01-15', null, 'America/New_York');
|
|
console.log('Test 2 conditions (NY EST):', conditions);
|
|
assertBoundary(
|
|
conditions[0],
|
|
'receivedDateTime ge 2024-01-15T05:00:00.000Z',
|
|
'Test 2 start of local day in EST'
|
|
);
|
|
assertBoundary(
|
|
conditions[1],
|
|
'receivedDateTime le 2024-01-16T04:59:59.999Z',
|
|
'Test 2 end of local day in EST'
|
|
);
|
|
}
|
|
|
|
// Test 3: Plain date strings in Pacific Time during PDT (UTC-7).
|
|
{
|
|
const conditions = buildDateFilter('2024-06-21', '2024-06-21', null, 'America/Los_Angeles');
|
|
console.log('Test 3 conditions (LA PDT):', conditions);
|
|
assertBoundary(
|
|
conditions[0],
|
|
'receivedDateTime ge 2024-06-21T07:00:00.000Z',
|
|
'Test 3 start of local day in PDT'
|
|
);
|
|
assertBoundary(
|
|
conditions[1],
|
|
'receivedDateTime le 2024-06-22T06:59:59.999Z',
|
|
'Test 3 end of local day in PDT'
|
|
);
|
|
}
|
|
|
|
// Test 4: ISO strings with explicit offsets are respected as-is.
|
|
{
|
|
const conditions = buildDateFilter('2024-06-21T08:00:00-04:00', '2024-06-21T18:00:00-04:00', null, 'America/New_York');
|
|
console.log('Test 4 conditions (offset provided):', conditions);
|
|
assertBoundary(
|
|
conditions[0],
|
|
'receivedDateTime ge 2024-06-21T12:00:00.000Z',
|
|
'Test 4 explicit offset fromDate'
|
|
);
|
|
assertBoundary(
|
|
conditions[1],
|
|
'receivedDateTime le 2024-06-21T22:00:00.000Z',
|
|
'Test 4 explicit offset toDate'
|
|
);
|
|
}
|
|
|
|
// Test 5: Windows timezone name should map correctly.
|
|
{
|
|
const conditions = buildDateFilter('2024-06-21', '2024-06-21', null, 'Pacific Standard Time');
|
|
console.log('Test 5 conditions (Windows PST in summer -> PDT):', conditions);
|
|
assertBoundary(
|
|
conditions[0],
|
|
'receivedDateTime ge 2024-06-21T07:00:00.000Z',
|
|
'Test 5 Windows Pacific start'
|
|
);
|
|
}
|
|
|
|
// Test 6: dateRange='today' boundary for a known UTC instant.
|
|
// Force "now" by passing a specific date into processDateRange indirectly via startOfDay.
|
|
// We instead test processDateRange by stubbing Date in a narrow scope.
|
|
{
|
|
const savedDate = Date;
|
|
const fixedNow = new Date('2024-06-21T02:30:00.000Z'); // 2024-06-20 22:30 EDT
|
|
global.Date = class extends savedDate {
|
|
constructor(...args) {
|
|
if (args.length === 0) {
|
|
super(fixedNow);
|
|
} else {
|
|
super(...args);
|
|
}
|
|
}
|
|
static now() { return fixedNow.getTime(); }
|
|
};
|
|
// Reload helpers so the new Date constructor is used.
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
const helpers = require('../utils/odata-helpers');
|
|
|
|
const range = helpers.processDateRange('today', 'America/New_York');
|
|
console.log('Test 6 today range:', range);
|
|
assertBoundary(
|
|
range.from.toISOString(),
|
|
'2024-06-20T04:00:00.000Z',
|
|
'Test 6 today start in EDT (local date is 2024-06-20)'
|
|
);
|
|
assertBoundary(
|
|
range.to.toISOString(),
|
|
'2024-06-21T03:59:59.999Z',
|
|
'Test 6 today end in EDT'
|
|
);
|
|
|
|
global.Date = savedDate;
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
}
|
|
|
|
// Test 7: dateRange='yesterday' for the same fixed EDT instant.
|
|
{
|
|
const savedDate = Date;
|
|
const fixedNow = new Date('2024-06-21T02:30:00.000Z');
|
|
global.Date = class extends savedDate {
|
|
constructor(...args) {
|
|
if (args.length === 0) {
|
|
super(fixedNow);
|
|
} else {
|
|
super(...args);
|
|
}
|
|
}
|
|
static now() { return fixedNow.getTime(); }
|
|
};
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
const helpers = require('../utils/odata-helpers');
|
|
|
|
const range = helpers.processDateRange('yesterday', 'America/New_York');
|
|
console.log('Test 7 yesterday range:', range);
|
|
assertBoundary(
|
|
range.from.toISOString(),
|
|
'2024-06-19T04:00:00.000Z',
|
|
'Test 7 yesterday start in EDT'
|
|
);
|
|
assertBoundary(
|
|
range.to.toISOString(),
|
|
'2024-06-20T03:59:59.999Z',
|
|
'Test 7 yesterday end in EDT'
|
|
);
|
|
|
|
global.Date = savedDate;
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
}
|
|
|
|
// Test 8: dateRange='thisweek' (Sunday-based) in EDT around the same instant.
|
|
// Local date is Thursday 2024-06-20, so Sunday is 2024-06-16.
|
|
{
|
|
const savedDate = Date;
|
|
const fixedNow = new Date('2024-06-21T02:30:00.000Z');
|
|
global.Date = class extends savedDate {
|
|
constructor(...args) {
|
|
if (args.length === 0) {
|
|
super(fixedNow);
|
|
} else {
|
|
super(...args);
|
|
}
|
|
}
|
|
static now() { return fixedNow.getTime(); }
|
|
};
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
const helpers = require('../utils/odata-helpers');
|
|
|
|
const range = helpers.processDateRange('thisweek', 'America/New_York');
|
|
console.log('Test 8 thisweek range:', range);
|
|
assertBoundary(
|
|
range.from.toISOString(),
|
|
'2024-06-16T04:00:00.000Z',
|
|
'Test 8 thisweek start (Sunday 2024-06-16 EDT)'
|
|
);
|
|
|
|
global.Date = savedDate;
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
}
|
|
|
|
// Test 9: dateRange='thismonth' in EDT.
|
|
{
|
|
const savedDate = Date;
|
|
const fixedNow = new Date('2024-06-21T02:30:00.000Z');
|
|
global.Date = class extends savedDate {
|
|
constructor(...args) {
|
|
if (args.length === 0) {
|
|
super(fixedNow);
|
|
} else {
|
|
super(...args);
|
|
}
|
|
}
|
|
static now() { return fixedNow.getTime(); }
|
|
};
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
const helpers = require('../utils/odata-helpers');
|
|
|
|
const range = helpers.processDateRange('thismonth', 'America/New_York');
|
|
console.log('Test 9 thismonth range:', range);
|
|
assertBoundary(
|
|
range.from.toISOString(),
|
|
'2024-06-01T04:00:00.000Z',
|
|
'Test 9 thismonth start (June 1 EDT)'
|
|
);
|
|
|
|
global.Date = savedDate;
|
|
delete require.cache[require.resolve('../utils/odata-helpers')];
|
|
delete require.cache[require.resolve('../utils/timezone-mapper')];
|
|
delete require.cache[require.resolve('../config')];
|
|
}
|
|
|
|
console.log('\nAll timezone-aware date filter tests passed.');
|