Skip to content

Commit 1d87d76

Browse files
simonorzel26claude
andauthored
fix(e2e): assert the journey lander contract that #127 shipped (#128)
#127 made an anonymous hit on the /journey root land on /start instead of the signin form, but left e2e/smoke.spec.ts asserting the old contract. That PR was merged 100 seconds after opening while its checks were still pending, and its e2e run went red afterwards. e2e.yml triggers on pull_request only, never on push to main, so nothing re-ran and nothing reported it. main has been shipping a behavior its own suite contradicts, and every PR opened since inherits the failure: #125 and #126 are pure bun.lock changes and both fail on this test. The code is right and the test was stale, so the test moves. Splits the unauthenticated case in two rather than just repointing the URL. ANONYMOUS_LANDERS in proxy.ts is keyed on the exact stripped path, so /journey diverts to /start while every deeper app URL still walls to signin with callbackUrl preserved. Asserting only the lander would stop proving anything about auth, which is what the original test was for; asserting only the wall would not notice the lander regressing back to a login form. /de/risks covers the second half and is already exercised elsewhere in the suite. de is the default locale under localePrefix "as-needed", so the lander target carries no locale prefix: /de/journey resolves to /start. Not verified locally: the suite needs Postgres, a seeded database and a production build, so CI is the check here. Claude-Session: https://claude.ai/code/session_01J93t7LS29yZq2app1Pqsmn Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent cfd69b0 commit 1d87d76

1 file changed

Lines changed: 31 additions & 6 deletions

File tree

e2e/smoke.spec.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,43 @@ test("journey renders all 49 NIS2 requirement nodes", async ({ page }) => {
1313
});
1414

1515
/**
16-
* Proves the smoke above is not passing vacuously: without the session,
17-
* the default-deny middleware must bounce /journey to the signin form.
16+
* Proves the smoke above is not passing vacuously: without a session the
17+
* journey must not render.
18+
*
19+
* How that is enforced for the /journey root changed in #127. Anonymous
20+
* visitors used to meet the signin form; they now land on /start, the
21+
* public pre-login page, because /start had recorded zero visits while
22+
* nothing linked to it. Default-deny is unchanged everywhere else:
23+
* ANONYMOUS_LANDERS in proxy.ts is keyed on the exact stripped path, so
24+
* only the root is diverted and every deeper app URL still walls to
25+
* signin with callbackUrl preserved.
26+
*
27+
* Both halves are asserted. The lander on its own no longer proves
28+
* anything about auth, and the wall on its own would not notice the
29+
* lander regressing back to a login form.
30+
*
31+
* de is the default locale under localePrefix "as-needed", so the lander
32+
* target carries no locale prefix: /de/journey resolves to /start.
1833
*/
1934
test.describe("unauthenticated", () => {
2035
test.use({ storageState: { cookies: [], origins: [] } });
2136

22-
test("journey redirects to signin without a session", async ({ page }) => {
37+
test("the journey root lands anonymous visitors on /start", async ({
38+
page,
39+
}) => {
2340
await page.goto("/de/journey");
41+
await page.waitForURL(/\/start$/, { timeout: 15_000 });
42+
await expect(page.locator('[data-testid^="journey-node-"]')).toHaveCount(
43+
0,
44+
);
45+
});
46+
47+
test("a deeper app URL still walls to signin with callbackUrl", async ({
48+
page,
49+
}) => {
50+
await page.goto("/de/risks");
2451
await page.waitForURL(/\/auth\/signin/, { timeout: 15_000 });
52+
expect(page.url()).toContain("callbackUrl");
2553
await expect(page.locator("#email")).toBeVisible();
26-
await expect(
27-
page.locator('[data-testid^="journey-node-"]'),
28-
).toHaveCount(0);
2954
});
3055
});

0 commit comments

Comments
 (0)