commit ac51e43166bbda046af9f034d386f9a8fa19fcf7
parent 5bc6a32f6b720d811de85b189233f1b72a1e99a1
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sun, 27 Sep 2026 01:02:11 -0400
common: homepageChartData tests — /stats site colours, and the leaderboard by site and by channel
Review fix. A site series wears siteChartColors (and keeps it when the top
site is excluded); the By-site leaderboard keeps each site's own colour after
the rank sort; the By-channel leaderboard is still coloured by rank. The first
two fail on 5446f83b's homepageChartData.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
1 file changed, 127 insertions(+), 0 deletions(-)
diff --git a/common/lib/homepageChartData.test.ts b/common/lib/homepageChartData.test.ts
@@ -0,0 +1,127 @@
+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<string, number[]>, byChannel: Record<string, number[]>): 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> = {}): 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)],
+ ],
+ );
+});