UNPKG

@wordpress/components

Version:
225 lines (199 loc) 6.97 kB
import timezoneMock from 'timezone-mock'; import { getSettings, setSettings, type DateSettings } from '@wordpress/date'; import { inputToDate, getDaysInMonth } from '../utils'; describe( 'getDaysInMonth', () => { it( 'should return the number of days in the month', () => { expect( getDaysInMonth( 2026, 0 ) ).toBe( 31 ); expect( getDaysInMonth( 2026, 1 ) ).toBe( 28 ); expect( getDaysInMonth( 2028, 1 ) ).toBe( 29 ); } ); } ); describe( 'inputToDate', () => { let originalSettings: DateSettings; beforeAll( () => { originalSettings = getSettings(); } ); afterEach( () => { timezoneMock.unregister(); } ); afterAll( () => { setSettings( originalSettings ); } ); describe( 'timezoneless strings', () => { beforeEach( () => { // Default settings are UTC, but make it explicit so these tests // don't depend on global settings state. setSettings( { ...originalSettings, timezone: { offset: 0, offsetFormatted: '0', string: '', abbr: '', }, } ); } ); describe.each( [ { timezone: 'US/Pacific' as const, description: 'Pacific time (behind UTC)', }, { timezone: 'UTC' as const, description: 'UTC (zero offset)', }, { timezone: 'Australia/Adelaide' as const, description: 'Adelaide (ahead of UTC)', }, ] )( 'in $description', ( { timezone } ) => { beforeEach( () => { timezoneMock.register( timezone ); } ); it( 'should parse midnight as UTC midnight, preventing day shifts', () => { const result = inputToDate( '2025-11-01T00:00:00' ); // Should always be Nov 1 00:00 in UTC, regardless of browser timezone expect( result.getUTCFullYear() ).toBe( 2025 ); expect( result.getUTCMonth() ).toBe( 10 ); // November (0-indexed) expect( result.getUTCDate() ).toBe( 1 ); expect( result.getUTCHours() ).toBe( 0 ); expect( result.getUTCMinutes() ).toBe( 0 ); expect( result.getUTCSeconds() ).toBe( 0 ); } ); it( 'should preserve non-midnight times in UTC, preventing day shifts', () => { const result = inputToDate( '2025-06-20T15:30:45' ); expect( result.getUTCFullYear() ).toBe( 2025 ); expect( result.getUTCMonth() ).toBe( 5 ); // June (0-indexed) expect( result.getUTCDate() ).toBe( 20 ); expect( result.getUTCHours() ).toBe( 15 ); expect( result.getUTCMinutes() ).toBe( 30 ); expect( result.getUTCSeconds() ).toBe( 45 ); } ); it( 'should parse date-only strings as midnight UTC', () => { const result = inputToDate( '2025-03-15' ); expect( result.getUTCFullYear() ).toBe( 2025 ); expect( result.getUTCMonth() ).toBe( 2 ); // March (0-indexed) expect( result.getUTCDate() ).toBe( 15 ); expect( result.getUTCHours() ).toBe( 0 ); expect( result.getUTCMinutes() ).toBe( 0 ); expect( result.getUTCSeconds() ).toBe( 0 ); } ); } ); } ); describe( 'timezoneless strings with a site timezone string (DST-aware)', () => { beforeEach( () => { setSettings( { ...originalSettings, timezone: { offset: -5, offsetFormatted: '-5', string: 'America/New_York', abbr: 'EST', }, } ); } ); describe.each( [ { timezone: 'US/Pacific' as const, description: 'Pacific time (behind UTC)', }, { timezone: 'UTC' as const, description: 'UTC (zero offset)', }, { timezone: 'Australia/Adelaide' as const, description: 'Adelaide (ahead of UTC)', }, ] )( 'in $description', ( { timezone } ) => { beforeEach( () => { timezoneMock.register( timezone ); } ); it( 'should interpret midnight using site timezone (winter)', () => { // Jan 10 is Eastern Standard Time in New York (UTC-5) const result = inputToDate( '2025-01-10T00:00:00' ); expect( result.toISOString() ).toBe( '2025-01-10T05:00:00.000Z' ); } ); it( 'should interpret midnight using site timezone (summer/DST)', () => { // Mar 10 is Eastern Daylight Time in New York (UTC-4) const result = inputToDate( '2025-03-10T00:00:00' ); expect( result.toISOString() ).toBe( '2025-03-10T04:00:00.000Z' ); } ); } ); } ); describe( 'strings with timezone indicators', () => { describe.each( [ { input: '2025-11-01T00:00:00Z', expectedHour: 0, expectedMinute: 0, description: 'Z suffix', }, { input: '2025-11-01T10:00:00+05:30', expectedHour: 4, expectedMinute: 30, description: '+HH:MM offset', }, { input: '2025-11-01T10:00:00-08:00', expectedHour: 18, expectedMinute: 0, description: '-HH:MM offset', }, // There's a few other valid formats in ISO-8601 (HHMM, HH, etc.), // but those aren't included in the ECMAScript specification, which // only includes "Z"-suffixed or "HH:mm"-suffixed strings. // // See: https://tc39.es/ecma262/#sec-date-time-string-format ] )( '$description', ( { input, expectedHour, expectedMinute } ) => { it( 'should respect explicit timezone offset', () => { const result = inputToDate( input ); expect( result.getUTCFullYear() ).toBe( 2025 ); expect( result.getUTCMonth() ).toBe( 10 ); // November expect( result.getUTCDate() ).toBe( 1 ); expect( result.getUTCHours() ).toBe( expectedHour ); expect( result.getUTCMinutes() ).toBe( expectedMinute ); } ); } ); } ); describe( 'Date objects', () => { it( 'should extract the UTC timestamp, not local time components', () => { // Mock Pacific timezone where local time differs from UTC. // This ensures the test fails on trunk if we incorrectly preserve // local components instead of extracting the UTC timestamp. timezoneMock.register( 'US/Pacific' ); // Create Nov 1, 2025 at 15:30:45 UTC const timestamp = Date.UTC( 2025, 10, 1, 15, 30, 45 ); const input = new Date( timestamp ); const result = inputToDate( input ); // Should preserve the exact UTC moment (15:30:45), not the local // Pacific time components (7:30:45 or 8:30:45 depending on DST). expect( result.getUTCFullYear() ).toBe( 2025 ); expect( result.getUTCMonth() ).toBe( 10 ); // November expect( result.getUTCDate() ).toBe( 1 ); expect( result.getUTCHours() ).toBe( 15 ); // UTC hour, not 7 or 8 expect( result.getUTCMinutes() ).toBe( 30 ); expect( result.getUTCSeconds() ).toBe( 45 ); } ); } ); describe( 'timestamps', () => { it( 'should preserve the UTC moment exactly', () => { // Ensure we're using a different timezone from UTC (the tests use // UTC by default). timezoneMock.register( 'US/Pacific' ); const timestamp = Date.UTC( 2025, 10, 1, 15, 30, 45 ); const result = inputToDate( timestamp ); expect( result.getUTCFullYear() ).toBe( 2025 ); expect( result.getUTCMonth() ).toBe( 10 ); // November expect( result.getUTCDate() ).toBe( 1 ); expect( result.getUTCHours() ).toBe( 15 ); expect( result.getUTCMinutes() ).toBe( 30 ); expect( result.getUTCSeconds() ).toBe( 45 ); } ); } ); } );