import { describe, expect, test } from "bun:test"; import { statsPage, type StatsData } from "./stats"; function page(domains: string[], trafficAll?: StatsData["trafficAll"]): string { const trafficSources = domains.map((domain, i) => ({ domain, hits: 100 - i })); const d: StatsData = { total: 100, hiddenCount: 0, rows: [], totalSearches: 0, avgLatency: 0, avgCacheLatency: 0, handlePct: "0", avatarPct: "0", snapshots: [], trafficSources, trafficAll: trafficAll ?? { domains: trafficSources.length, hits: trafficSources.reduce((s, r) => s + r.hits, 0) }, trafficSeries: [], trafficSeries5m: [], trafficDaily: [], requestSeries: [], requestSeries5m: [], requestDaily: [], }; return statsPage(d); } /** The selection targets — one legend entry, one table row — as raw markup. */ function legendEntry(html: string, domain: string): string { const start = html.indexOf(``); if (start < 0) return ""; const next = html.indexOf(`.*?`, "s"))?.[0] ?? ""; } describe("traffic source selection targets", () => { // The split contract (2026-08-15): in the TABLE the domain name is a link to // the app's site — the row still selects via the rank/hits/% cells because // the click handler skips anchors. In the LEGEND the whole entry stays a // selection target (it has no other tappable surface), so the name there is // NOT a link. const html = page(["plyr.fm", "unknown"]); test("the legend entry is not a link", () => { const entry = legendEntry(html, "plyr.fm"); expect(entry).toContain("plyr.fm"); expect(entry).not.toContain(" { const cell = tableRow(html, "plyr.fm").match(/