Files
OrbitTv/server/schedule.test.ts
pauljdandClaude Opus 5.5 934f82d805
pauljd/davidson-ci: Davidson CI / quality (push) Failing after 1m48s
pauljd/davidson-ci: Davidson CI / ai-review (push) Successful in 49s
Orbit TV at 0.16.0-tuning-screen
First commit, imported from the working folder: Android TV app, loopback
guide server, design sources and per-release verification notes.

Includes the 0.16 tuning screen, built and tested but not yet confirmed
on the box.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-01 17:25:30 +00:00

28 lines
1.4 KiB
TypeScript

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));
});