doctor.test.ts68 lines · main
1/**
2 * Doctor unit tests — focused on the pure logic that doesn't need the
3 * network. The interactive `runDoctor` orchestration (which fans out
4 * fetches and renders cli output) is exercised by the post-deploy
5 * integration suite that lives in infra/.
6 */
7
8import assert from 'node:assert/strict';
9import { describe, test } from 'node:test';
10
11describe('realtime origin derivation', () => {
12 // Mirrors the regex in doctor.ts. Refactor target: extract the helper
13 // once we add a second consumer; for now the single test pins the
14 // behaviour we depend on so any change to the api-host pattern shows
15 // up here.
16 function deriveRealtime(origin: string): string {
17 return origin.replace(/:\/\/api\./, '://realtime.');
18 }
19
20 test('rewrites api.<domain> → realtime.<domain>', () => {
21 assert.equal(deriveRealtime('https://api.briven.tech'), 'https://realtime.briven.tech');
22 assert.equal(
23 deriveRealtime('http://api.briven.local:3001'),
24 'http://realtime.briven.local:3001',
25 );
26 });
27
28 test('leaves origins without an api. prefix unchanged', () => {
29 assert.equal(deriveRealtime('http://localhost:3001'), 'http://localhost:3001');
30 assert.equal(deriveRealtime('https://briven.tech'), 'https://briven.tech');
31 assert.equal(deriveRealtime('https://my-api.example.com'), 'https://my-api.example.com');
32 });
33});
34
35describe('boot-time formatting', () => {
36 function formatBoot(iso: string, nowMs: number): string {
37 const then = new Date(iso).getTime();
38 if (!Number.isFinite(then)) return iso;
39 const sec = Math.max(0, Math.round((nowMs - then) / 1000));
40 if (sec < 60) return `${sec}s ago`;
41 if (sec < 3600) return `${Math.round(sec / 60)}m ago`;
42 return `${Math.round(sec / 3600)}h ago`;
43 }
44
45 const NOW = new Date('2026-05-10T20:00:00Z').getTime();
46
47 test('seconds-ago window', () => {
48 assert.equal(formatBoot('2026-05-10T19:59:30Z', NOW), '30s ago');
49 assert.equal(formatBoot('2026-05-10T19:59:01Z', NOW), '59s ago');
50 });
51
52 test('minutes-ago window', () => {
53 assert.equal(formatBoot('2026-05-10T19:55:00Z', NOW), '5m ago');
54 assert.equal(formatBoot('2026-05-10T19:01:00Z', NOW), '59m ago');
55 });
56
57 test('hours-ago window', () => {
58 assert.equal(formatBoot('2026-05-10T15:00:00Z', NOW), '5h ago');
59 });
60
61 test('clamps negative deltas to zero (clock-skew safety)', () => {
62 assert.equal(formatBoot('2026-05-10T20:01:00Z', NOW), '0s ago');
63 });
64
65 test('returns the raw string for unparseable input (best-effort)', () => {
66 assert.equal(formatBoot('not-a-date', NOW), 'not-a-date');
67 });
68});