From 37eb9bdf59f96c51663b8fb05368b972f2b08009 Mon Sep 17 00:00:00 2001 From: Agents Date: Sun, 24 May 2026 21:32:50 +0100 Subject: [PATCH] test(web): add E2E for Fleet route nav + per-instance row render MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two focused Playwright tests, mirroring the existing sidebar.spec pattern (no backend dependency — instances point at unreachable ports and we only assert on rendered names + row count, not health): - Fleet link in the sidebar navigates to /fleet - /fleet renders one row per configured instance under the table role Also adds a Fleet link assertion to the existing sidebar.spec so the nav entry is covered on the dashboard route alongside the other top links. Both new tests run under the existing `pnpm test:e2e` (not gated in CI by design — matches the current Compare/Dashboard E2E posture). Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/web/e2e/fleet.spec.ts | 51 ++++++++++++++++++++++++++++++++ packages/web/e2e/sidebar.spec.ts | 1 + 2 files changed, 52 insertions(+) create mode 100644 packages/web/e2e/fleet.spec.ts diff --git a/packages/web/e2e/fleet.spec.ts b/packages/web/e2e/fleet.spec.ts new file mode 100644 index 0000000..a8c07b3 --- /dev/null +++ b/packages/web/e2e/fleet.spec.ts @@ -0,0 +1,51 @@ +import { expect, test } from "@playwright/test"; + +const STORE_KEY = "openconcho:instances"; + +// Two unreachable instances — the rows still render with their configured +// names; only the health column flips to "unreachable" once the workspaces +// query errors. We only assert on the rendered names + row count, so the +// test doesn't depend on a live backend. +const FLEET_STORE = JSON.stringify({ + instances: [ + { id: "a", name: "Neo", baseUrl: "http://localhost:9001", token: "" }, + { id: "b", name: "Iris", baseUrl: "http://localhost:9002", token: "" }, + { id: "c", name: "Lexi", baseUrl: "http://localhost:9003", token: "" }, + ], + activeId: "a", +}); + +test.describe("Fleet route", () => { + test.beforeEach(async ({ context }) => { + await context.addInitScript( + ([key, value]) => { + window.localStorage.setItem(key, value); + }, + [STORE_KEY, FLEET_STORE], + ); + }); + + test("renders one row per configured instance and the Fleet heading", async ({ page }) => { + await page.goto("/fleet"); + + // Page header + await expect(page.getByRole("heading", { name: /^Fleet$/ })).toBeVisible(); + + // One row per instance, asserted via the table not the sidebar (the + // active instance's name also appears in the sidebar switcher). + const table = page.getByRole("table"); + await expect(table.getByText("Neo", { exact: true })).toBeVisible(); + await expect(table.getByText("Iris", { exact: true })).toBeVisible(); + await expect(table.getByText("Lexi", { exact: true })).toBeVisible(); + + // 1 header row + 3 instance rows + await expect(table.getByRole("row")).toHaveCount(4); + }); + + test("Fleet link in the sidebar navigates to /fleet", async ({ page }) => { + await page.goto("/"); + await page.getByRole("link", { name: /fleet/i }).click(); + await expect(page).toHaveURL(/\/fleet$/); + await expect(page.getByRole("heading", { name: /^Fleet$/ })).toBeVisible(); + }); +}); diff --git a/packages/web/e2e/sidebar.spec.ts b/packages/web/e2e/sidebar.spec.ts index b0eb6e0..1037a22 100644 --- a/packages/web/e2e/sidebar.spec.ts +++ b/packages/web/e2e/sidebar.spec.ts @@ -17,6 +17,7 @@ test.describe("Sidebar", () => { await page.goto("/"); await expect(page.getByRole("complementary")).toBeVisible(); await expect(page.getByRole("link", { name: /dashboard/i })).toBeVisible(); + await expect(page.getByRole("link", { name: /fleet/i })).toBeVisible(); await expect(page.getByRole("link", { name: /workspaces/i })).toBeVisible(); await expect(page.getByRole("link", { name: /settings/i })).toBeVisible(); });