Browser E2E for the admin OAuth2-clients screen #39

Merged
lilleman merged 2 commits from e2e-oauth2-clients into main 2026-08-02 16:18:43 +02:00
3 changed files with 11 additions and 20 deletions
Showing only changes of commit 0919adf4ef - Show all commits
+2 -2
View File
@@ -1119,8 +1119,8 @@ docker compose -f compose.yml -f e2e-tests/compose.oauth.yml down -v
**Full browser flow** (`full-flow.spec.ts`) — the real Playwright UI against the live stack: **Full browser flow** (`full-flow.spec.ts`) — the real Playwright UI against the live stack:
the themed **password login** and a **mocked-SSO** login (an in-network mock OIDC provider, the themed **password login** and a **mocked-SSO** login (an in-network mock OIDC provider,
`e2e-tests/mock-oidc.ts`), **menu filtering by role**, the **users/groups/roles** admin CRUD, the `e2e-tests/mock-oidc.ts`), **menu filtering by role**, the **users/groups/roles** admin CRUD, the
**OAuth2-clients** admin screen (register → one-time secret → delete; Hydra is part of this **OAuth2-clients** admin screen (register → one-time secret → delete; Hydra is part of this stack
stack for it), a permission-gated **plugin page**, and **logout**. Because the themed form posts straight to for it), a permission-gated **plugin page**, and **logout**. Because the themed form posts straight to
Kratos and cookies are host-scoped, a tiny same-origin gateway (`e2e-tests/proxy.ts`) fronts web + Kratos and cookies are host-scoped, a tiny same-origin gateway (`e2e-tests/proxy.ts`) fronts web +
Kratos on one host (`ory/kratos/e2e-proxy.yml` points Kratos at it) — exactly as a production Kratos on one host (`ory/kratos/e2e-proxy.yml` points Kratos at it) — exactly as a production
reverse proxy would. reverse proxy would.
+8 -17
View File
@@ -1,25 +1,16 @@
# Full browser E2E — the real Playwright UI flow against the live stack: password + # Full browser E2E — the real Playwright UI flow against the live stack: password + mocked-SSO
# mocked-SSO login, menu filtering by role, users/groups/roles/OAuth2-clients CRUD, a plugin page, # login, menu filtering by role, users/groups/roles/OAuth2-clients CRUD, a plugin page, logout. A
# logout. A tiny # tiny same-origin gateway (proxy, e2e-tests/proxy.ts) fronts web + Kratos on one host so the browser's cookies
# same-origin gateway (proxy, e2e-tests/proxy.ts) fronts web + Kratos on one host so the browser's cookies
# round-trip (ory/kratos/e2e-proxy.yml points Kratos at it); a mock OIDC provider backs the SSO test. # round-trip (ory/kratos/e2e-proxy.yml points Kratos at it); a mock OIDC provider backs the SSO test.
# docker compose -f compose.yml -f e2e-tests/compose.full.yml run --build --rm e2e # docker compose -f compose.yml -f e2e-tests/compose.full.yml run --build --rm e2e
# docker compose -f compose.yml -f e2e-tests/compose.full.yml down -v # tear down after # docker compose -f compose.yml -f e2e-tests/compose.full.yml down -v # tear down after
services: services:
web: web:
# Kratos + Keto + bootstrap back the login/role flows; Hydra backs the admin plugin's # The base's full depends_on applies (Hydra included — the admin plugin's OAuth2-clients
# OAuth2-clients screen. SSO is enabled here only (clean clone stays password-only): the mock # screen needs it); only the reference plugin's upstream is added. SSO is enabled here only
# provider's whole array is the env-settable form Kratos offers, mapped through the committed # (clean clone stays password-only): the mock provider's whole array is the env-settable form
# claims jsonnet. # Kratos offers, mapped through the committed claims jsonnet.
depends_on: !override depends_on:
bootstrap:
condition: service_completed_successfully
hydra:
condition: service_healthy
kratos:
condition: service_healthy
keto:
condition: service_healthy
shifts-upstream: shifts-upstream:
condition: service_healthy condition: service_healthy
environment: environment:
+1 -1
View File
@@ -97,7 +97,7 @@ test.describe.serial("authenticated admin journey", () => {
await expect(page.locator("h1")).toHaveText("Client registered"); await expect(page.locator("h1")).toHaveText("Client registered");
const clientId = await page.locator("#cid").inputValue(); const clientId = await page.locator("#cid").inputValue();
expect(clientId).toBeTruthy(); expect(clientId).toBeTruthy();
await expect(page.locator("#csecret")).not.toHaveValue(""); await expect(page.locator("#csecret")).toHaveValue(/.+/);
// Listed; the row header links to the plain detail, which never shows the secret again. // Listed; the row header links to the plain detail, which never shows the secret again.
await page.goto("/admin/clients"); await page.goto("/admin/clients");