'use strict'; // Shared pipeline-freshness tier (Ship A + design-train M1b). The desktop // HeartbeatBar and the mobile app-bar clock BOTH key off this — one source, so // mobile can never silently disagree with desktop about staleness. const { freshnessTier, DEFAULT_EXPECTED_S } = require('../../web/src/lib/freshness'); const S = 1000; const now = 1_000_000_000_000; describe('freshnessTier', () => { test('calm when the heartbeat is recent (< 1.5× expected)', () => { const r = freshnessTier(now - 1000 * S, 1200, now); // 1000s elapsed, expected 1200 → 0.83× expect(r.tier).toBe('normal'); expect(r.elapsedMs).toBe(1000 * S); }); test('amber at ≥ 1.5× expected (the reaction begins)', () => { const r = freshnessTier(now - 1800 * S, 1200, now); // 1800/1200 = 1.5× expect(r.tier).toBe('amber'); }); test('stale (red) at ≥ 3× expected — never silently stale', () => { const r = freshnessTier(now - 3600 * S, 1200, now); // 3600/1200 = 3× expect(r.tier).toBe('stale'); }); test('absent/NaN heartbeat is calm, not a false STALE', () => { expect(freshnessTier(NaN, 1200, now).tier).toBe('normal'); expect(freshnessTier(NaN, 1200, now).elapsedMs).toBeNull(); }); test('non-positive expected falls back to the default 5h gap', () => { // 4h elapsed vs the 5h (18000s) default → still under 1.5× → calm const r = freshnessTier(now - 4 * 3600 * S, 0, now); expect(DEFAULT_EXPECTED_S).toBe(18000); expect(r.tier).toBe('normal'); }); test('future/negative elapsed clamps to 0 (calm), never a negative age', () => { const r = freshnessTier(now + 5000 * S, 1200, now); expect(r.elapsedMs).toBe(0); expect(r.tier).toBe('normal'); }); });