From df0dbe9bf6c0ee844754c6413cf809251fab364a Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sun, 14 Jun 2026 01:46:49 +0000 Subject: [PATCH] test(e2e): make org-template import spec fail-closed (#2809) canvas/e2e/org-template-import.spec.ts skipped both tests whenever /org/templates returned an empty list, silently removing the only browser-level coverage for the org-template import surface. - Add a suite-level beforeAll that fetches /org/templates and asserts at least one template exists, failing with a clear setup-error message instead of skipping. - Remove the per-test test.skip(orgs.length === 0) guards. - Share the fetched org list between tests. Component-level empty-state tests continue to cover the no-templates UI path; this E2E now requires a populated template registry. Fixes #2809 Co-Authored-By: Claude --- canvas/e2e/org-template-import.spec.ts | 35 ++++++++++++++++++-------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/canvas/e2e/org-template-import.spec.ts b/canvas/e2e/org-template-import.spec.ts index 9bafb08b5..75e176748 100644 --- a/canvas/e2e/org-template-import.spec.ts +++ b/canvas/e2e/org-template-import.spec.ts @@ -2,14 +2,30 @@ import { test, expect } from "@playwright/test"; const API = process.env.E2E_API_URL ?? "http://localhost:8080"; -test.describe("Org template import (PLAN.md §20.3)", () => { - test("org templates section renders inside the palette", async ({ page }) => { - // Sanity: platform must serve /org/templates - const res = await page.request.get(`${API}/org/templates`); - expect(res.ok()).toBeTruthy(); - const orgs: { dir: string; name: string; workspaces: number }[] = await res.json(); - test.skip(orgs.length === 0, "No org templates configured"); +interface OrgTemplate { + dir: string; + name: string; + workspaces: number; +} +test.describe("Org template import (PLAN.md §20.3)", () => { + let orgs: OrgTemplate[] = []; + + test.beforeAll(async ({ request }) => { + const res = await request.get(`${API}/org/templates`); + expect(res.ok(), "GET /org/templates must succeed").toBeTruthy(); + orgs = (await res.json()) as OrgTemplate[]; + + // Fail-closed: this E2E exists to prove the org-template import surface + // renders real templates. An empty registry is a setup failure, not a + // reason to skip coverage. Component tests cover the empty-state UI. + expect( + orgs.length, + "No org templates configured — run scripts/clone-manifest.sh (or equivalent) before this E2E suite", + ).toBeGreaterThan(0); + }); + + test("org templates section renders inside the palette", async ({ page }) => { await page.goto("/", { waitUntil: "networkidle" }); // The Org Templates section lives in TWO places: inside the EmptyState @@ -34,10 +50,6 @@ test.describe("Org template import (PLAN.md §20.3)", () => { }); test("import button exists for every org template returned by the API", async ({ page }) => { - const res = await page.request.get(`${API}/org/templates`); - const orgs: { dir: string }[] = await res.json(); - test.skip(orgs.length === 0, "No org templates configured"); - await page.goto("/", { waitUntil: "networkidle" }); const paletteToggle = page.getByTitle("Template Palette"); if (await paletteToggle.isVisible()) { @@ -45,6 +57,7 @@ test.describe("Org template import (PLAN.md §20.3)", () => { } const section = page.getByTestId("org-templates-section").first(); await expect(section).toBeVisible({ timeout: 15000 }); + // Wait for the API result to render (one Import button per org) const buttons = section.getByRole("button", { name: /Import org/i }); await expect(buttons).toHaveCount(orgs.length, { timeout: 15000 }); -- 2.52.0