/** * earth-now.co * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * File: apps/web/test/tiers.test.ts * Purpose: Display-tier classification — fast tickers lead, slow stocks land in the reference strip, RT and countries route to their sections */ import { describe, expect, it } from "vitest"; import type { CounterModel } from "@earth-now/counter"; import type { MetricSummary } from "../lib/api"; import { secondsPerVisibleTick, tierFor, LIVE_TICK_THRESHOLD_S } from "../lib/tiers"; const T = Date.parse("2026-08-09T12:00:00Z"); function model(perSecond: number): CounterModel { return { metricId: "m", anchorValue: 0, anchorTime: "2026-01-01T00:00:00.000Z", rateFn: { kind: "linear", perSecond }, observedAt: "2026-01-01T00:00:00.000Z", sourceId: "s", modelVersion: "test-v1", displayHints: { decimals: 0, unit: "u" }, }; } function metric(over: Partial): MetricSummary { return { id: "some_metric", name: { fr: "x", en: "x" }, domain: "population", priority: "mvp", kind: "cumulative", level: 1, model: "seasonal-ytd-v1", unit: "people", sources: [], display: { decimals: 0, unit: { fr: "u", en: "u" } }, windows: ["ytd"], stale: false, ...over, }; } describe("secondsPerVisibleTick", () => { it("computes the visible tick interval from rate, decimals and display scale", () => { // 4 units/s at 0 decimals → last digit changes every 0.25 s. expect(secondsPerVisibleTick(model(4), { decimals: 0 }, T)).toBeCloseTo(0.25, 9); // 1027 MWh/s displayed in TWh (scale 1e-6) with 2 decimals → 0.01 TWh per tick. expect(secondsPerVisibleTick(model(1027), { decimals: 2, scale: 1e-6 }, T)).toBeCloseTo( 0.01 / (1027e-6), 6, ); expect(secondsPerVisibleTick(model(0), { decimals: 0 }, T)).toBe(Infinity); }); }); describe("tierFor", () => { it("fast tickers are live, slow stocks are reference", () => { expect(tierFor(metric({}), model(4.2), T)).toBe("live"); // CO₂ ppm style: 2.6 ppm/yr, 2 decimals → hours per tick → reference. expect( tierFor( metric({ id: "co2_ppm", kind: "stock", display: { decimals: 2, unit: { fr: "ppm", en: "ppm" } } }), model(2.6 / 31_556_952), T, ), ).toBe("reference"); }); it("routes hero, countries and RT metrics to their sections regardless of rate", () => { expect(tierFor(metric({ id: "world_population" }), model(2.2), T)).toBe("hero"); expect(tierFor(metric({ id: "country_population_india" }), model(0.37), T)).toBe("country"); expect(tierFor(metric({ id: "earthquakes_24h", level: "rt" }), model(0), T)).toBe("realtime"); }); it("rate-of and depletion displays read as static → reference", () => { const rateOf = metric({ id: "co2_rate", kind: "derived", derived: { op: "rate-of", inputs: [{ id: "co2_emissions_ytd", weight: 1 }] }, }); expect(tierFor(rateOf, model(1200), T)).toBe("reference"); }); it("no model → reference (stale metrics never fake liveness)", () => { expect(tierFor(metric({}), undefined, T)).toBe("reference"); }); it("threshold boundary respects LIVE_TICK_THRESHOLD_S", () => { const boundaryRate = 1 / LIVE_TICK_THRESHOLD_S; expect(tierFor(metric({}), model(boundaryRate * 1.01), T)).toBe("live"); expect(tierFor(metric({}), model(boundaryRate * 0.99), T)).toBe("reference"); }); });