From a7e03cceb2fbb66d2262df5cb4718e1c1d33ebfc Mon Sep 17 00:00:00 2001 From: charming_wicket <235307685+charming-wicket-5502@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:59:35 +0100 Subject: [PATCH 1/2] test(admin-ui): scope realm-delete E2E assertion to realm cards The page-wide getByText("my-service") also matched the confirm modal and the success toast; on a slow runner it hit several elements and failed at once with a strict-mode violation. --- admin-ui/tests/e2e/realms.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin-ui/tests/e2e/realms.spec.ts b/admin-ui/tests/e2e/realms.spec.ts index 6129d5d..e7fc175 100644 --- a/admin-ui/tests/e2e/realms.spec.ts +++ b/admin-ui/tests/e2e/realms.spec.ts @@ -203,7 +203,8 @@ test.describe("Realms page", () => { await page.getByRole("button", { name: "Delete" }).last().click(); // The realm must no longer appear in the cards. - await expect(page.getByText("my-service")).not.toBeVisible(); + // Scope to `.ant-card`: the confirm modal and the success toast also show the realm name. + await expect(page.locator(".ant-card").filter({ hasText: "my-service" })).toHaveCount(0); }); test("should create a SAML realm from pasted IdP metadata", async ({ page }) => { From e2b8cc29f03dc33a8777b1e2a28e53e5fdf01621 Mon Sep 17 00:00:00 2001 From: charming_wicket <235307685+charming-wicket-5502@users.noreply.github.com> Date: Tue, 27 Oct 2026 16:00:02 +0100 Subject: [PATCH 2/2] docs(admin-ui): require scoped locators in E2E assertions after CRUD actions --- CHANGELOG/fix_e2e-realm-delete-flake.md | 7 +++++++ admin-ui/CLAUDE.md | 2 +- admin-ui/tests/e2e/README.md | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG/fix_e2e-realm-delete-flake.md diff --git a/CHANGELOG/fix_e2e-realm-delete-flake.md b/CHANGELOG/fix_e2e-realm-delete-flake.md new file mode 100644 index 0000000..7b2d82b --- /dev/null +++ b/CHANGELOG/fix_e2e-realm-delete-flake.md @@ -0,0 +1,7 @@ +## Tests + +- The admin UI E2E test that deletes a realm now checks the realm cards instead of any text on the page, because the confirm modal and the success toast also show the realm name, so on a slow runner the page-wide match found several elements and failed at once with a strict-mode violation. + +## Docs + +- The admin UI E2E conventions now require scoped locators (card, row or cell) for assertions after a create, update or delete, and `admin-ui/CLAUDE.md` points agents to those conventions when they add E2E tests. diff --git a/admin-ui/CLAUDE.md b/admin-ui/CLAUDE.md index 1810947..7559fc2 100644 --- a/admin-ui/CLAUDE.md +++ b/admin-ui/CLAUDE.md @@ -47,7 +47,7 @@ tests/ 1. Write failing test (red) — include error/edge cases, not just happy path 2. Implement minimal code (green) 3. Refactor, re-run tests -4. Add E2E test after unit tests pass +4. Add E2E test after unit tests pass, following the conventions in `tests/e2e/README.md` ## Coding Rules diff --git a/admin-ui/tests/e2e/README.md b/admin-ui/tests/e2e/README.md index ecbd82d..97891d9 100644 --- a/admin-ui/tests/e2e/README.md +++ b/admin-ui/tests/e2e/README.md @@ -27,5 +27,9 @@ pnpm exec playwright test - Prefer role-based locators (`getByRole("cell" | "tab" | "button", ...)`). Use `exact: true` or an anchored regex when a substring would match multiple elements (e.g. a role name that is also a substring of its `role_id` cell). +- After a create, update or delete, assert on the element that holds the data (`.ant-card`, + `getByRole("cell" | "row")`), not a page-wide `getByText(name)`: the confirm modal and the + success toast repeat the name, and several matches fail at once with a strict-mode + violation. Assert absence with `toHaveCount(0)` on that scoped locator. - Token self-service endpoints authenticate via the `X-Vault-Token` header, not the admin cookie — assert the header is present in their mocks.