What happened
tests/e2e/helpers.ts's ensureWelcomePortalEntry() failed 3 times in a row on 2026-09-02/03 (PR #587's own run, and twice on main post-merge at commit c1a728bf), always the same test: onboarding-entry-precondition.spec.ts:18 ("reaches the entry point when a non-English language is already persisted", Mobile Chrome), always the same locator timeout on [data-tour="nav-mobile"] >> role=button[name=/More/i].
None of the failing commits touched any app or test source (PR #587 was a pnpm-workspace.yaml/pnpm-lock.yaml/AUDIT.md-only dependency-floor bump), which ruled out a code regression from that PR specifically.
Actual root cause (from the Playwright error-context accessibility snapshot)
The test persists worldscript-language: 'es' before navigating. The helper's contract (per its own comment) is meant to be locale-independent, but its fallback path is not:
// helpers.ts:188-213 (ensureWelcomePortalEntry)
if (await portal.isVisible({ timeout: 3000 }).catch(() => false)) return;
// force English before the locale-dependent recovery flow below...
await page.evaluate(() => localStorage.setItem('worldscript-language', 'en'));
await page.reload();
await waitForSpaReady(page);
if (await portal.isVisible({ timeout: 3000 }).catch(() => false)) return;
await waitForMainChrome(page);
await clickNavItem(page, /Settings/i); // <- fails here
await page.getByRole('button', { name: /Data & Backups|Daten & Backups/i })...
await page.getByRole('button', { name: /Factory Reset|Werkseinstellungen/i })...
await page.getByRole('button', { name: /Delete everything & restart|Alles löschen & neu starten/i })...
The recovery branch (used when a pre-existing/leftover project causes the app to land in the main shell instead of the WelcomePortal — the helper's own comment calls this "its own internal-reload race", i.e. a known, accepted, low-probability contingency) tries to force English via localStorage.setItem + page.reload(), then drives Factory Reset through English/German-only button-name regexes. The captured accessibility snapshot at the failure point shows the UI still fully rendered in Spanish ("Panel", "Manuscrito", "Más", ...) — the forced-English reload did not actually take effect before clickNavItem ran, so it searches for /More/i against a button labeled "Más" and never finds it. This will deterministically fail for any persisted locale other than English/German, every time the rare internal-reload race triggers.
This is pre-existing test-infrastructure debt, not something introduced by #587. It manifested 3x on 2026-09-02/03 specifically, plausibly because this session ran an unusually high number of back-to-back full-suite CI runs that day (heavier runner load can increase the probability of the debounced-autosave-vs-reload race the comment already documents), but the underlying bug is real and deterministic once the race triggers, independent of load.
Fix needed
Either:
- Make the forced-English step actually reliable before the Factory-Reset recovery path runs (e.g. wait for the language change to actually apply — check a stable indicator, not just
page.reload() timing — before proceeding), or
- Make the Factory-Reset recovery path itself locale-independent (match by stable
data-testid/aria-label keys rather than translated button text, consistent with how the rest of this same test file already treats welcome-portal as the stable, locale-independent success signal).
Non-goals
- Do not weaken the test's actual coverage (it should still prove a fresh WelcomePortal is reached regardless of persisted locale).
- Do not just increase timeouts as a workaround — the button is never going to say "More" in Spanish no matter how long you wait.
What happened
tests/e2e/helpers.ts'sensureWelcomePortalEntry()failed 3 times in a row on 2026-09-02/03 (PR #587's own run, and twice onmainpost-merge at commitc1a728bf), always the same test:onboarding-entry-precondition.spec.ts:18("reaches the entry point when a non-English language is already persisted", Mobile Chrome), always the same locator timeout on[data-tour="nav-mobile"] >> role=button[name=/More/i].None of the failing commits touched any app or test source (PR #587 was a
pnpm-workspace.yaml/pnpm-lock.yaml/AUDIT.md-only dependency-floor bump), which ruled out a code regression from that PR specifically.Actual root cause (from the Playwright error-context accessibility snapshot)
The test persists
worldscript-language: 'es'before navigating. The helper's contract (per its own comment) is meant to be locale-independent, but its fallback path is not:The recovery branch (used when a pre-existing/leftover project causes the app to land in the main shell instead of the WelcomePortal — the helper's own comment calls this "its own internal-reload race", i.e. a known, accepted, low-probability contingency) tries to force English via
localStorage.setItem+page.reload(), then drives Factory Reset through English/German-only button-name regexes. The captured accessibility snapshot at the failure point shows the UI still fully rendered in Spanish ("Panel", "Manuscrito", "Más", ...) — the forced-English reload did not actually take effect beforeclickNavItemran, so it searches for/More/iagainst a button labeled "Más" and never finds it. This will deterministically fail for any persisted locale other than English/German, every time the rare internal-reload race triggers.This is pre-existing test-infrastructure debt, not something introduced by #587. It manifested 3x on 2026-09-02/03 specifically, plausibly because this session ran an unusually high number of back-to-back full-suite CI runs that day (heavier runner load can increase the probability of the debounced-autosave-vs-reload race the comment already documents), but the underlying bug is real and deterministic once the race triggers, independent of load.
Fix needed
Either:
page.reload()timing — before proceeding), ordata-testid/aria-labelkeys rather than translated button text, consistent with how the rest of this same test file already treatswelcome-portalas the stable, locale-independent success signal).Non-goals