fix(web-app-shopware): let the logout sweep land before leaving the page

e59ea21c6 waited on document.cookie, which is origin-scoped. By the time
it runs the page sits on logout.<domain>, where Shopware's bearerAuth -
host-scoped to shop.<domain> - is not visible. The predicate was true on
the first poll, so the wait did nothing and three of the six jobs were
unchanged.

page.context().cookies() reads the browser context's jar regardless of
which document is displayed, so the same post-condition can be observed
from Keycloak's logout page.

The wait matters because the thing that clears that cookie is not
Shopware and not the injected patch - it is web-svc-logout. Keycloak
loads its conductor as the front-channel logout URL in an iframe; the
conductor fetches <host>/logout for every domain with
credentials: "include" (universal-logout templates/conductor.html.j2),
each /logout deletes the cookies visible on that host and sends
Clear-Site-Data (app.py), and roles/web-svc-logout/templates/logout-proxy.conf.j2
supplies the matching Access-Control-Allow-Origin plus
Allow-Credentials. Every link of that chain is in place.

What was missing was time. In run 32284541284 the trace shows the
logout-confirm click at 16543.805 and the navigation to /admin at
16902.227 - 358 ms, against 220-350 ms per Tor hop. The conductor's
document had not finished loading, so its sweep never ran:
grep -c -a "onion/logout" on the trace network log returns 0. On clearnet
the same chain fits inside those 358 ms, which is why variant 0 passes
there and fails over Tor.

A failure now reports the cookie that survived instead of the missing
password field two lines below, which said nothing about the cause.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-08-22 01:31:08 +02:00
1 parent d48073ac3f
commit 5b6d12f129
1 file changed
+10 -5
@@ -76,11 +76,16 @@ test("administrator: admin login → catalogue → in-app logout", async ({ page
});
await logout.click();
await confirmKeycloakLogoutIfPrompted(page);
await page
.waitForFunction(() => !document.cookie.includes("bearerAuth"), null, {
timeout: resolveTimeout(30_000),
})
.catch(() => {});
await expect
.poll(
async () => (await page.context().cookies()).some((c) => c.name === "bearerAuth"),
{
message:
"web-svc-logout sweeps shop.<domain>/logout from an iframe on Keycloak's logout page; navigating away before that lands leaves the admin cookie alive",
timeout: resolveTimeout(30_000),
},
)
.toBe(false);
await gotoOnion(page, `${appBaseUrl}/admin`, { waitUntil: "domcontentloaded" });
await expect(