commit 78c1ab1894b46557299653a8bd2be1217b8856f7
parent 0ebdb1a6b3247eb856d297eb7b4effc702ae2f22
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Fri, 25 Sep 2026 20:08:42 -0400
e2e: Official Instances heading exact, no card description, Ko-fi on the hub and homepage footers, none on a site build
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
3 files changed, 65 insertions(+), 6 deletions(-)
diff --git a/export/e2e-hub/official-instances.spec.ts b/export/e2e-hub/official-instances.spec.ts
@@ -1,6 +1,7 @@
import { expect, test, type Page, type Route } from "@playwright/test";
+import { KOFI_URL } from "../../common/lib/project";
-// The hub's "Official instances": one card per built-in member
+// The hub's "Official Instances": one card per built-in member
// (hub-sites.json), carrying the homepage's own figures for it when the hub was
// composed with them (hub-summary.json, written by compose-hub from the same
// buildHomepageSummary call the homepage makes). The summary is OPTIONAL — an
@@ -79,8 +80,15 @@ test.describe("hub official instances", () => {
}),
).toBeVisible();
await expect(
- page.getByRole("heading", { level: 2, name: "Official instances" }),
+ page.getByRole("heading", {
+ level: 2,
+ name: "Official Instances",
+ exact: true,
+ }),
).toBeVisible();
+ // No subtitle under the heading (operator ruling 2026-09-25: the title
+ // implies it).
+ await expect(page.getByText("The archives I run")).toHaveCount(0);
const card = page
.getByTestId("shelf-spine")
@@ -89,7 +97,9 @@ test.describe("hub official instances", () => {
await expect(
card.getByRole("link", { name: /Member Archive/ }),
).toHaveAttribute("target", "_blank");
- await expect(card).toContainText("Every word the member said.");
+ // The summary carries a description, and the card does not show it: no
+ // subtitle unless needed. The four figures carry the card.
+ await expect(card).not.toContainText("Every word the member said.");
for (const [value, unit] of [
["12", "channels"],
["3,456", "recordings"],
@@ -103,10 +113,26 @@ test.describe("hub official instances", () => {
// "Archives you added" section until they add one.
await expect(card.getByRole("button", { name: /^Remove/ })).toHaveCount(0);
await expect(
- page.getByRole("heading", { name: "Archives you added" }),
+ page.getByRole("heading", { name: "Archives You Added" }),
).toHaveCount(0);
});
+ test("the hub footer carries a bare Ko-fi link", async ({ page }) => {
+ await stubMember(page);
+ await page.route("**/hub-summary.json", (r) =>
+ r.fulfill({ status: 404, body: "" }),
+ );
+ await page.goto("/");
+ const kofi = page
+ .locator("footer")
+ .getByRole("link", { name: "Ko-fi", exact: true });
+ await expect(kofi).toHaveCount(1);
+ await expect(kofi).toHaveAttribute("href", KOFI_URL);
+ await expect(kofi).toHaveAttribute("target", "_blank");
+ await expect(kofi).toHaveAttribute("rel", "noopener noreferrer");
+ await expect(kofi).toHaveText("Ko-fi");
+ });
+
test("without hub-summary.json, the card renders with no figures", async ({
page,
}) => {
diff --git a/export/e2e/site-branding.spec.ts b/export/e2e/site-branding.spec.ts
@@ -1,5 +1,5 @@
import { test, expect } from "@playwright/test";
-import { PROJECT_URL } from "../../common/lib/project";
+import { KOFI_URL, PROJECT_URL } from "../../common/lib/project";
import { installRoutes } from "./helpers";
// The export app is built per-site; its SSR branding (document title, header,
@@ -45,6 +45,15 @@ test("footer credits the project, ungated and in the same tab", async ({
await expect(footer).toContainText("Built with Archilyzer");
});
+test("a site build carries no Ko-fi link", async ({ page }) => {
+ await installRoutes(page);
+ await page.goto("/");
+ // The project's Ko-fi is on the hub and the homepage only: an archive
+ // someone else hosts must not carry this project's tip jar.
+ await expect(page.getByRole("link", { name: "Ko-fi" })).toHaveCount(0);
+ await expect(page.locator(`a[href="${KOFI_URL}"]`)).toHaveCount(0);
+});
+
test("the Downloads eyebrow appears only when something is behind it", async ({
page,
}) => {
diff --git a/homepage/e2e/marketing.spec.ts b/homepage/e2e/marketing.spec.ts
@@ -1,6 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { test, expect } from "@playwright/test";
+import { KOFI_URL } from "../../common/lib/project";
// The home page's job is to say what Archilyzer is and offer the download.
// Nothing asserted here names a count, a site or a headline number. The numeric
@@ -92,12 +93,18 @@ test("official instances link out, and the numbers carry their build date", asyn
page,
}) => {
const summary = readSummary();
- const heading = page.getByRole("heading", { name: "Official instances" });
+ const heading = page.getByRole("heading", {
+ level: 2,
+ name: "Official Instances",
+ exact: true,
+ });
if (!summary?.sites?.length) {
await expect(heading).toHaveCount(0);
return;
}
await expect(heading).toBeVisible();
+ // No subtitle under the heading, and no description under a card's title.
+ await expect(page.getByText("The archives I run")).toHaveCount(0);
const section = page.locator("section").filter({ has: heading });
const links = section.getByRole("link");
expect(await links.count()).toBeGreaterThanOrEqual(1);
@@ -113,6 +120,23 @@ test("official instances link out, and the numbers carry their build date", asyn
}
});
+test("the headings after the H1 are in Title Case", async ({ page }) => {
+ await expect(
+ page.getByRole("heading", { level: 2, name: "What It Does", exact: true }),
+ ).toBeVisible();
+});
+
+test("the footer carries a bare Ko-fi link", async ({ page }) => {
+ const kofi = page
+ .locator("footer")
+ .getByRole("link", { name: "Ko-fi", exact: true });
+ await expect(kofi).toHaveCount(1);
+ await expect(kofi).toHaveAttribute("href", KOFI_URL);
+ await expect(kofi).toHaveAttribute("target", "_blank");
+ await expect(kofi).toHaveAttribute("rel", "noopener noreferrer");
+ await expect(kofi).toHaveText("Ko-fi");
+});
+
test("branded 404 for an unknown path", async ({ page }) => {
await page.goto("/no-such-page/");
await expect(page.getByRole("heading", { name: /no such page/i })).toBeVisible();