import { test } from 'node:test'; import assert from 'node:assert/strict'; import { channels, programme, guide, SLOT_MS } from './schedule.ts'; test('join in progress returns the broadcast offset', () => { const start = SLOT_MS * 100; assert.equal(programme(channels[0], start + 18 * 60000).offsetMs, 18 * 60000); }); test('exact boundary switches programmes with no gap', () => { const a = programme(channels[0], SLOT_MS - 1), b = programme(channels[0], SLOT_MS); assert.equal(a.end, b.start); assert.equal(b.offsetMs, 0); assert.notEqual(a.title, b.title); }); test('schedule is deterministic and contiguous across midnight', () => { const at = Date.UTC(2026, 9, 31, 23, 59); assert.deepEqual(guide(at), guide(at)); for (const channel of guide(at, 48)) channel.programmes.slice(1).forEach((show, i) => assert.equal(channel.programmes[i].end, show.start)); }); test('invalid input is rejected and negative epochs work', () => { for (const count of [0, -1, 49, 1.5, NaN]) assert.throws(() => guide(0, count)); for (const at of [NaN, Infinity, 8.1e15]) assert.throws(() => guide(at)); assert.equal(programme(channels[0], -1).start, -SLOT_MS); }); test('future guide entries start at zero rather than inheriting current offset', () => { const programmes = guide(18 * 60000)[0].programmes; assert.equal(programmes[0].offsetMs, 18 * 60000); assert.ok(programmes.slice(1).every(show => show.offsetMs === 0)); });