import assert from 'node:assert/strict'; import test from 'node:test'; import { millisecondsUntilNextMinute, projectServerClock, sampleServerClock, } from '../src/utils/serverClockProjection.ts'; void test('projects a running server clock from the browser sample instant', () => { const sample = sampleServerClock( { serverTime: '2026-08-13T00:00:35.250Z', clockMode: 'realtime', clockRunning: true, }, 10_000 ); assert.ok(sample); assert.equal(projectServerClock(sample, 34_750).time.toISOString(), '2026-08-13T00:01:00.000Z'); assert.equal(millisecondsUntilNextMinute(projectServerClock(sample, 10_000).time), 24_750); }); void test('keeps manual clocks fixed even while client time advances', () => { const sample = sampleServerClock( { serverTime: '2026-08-13T00:00:35.000Z', clockMode: 'manual', clockRunning: false }, 10_000 ); assert.ok(sample); assert.equal(projectServerClock(sample, 130_000).time.toISOString(), '2026-08-13T00:00:35.000Z'); }); void test('holds a preopen clock until its wall-clock start delay passes', () => { const sample = sampleServerClock( { serverTime: '2026-08-13T00:00:00.000Z', serverWallTime: '2026-08-13T08:00:00.000Z', clockMode: 'realtime', clockRunning: false, clockStartsAt: '2026-08-13T08:01:00.000Z', }, 10_000 ); assert.ok(sample); assert.equal(projectServerClock(sample, 69_999).time.toISOString(), '2026-08-13T00:00:00.000Z'); assert.equal(projectServerClock(sample, 70_001).time.toISOString(), '2026-08-13T00:00:00.001Z'); }); void test('rejects an invalid server clock sample', () => { assert.equal(sampleServerClock({ serverTime: 'not-a-time' }, 10_000), null); }); void test('a single browser sample accelerates only inside the recovery window and rejoins normal time', () => { const sample = sampleServerClock( { serverTime: '2026-09-06T00:20:00Z', serverWallTime: '2026-09-06T04:20:00Z', clockRunning: true, clockRecovery: { startsAt: '2026-09-06T05:00:00Z', endsAt: '2026-09-06T09:00:00Z' }, }, 0 ); assert.ok(sample); const minute = 60_000; assert.equal(projectServerClock(sample, 40 * minute).time.toISOString(), '2026-09-06T01:00:00.000Z'); assert.equal(projectServerClock(sample, 100 * minute).time.toISOString(), '2026-09-06T03:00:00.000Z'); assert.equal(projectServerClock(sample, 280 * minute).time.toISOString(), '2026-09-06T09:00:00.000Z'); assert.equal(projectServerClock(sample, 340 * minute).time.toISOString(), '2026-09-06T10:00:00.000Z'); assert.equal(projectServerClock(sample, 280 * minute).rate, 1); }); void test('waits then accelerates from a partial month and returns to normal without resampling', () => { const sample = sampleServerClock( { serverTime: '2026-09-07T00:10:00Z', serverWallTime: '2026-09-07T00:24:00Z', clockMode: 'realtime', clockRunning: false, clockStartsAt: '2026-09-07T00:35:00Z', clockRecovery: { startsAt: '2026-09-07T00:35:00Z', endsAt: '2026-09-07T01:00:00Z' }, }, 0 ); assert.ok(sample); for (const elapsed of [0, 660000 - 1, 660000]) { assert.equal(projectServerClock(sample, elapsed).time.toISOString(), '2026-09-07T00:10:00.000Z'); } assert.equal(projectServerClock(sample, 660001).time.toISOString(), '2026-09-07T00:10:00.002Z'); assert.equal(projectServerClock(sample, 2160000 - 1).time.toISOString(), '2026-09-07T00:59:59.998Z'); assert.equal(projectServerClock(sample, 2160000 - 1).rate, 2); assert.equal(projectServerClock(sample, 2160000).time.toISOString(), '2026-09-07T01:00:00.000Z'); assert.equal(projectServerClock(sample, 2160000).rate, 1); assert.equal(projectServerClock(sample, 2160001).time.toISOString(), '2026-09-07T01:00:00.001Z'); });