import { test } from "node:test"; import assert from "node:assert/strict"; import { buildRanking, buildTimeSeries } from "./homepageChartData"; import { seriesColor, type ChartState } from "./homepageChart"; import type { BucketSeries, HomepageSummary } from "./homepageSummary"; import { siteChartColors } from "./siteColor"; // Run with: // pnpm --filter yt-dlp-transcript-common test // // The /stats colours (release 10): a SITE wears its chart colour // (siteChartColors — its accent's hue family, else its index) on every chart // and keeps it through the leaderboard's rank sort; a CHANNEL is still // coloured by rank. const stat = { total: 0, thisMonth: 0, last12: [] }; function series(bySite: Record, byChannel: Record): BucketSeries { return { buckets: ["2026-07", "2026-08"], total: [0, 0], bySite, byChannel, }; } function summary(): HomepageSummary { const month = series( { alpha: [1, 1], beta: [5, 5], gamma: [3, 3] }, { c1: [1, 0], c2: [9, 9], c3: [2, 2] }, ); const metric = { day: month, week: month, month }; const site = (siteId: string, accentId?: "brass" | "blue") => ({ siteId, siteTitle: siteId, siteDescription: "", siteUrl: `https://${siteId}.example`, transcribed: stat, downloaded: stat, ...(accentId ? { accentId } : {}), }); return { version: 5, generatedAt: "2026-09-27T00:00:00.000Z", totals: {} as HomepageSummary["totals"], channels: [ { slug: "c1", name: "Channel 1" }, { slug: "c2", name: "Channel 2" }, { slug: "c3", name: "Channel 3" }, ], series: { transcribed: metric, downloaded: metric }, // Summary order: alpha Brass, beta no accent, gamma Blue. sites: [site("alpha", "brass"), site("beta"), site("gamma", "blue")], recent: [], }; } function state(breakdown: ChartState["breakdown"], over: Partial = {}): ChartState { return { preset: "custom", metric: "transcribed", breakdown, chartType: "line", bucket: "month", range: "all", scale: "linear", valueMode: "counts", hidden: new Set(), soloId: null, excludeTop: false, ...over, }; } test("a site series wears its chart colour (siteChartColors), not its index's", () => { const s = summary(); const want = siteChartColors(s.sites); // alpha Brass → amber (chart-4); beta's own index is free (chart-2); // gamma Blue → blue (chart-1). assert.deepEqual(want, ["var(--chart-4)", "var(--chart-2)", "var(--chart-1)"]); const { series: out } = buildTimeSeries(s, state("site")); assert.deepEqual( out.map((x) => [x.id, x.color]), [ ["alpha", want[0]], ["beta", want[1]], ["gamma", want[2]], ], ); // Dropping the top site does not repaint the survivors. const { series: rest } = buildTimeSeries(s, state("site", { excludeTop: true })); assert.deepEqual( rest.map((x) => [x.id, x.color]), [ ["alpha", want[0]], ["gamma", want[2]], ], ); }); test("the site leaderboard keeps each site's own colour after the rank sort", () => { const s = summary(); const want = new Map(s.sites.map((x, i) => [x.siteId, siteChartColors(s.sites)[i]])); const { rows } = buildRanking(s, state("site", { chartType: "barH" }), 12); // Ranked by window total: beta 10, gamma 6, alpha 2. assert.deepEqual( rows.map((r) => [r.id, r.value, r.color]), [ ["beta", 10, want.get("beta")], ["gamma", 6, want.get("gamma")], ["alpha", 2, want.get("alpha")], ], ); }); test("the channel leaderboard is still coloured by rank", () => { const { rows } = buildRanking(summary(), state("channel", { chartType: "barH" }), 12); // Ranked: c2 18, c3 4, c1 1 — chart-1, chart-2, chart-3 by place. assert.deepEqual( rows.map((r) => [r.id, r.value, r.color]), [ ["c2", 18, seriesColor(0)], ["c3", 4, seriesColor(1)], ["c1", 1, seriesColor(2)], ], ); });