commit cb8a042d27f4d43546208bd061c78bc3a3bf6c95
parent bddc4e4110303b2b9af6503c4b34919bb1582651
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Tue, 29 Sep 2026 21:37:14 -0400
homepage: the fixture's second list unlists every site in it (buildFixtureInputs sets `listed: false`); the unlisted-site spec also proves the site is in the builder's input and that, listed, it would change the summary (review L1, L2)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
2 files changed, 46 insertions(+), 12 deletions(-)
diff --git a/homepage/e2e/fixture-summary.ts b/homepage/e2e/fixture-summary.ts
@@ -32,7 +32,8 @@ import type { VideoStat } from "../../common/lib/stats";
// also exposes the first site's first channel. The summary names it nowhere
// and counts its own channels in no total, so `buildFixtureSummary()` is
// exactly `buildFixtureSummary(FIXTURE_SITES, [])` — every number the specs
-// read is the six listed sites'.
+// read is the six listed sites'. Every site in the second list is unlisted:
+// `buildFixtureInputs` sets `listed: false` on it, whatever it carries.
export const FIXTURE_SUMMARY_NAME = ".e2e-summary.json";
@@ -48,8 +49,8 @@ export const FIXTURE_PALE_HEX = "#f4c2d7";
// site.json one (a named accent's site, the custom hex's and a site with no
// accent have one — the last ends MID-WORD, "Fix" + "ture Three", as
// "Jer" + "alyzer" does; the rest show their title plain); `daily` how many
-// recordings each channel transcribes a day; `listed` the site.json key
-// (absent = listed).
+// recordings each channel transcribes a day. Whether a site is listed is the
+// list it is passed in (buildFixtureInputs), not a field.
export type FixtureSite = {
siteId: string;
siteTitle: string;
@@ -57,7 +58,6 @@ export type FixtureSite = {
wordmarkLead?: string;
channels: number;
daily: number;
- listed?: boolean;
};
export const FIXTURE_SITES: readonly FixtureSite[] = [
@@ -70,13 +70,13 @@ export const FIXTURE_SITES: readonly FixtureSite[] = [
];
// The unlisted site (an invented id, as every fixture's). Not in FIXTURE_SITES,
-// which is the six the pages show.
+// which is the six the pages show; buildFixtureInputs' second list, which
+// unlists it.
export const FIXTURE_UNLISTED_SITE: FixtureSite = {
siteId: "fixture-unlisted",
siteTitle: "Fixture Unlisted",
channels: 2,
daily: 6,
- listed: false,
};
const DAY = 86_400_000;
@@ -94,10 +94,13 @@ function uploadDate(n: number): string {
return ymd(d.getTime());
}
-export function buildFixtureSummary(
+// The builder's inputs: the recordings, the channel → sites map and the sites.
+// `fixtureSites` are listed; every site in `unlistedSites` is written with
+// `listed: false`, and each also exposes the first listed site's first channel.
+export function buildFixtureInputs(
fixtureSites: readonly FixtureSite[] = FIXTURE_SITES,
unlistedSites: readonly FixtureSite[] = [FIXTURE_UNLISTED_SITE],
-) {
+): { stats: VideoStat[]; channelSites: Record<string, string[]>; sites: Site[] } {
const stats: VideoStat[] = [];
const channelSites: Record<string, string[]> = {};
const sites: Site[] = [];
@@ -135,7 +138,11 @@ export function buildFixtureSummary(
const today = Date.UTC(2026, 8, 15);
// A site's own channels, `<siteId>-ch<N>`, each transcribing every day of the
// last HISTORY_DAYS; `shared` are other sites' channels it also exposes.
- const addSite = (s: FixtureSite, i: number, shared: string[] = []) => {
+ const addSite = (
+ s: FixtureSite,
+ i: number,
+ { listed = true, shared = [] }: { listed?: boolean; shared?: string[] } = {},
+ ) => {
const slugs = Array.from({ length: s.channels }, (_, c) => `${s.siteId}-ch${c + 1}`);
for (const slug of [...slugs, ...shared]) (channelSites[slug] ??= []).push(s.siteId);
sites.push({
@@ -146,7 +153,7 @@ export function buildFixtureSummary(
channels: [...slugs, ...shared].map((slug) => ({ slug })),
...(s.accent ? { accent: s.accent } : {}),
...(s.wordmarkLead ? { wordmarkLead: s.wordmarkLead } : {}),
- ...(s.listed === false ? { listed: false } : {}),
+ ...(listed ? {} : { listed: false }),
} as unknown as Site);
slugs.forEach((slug, c) => {
const name = `${s.siteTitle} Channel ${c + 1}`;
@@ -168,8 +175,20 @@ export function buildFixtureSummary(
// The unlisted sites LAST, so every listed site's recordings (their numbers,
// dates and states) are the same with them or without.
unlistedSites.forEach((s, j) =>
- addSite(s, fixtureSites.length + j, [`${spikeSite.siteId}-ch1`]),
+ addSite(s, fixtureSites.length + j, {
+ listed: false,
+ shared: [`${spikeSite.siteId}-ch1`],
+ }),
);
+ return { stats, channelSites, sites };
+}
+
+// The summary the e2e dev server reads: the real builder over those inputs.
+export function buildFixtureSummary(
+ fixtureSites: readonly FixtureSite[] = FIXTURE_SITES,
+ unlistedSites: readonly FixtureSite[] = [FIXTURE_UNLISTED_SITE],
+) {
+ const { stats, channelSites, sites } = buildFixtureInputs(fixtureSites, unlistedSites);
return buildHomepageSummary(stats, channelSites, sites, FIXTURE_NOW);
}
diff --git a/homepage/e2e/unlisted-site.spec.ts b/homepage/e2e/unlisted-site.spec.ts
@@ -5,6 +5,7 @@ import {
FIXTURE_SITES,
FIXTURE_SUMMARY_NAME,
FIXTURE_UNLISTED_SITE,
+ buildFixtureInputs,
buildFixtureSummary,
} from "./fixture-summary";
@@ -19,11 +20,25 @@ import {
const NEEDLES = [FIXTURE_UNLISTED_SITE.siteId, FIXTURE_UNLISTED_SITE.siteTitle];
test("the summary the server reads is the one built without the unlisted site", () => {
+ // The site is in the builder's input: unlisted, with recordings of its own
+ // and a channel shared with the first listed site.
+ const { stats, channelSites, sites } = buildFixtureInputs();
+ const unlisted = sites.find((s) => s.siteId === FIXTURE_UNLISTED_SITE.siteId);
+ expect(unlisted?.listed).toBe(false);
+ const own = stats.filter((s) => s.channelSlug.startsWith(`${FIXTURE_UNLISTED_SITE.siteId}-ch`));
+ expect(own.length).toBeGreaterThan(0);
+ expect(channelSites[`${FIXTURE_SITES[0].siteId}-ch1`]).toContain(FIXTURE_UNLISTED_SITE.siteId);
+ // Listed, the same site would change the summary: a card, and its recordings.
+ const withoutIt = buildFixtureSummary(FIXTURE_SITES, []);
+ const asListed = buildFixtureSummary([...FIXTURE_SITES, FIXTURE_UNLISTED_SITE], []);
+ expect(asListed.sites.map((s) => s.siteId)).toContain(FIXTURE_UNLISTED_SITE.siteId);
+ expect(asListed.totals.transcripts).toBe(withoutIt.totals.transcripts + own.length);
+
const onDisk = JSON.parse(
fs.readFileSync(path.resolve(process.cwd(), "e2e", FIXTURE_SUMMARY_NAME), "utf8"),
);
// Every array and every total: what the six listed sites alone produce.
- expect(onDisk).toEqual(JSON.parse(JSON.stringify(buildFixtureSummary(FIXTURE_SITES, []))));
+ expect(onDisk).toEqual(JSON.parse(JSON.stringify(withoutIt)));
const text = JSON.stringify(onDisk);
for (const needle of NEEDLES) expect(text).not.toContain(needle);
expect(onDisk.sites.map((s: { siteId: string }) => s.siteId)).toEqual(