Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 63dcce2d7579dc3bbc50a3ef382cd954eef41f23
parent eee3543c9e35953c9cb782e3d79d287df798ac79
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Sat, 26 Sep 2026 23:18:10 -0400

export(e2e): a site page and the hub have no link to ko-fi.com

The two Ko-fi mark tests become one negative check each: once the footer
is visible, no <a href*="ko-fi.com"> anywhere on the page. expectKofiMarkLast
and KOFI_SYMBOL_SHA256 are gone from e2e/helpers.ts, which is back to slice
O's parent byte for byte.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Mexport/e2e-hub/official-instances.spec.ts | 10+++-------
Mexport/e2e/helpers.ts | 58+---------------------------------------------------------
Mexport/e2e/site-branding.spec.ts | 19++++---------------
3 files changed, 8 insertions(+), 79 deletions(-)

diff --git a/export/e2e-hub/official-instances.spec.ts b/export/e2e-hub/official-instances.spec.ts @@ -1,5 +1,4 @@ import { expect, test, type Page, type Route } from "@playwright/test"; -import { expectKofiMarkLast } from "../e2e/helpers"; // 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 @@ -117,17 +116,14 @@ test.describe("hub official instances", () => { ).toHaveCount(0); }); - test("the hub footer carries the Ko-fi mark, once, last in the social row", async ({ - page, - }) => { + test("the hub has no link to ko-fi.com", async ({ page }) => { await stubMember(page); await page.route("**/hub-summary.json", (r) => r.fulfill({ status: 404, body: "" }), ); await page.goto("/"); - // The same mark as every site (the operator's 2026-09-26 ruling). The - // hub's own "Ko-fi" text link is gone: one Ko-fi per footer. - await expectKofiMarkLast(page); + await expect(page.locator("footer")).toBeVisible(); + await expect(page.locator('a[href*="ko-fi.com"]')).toHaveCount(0); }); test("without hub-summary.json, the card renders with no figures", async ({ diff --git a/export/e2e/helpers.ts b/export/e2e/helpers.ts @@ -1,6 +1,4 @@ -import { createHash } from "node:crypto"; -import { expect, type Page, type Route } from "@playwright/test"; -import { KOFI_URL } from "../../common/lib/project"; +import type { Page, Route } from "@playwright/test"; import { channelSubsManifest, channelTranscriptsManifest, @@ -175,57 +173,3 @@ export async function closeModal(page: Page) { .getByRole("button", { name: "Mark clip start at current time" }) .waitFor({ state: "detached" }); } - -// sha256 of Ko-fi's official `kofi_symbol.svg` (their brand-asset zip), which -// the export vendors byte-for-byte as public/kofi-symbol.svg: a brand asset is -// used as shipped, never recoloured or re-exported. -export const KOFI_SYMBOL_SHA256 = - "f5a2d5f1abb5c7f13392ecf6e7d5dffc8bef77917ab59c28a6080deab52f5078"; - -// The footer's Ko-fi mark, on every build (site and hub): exactly one Ko-fi -// link on the page, the LAST item of the footer's social row, opening Ko-fi in -// a new tab, with no visible text — only the official symbol, which is drawn -// (not a broken image) and served unmodified. -export async function expectKofiMarkLast(page: Page) { - const footer = page.locator("footer"); - const kofi = footer.getByRole("link", { name: "Ko-fi", exact: true }); - await expect(kofi).toHaveCount(1); - // One per page: no second Ko-fi link anywhere (the hub's old text link). - await expect(page.getByRole("link", { name: /ko-?fi/i })).toHaveCount(1); - await expect(page.locator(`a[href="${KOFI_URL}"]`)).toHaveCount(1); - await expect(kofi).toBeVisible(); - await expect(kofi).toHaveAttribute("href", KOFI_URL); - await expect(kofi).toHaveAttribute("target", "_blank"); - await expect(kofi).toHaveAttribute("rel", "noopener noreferrer"); - // No copy: the mark is the whole link. - expect((await kofi.innerText()).trim()).toBe(""); - - const img = kofi.locator('img[src="/kofi-symbol.svg"]'); - await expect(img).toHaveCount(1); - await expect(img).toHaveAttribute("alt", ""); - await expect - .poll(() => - img.evaluate((el) => { - const i = el as HTMLImageElement; - return i.complete && i.naturalWidth > 0; - }), - ) - .toBe(true); - - // `has` is queried from each <ul>, so it takes a page-rooted locator: `kofi` - // itself starts at <footer> and would look for a footer inside the list. - const row = footer - .locator("ul") - .filter({ has: page.getByRole("link", { name: "Ko-fi", exact: true }) }); - await expect(row).toHaveCount(1); - await expect( - row.locator(":scope > li").last().getByRole("link"), - ).toHaveAccessibleName("Ko-fi"); - - const res = await page.request.get("/kofi-symbol.svg"); - expect(res.status()).toBe(200); - expect(res.headers()["content-type"]).toMatch(/^image\/svg\+xml/); - expect(createHash("sha256").update(await res.body()).digest("hex")).toBe( - KOFI_SYMBOL_SHA256, - ); -} diff --git a/export/e2e/site-branding.spec.ts b/export/e2e/site-branding.spec.ts @@ -1,6 +1,6 @@ import { test, expect } from "@playwright/test"; import { PROJECT_URL } from "../../common/lib/project"; -import { expectKofiMarkLast, installRoutes } from "./helpers"; +import { installRoutes } from "./helpers"; // The export app is built per-site; its SSR branding (document title, header, // home tagline, footer social links) comes from currentSite() reading the @@ -45,22 +45,11 @@ test("footer credits the project, ungated and in the same tab", async ({ await expect(footer).toContainText("Built with Archilyzer"); }); -test("every build carries the Ko-fi mark, last in the social row", async ({ - page, -}) => { +test("a site page has no link to ko-fi.com", async ({ page }) => { await installRoutes(page); await page.goto("/"); - // The operator's 2026-09-26 ruling replaced "hub and homepage only": the - // project's Ko-fi is on every site, as Ko-fi's official symbol after the - // site's own social links, with no copy around it. - await expectKofiMarkLast(page); - // The site's own links come first, in the same row. - const row = page - .locator("footer ul") - .filter({ has: page.getByRole("link", { name: "Ko-fi", exact: true }) }); - const items = row.locator(":scope > li"); - await expect(items).toHaveCount(2); - await expect(items.first().getByRole("link")).toHaveAccessibleName("GitHub"); + await expect(page.locator("footer")).toBeVisible(); + await expect(page.locator('a[href*="ko-fi.com"]')).toHaveCount(0); }); test("the Downloads eyebrow appears only when something is behind it", async ({