Archilyzer · Source

archilyzer

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

commit d48144397a89c335a5c67bd673e53d1a0fc3226d
parent 330f3134069da858cc9a89762b2d6474ab82cbb9
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Mon, 28 Sep 2026 01:52:06 -0400

sites: the Homepage group stamps data-hydrated; its specs wait for it before a click or a keystroke, and the queued lane is asserted with no alert

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

Diffstat:
Meditor/app/sites/components/HomepageBuildButtons.tsx | 12+++++++++++-
Meditor/e2e/sites-homepage.spec.ts | 18++++++++++++++----
2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/editor/app/sites/components/HomepageBuildButtons.tsx b/editor/app/sites/components/HomepageBuildButtons.tsx @@ -12,6 +12,7 @@ import { buildHomepageAction, deployHomepageAction, } from "../lib/homepageDeployActions"; +import { useHydrated } from "../../operations/components/useOperationsStatus"; import { JobLane } from "./JobLane"; type Lane = { @@ -53,6 +54,7 @@ export function HomepageBuildButtons({ project, builtAt }: Props) { const [preview, setPreview] = useState(""); const [lane, setLane] = useState<Lane | null>(null); const [run, setRun] = useState(0); + const hydrated = useHydrated(); const branch = preview.trim(); const problem = branch ? previewBranchProblem(branch) : null; @@ -75,7 +77,15 @@ export function HomepageBuildButtons({ project, builtAt }: Props) { } return ( - <div role="group" aria-label="Homepage build" className="flex flex-col gap-3"> + // data-hydrated: a TESTING AFFORDANCE, as on the operation lanes. A click + // that lands before React hydrates fires nothing at all, so a spec waits + // for this before it clicks Build homepage. + <div + role="group" + aria-label="Homepage build" + className="flex flex-col gap-3" + data-hydrated={hydrated ? "true" : undefined} + > <div className="flex flex-wrap items-center gap-3"> <button type="button" diff --git a/editor/e2e/sites-homepage.spec.ts b/editor/e2e/sites-homepage.spec.ts @@ -35,6 +35,15 @@ const deployAfter = (page: Page) => group(page).getByLabel("Deploy after build") const previewInput = (page: Page) => group(page).getByRole("textbox", { name: "preview branch", exact: true }); +// A click or a keystroke that lands before React hydrates is lost without a +// trace; the group stamps data-hydrated once its mount effect has run. +async function openSites(page: Page) { + await page.goto("/sites"); + await expect(group(page)).toHaveAttribute("data-hydrated", "true", { + timeout: 15_000, + }); +} + type Meta = { id: string; kind: string; @@ -107,7 +116,7 @@ test("the Homepage section follows Hub, with the build and deploy controls and w test("a bad preview name greys out every deploy and says why; a good one shows its alias", async ({ page, }) => { - await page.goto("/sites"); + await openSites(page); const ships = group(page).getByTestId("homepage-ships"); await previewInput(page).fill("main"); @@ -162,12 +171,13 @@ test("Build homepage starts a build-homepage job on the build queue (held there, ); expect(hold.ok()).toBe(true); - await page.goto("/sites"); + await openSites(page); await expect(deployAfter(page)).not.toBeChecked(); await buildButton(page).click(); - // The lane: queued behind the holder. - await expect(group(page).getByText(/^Queued/)).toBeVisible(); + // The lane: queued behind the holder — not refused, not running. + await expect(group(page).getByText(/^Queued/)).toBeVisible({ timeout: 15_000 }); + await expect(group(page).getByRole("alert")).toHaveCount(0); // One build-homepage job, on the build queue, queued — and nothing else. await expect.poll(async () => (await metasOfKind("build-homepage")).length).toBe(1);