commit a6e893dcf62d2b8a43294243157b1189fad1a39c
parent b0f48842bd3bf82e765518dba51f6140f119fab9
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Wed, 23 Sep 2026 09:07:17 -0400
sites: the preview problem message may not borrow the input's name
"preview branch problem" contains "preview branch", so every by-label lookup
for the input resolved to two elements once a problem was showing. That is a
screen-reader ambiguity before it is a strict-mode violation: two things in one
small region answering to the same words. The message is "preview problem"
now, and the spec asks for the textbox by exact name so it cannot re-acquire
the ambiguity quietly.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/editor/app/sites/components/DeployButton.tsx b/editor/app/sites/components/DeployButton.tsx
@@ -121,7 +121,11 @@ function PreviewDeploy({
{problem ? (
<p
role="status"
- aria-label="preview branch problem"
+ // NOT "preview branch problem". An accessible name that CONTAINS
+ // another control's name makes every by-label lookup for the input
+ // ambiguous — a real screen-reader confusion as much as a test one.
+ // Only the input answers to "preview branch".
+ aria-label="preview problem"
className="text-sm text-destructive"
>
{problem}
diff --git a/editor/e2e/site-publish-preview.spec.ts b/editor/e2e/site-publish-preview.spec.ts
@@ -21,6 +21,13 @@ async function openIndividualSteps(page: Page, siteId: string) {
const preview = (page: Page) =>
page.getByRole("region", { name: "Deploy preview" });
+// EXACT, not the default substring match. getByLabel("preview branch") once
+// matched the problem message too, whose aria-label began with the same two
+// words — the ambiguity was the component's, and it is fixed there; this keeps
+// the spec from being able to re-acquire it silently.
+const branchInput = (page: Page) =>
+ preview(page).getByRole("textbox", { name: "preview branch", exact: true });
+
test.beforeEach(async () => {
await resetData("empty");
});
@@ -43,7 +50,7 @@ test("the production deploy says production, and a preview sits beside it", asyn
const panel = preview(page);
await expect(panel.getByRole("button", { name: "Deploy preview" })).toBeVisible();
// Defaulted, so the common case is one click.
- await expect(panel.getByLabel("preview branch")).toHaveValue("preview");
+ await expect(branchInput(page)).toHaveValue("preview");
});
test("the alias is shown before the deploy, and follows the branch name", async ({
@@ -59,7 +66,7 @@ test("the alias is shown before the deploy, and follows the branch name", async
await expect(link).toBeVisible();
await expect(link).toHaveAttribute("href", "https://preview.proj.pages.dev");
- const input = panel.getByLabel("preview branch");
+ const input = branchInput(page);
await input.fill("tags-exclude");
await expect(
panel.getByRole("link", { name: "https://tags-exclude.proj.pages.dev" }),
@@ -74,7 +81,7 @@ test("main disables the preview button and says why", async ({ page }) => {
const button = panel.getByRole("button", { name: "Deploy preview" });
await expect(button).toBeEnabled();
- await panel.getByLabel("preview branch").fill("main");
+ await branchInput(page).fill("main");
await expect(button).toBeDisabled();
await expect(panel.getByText(/is the production branch/)).toBeVisible();
// No alias while the name is refused — a link to a hostname that will not
@@ -82,14 +89,14 @@ test("main disables the preview button and says why", async ({ page }) => {
await expect(panel.getByRole("link")).toHaveCount(0);
// Uppercase is refused for its shape rather than lowercased into production.
- await panel.getByLabel("preview branch").fill("Main");
+ await branchInput(page).fill("Main");
await expect(button).toBeDisabled();
await expect(
panel.getByText(/not a valid preview branch name/),
).toBeVisible();
// And a good name re-arms it.
- await panel.getByLabel("preview branch").fill("rc-1");
+ await branchInput(page).fill("rc-1");
await expect(button).toBeEnabled();
await expect(
panel.getByRole("link", { name: "https://rc-1.proj.pages.dev" }),