fix(e2e): settle hub login form before fill + URL-based 2FA advance signal #409

Merged
nrupard merged 2 commits from fix/PMS-595-chromium-credential-resubmit-settle into main 2026-06-30 16:22:43 +02:00
Member

The PMS-592 chromium credential race fix verified the typed values survived right before the submit click, but run 2874 still failed the same way: on chromium the hub's server-rendered login form re-renders (hydration / htmx swap) in the window between the click and the POST being serialised, so the body went out empty, the hub bounced back to a fresh /login, and re-filling into a form that was itself mid-re-render lost the next attempt identically. firefox/webkit win the race and pass.

Two changes close the race in submitCredentials. First, settle the form before each fill: drain in-flight network from the hydration/swap on a short 3s budget, then give a synchronous client re-render one 300ms frame to land, so we type into the form the hub will actually submit rather than one a frame from being replaced. Second, treat the credential step as consumed on EITHER the password field detaching OR the URL advancing into /login/2fa, raced so it only resolves true on success and false at the per-signal timeout; on chromium the post-submit DOM teardown and the navigation do not always land in the same order, so a single DOM-only signal flapped. Bumped the retry budget from 3 to 4 for a little margin now that each attempt converges.

tsc --noEmit and just check both green; the chromium form-validation e2e can only be exercised by the CI run against staging.

#PMS-595

The PMS-592 chromium credential race fix verified the typed values survived right before the submit click, but run 2874 still failed the same way: on chromium the hub's server-rendered login form re-renders (hydration / htmx swap) in the window between the click and the POST being serialised, so the body went out empty, the hub bounced back to a fresh `/login`, and re-filling into a form that was itself mid-re-render lost the next attempt identically. firefox/webkit win the race and pass. Two changes close the race in `submitCredentials`. First, settle the form before each fill: drain in-flight network from the hydration/swap on a short 3s budget, then give a synchronous client re-render one 300ms frame to land, so we type into the form the hub will actually submit rather than one a frame from being replaced. Second, treat the credential step as consumed on EITHER the password field detaching OR the URL advancing into `/login/2fa`, raced so it only resolves true on success and false at the per-signal timeout; on chromium the post-submit DOM teardown and the navigation do not always land in the same order, so a single DOM-only signal flapped. Bumped the retry budget from 3 to 4 for a little margin now that each attempt converges. tsc --noEmit and `just check` both green; the chromium form-validation e2e can only be exercised by the CI run against staging. #PMS-595
fix(e2e): recover chromium SPA login from credential-form re-render race
Some checks failed
Check / fmt + clippy + build + tests (pull_request) Failing after 4s
Integration / integration tests (pull_request) Failing after 7s
E2E / Playwright against staging (pull_request) Failing after 1m16s
Create release / Gate (release-branch merges only) (pull_request) Successful in 0s
Create release / Create release from merged PR (pull_request) Has been skipped
026120bb9b
The chromium form-validation run on PR #407 (run 2871) timed out with the SPA login stuck on a bare `/login`, never reaching `/login/2fa`, while `setup` (same loginViaSpa, same Desktop Chrome, 2s earlier), firefox, and webkit all logged in fine. The captured URL trail ends with a full frame navigation back to a bare `/login` (the `?redirect=...&checked=1` query dropped), which is the bunyip hub rejecting a credential POST and 302'ing to a fresh form: the server-rendered hub form re-rendered between `fill` and `click`, the click POSTed an empty form, and the helper then polled a never-submitted form until the 30s timeout. chromium lost that race; the other engines won it.

Harden the credential step: verify the typed email/password values survived right before clicking, and confirm the password field leaves the DOM after submit (the hub advancing to 2FA / onward). If either check fails, the form was re-rendered out from under us, so re-fill the freshly-rendered form and submit again (up to 3 attempts) instead of charging ahead with an empty POST. firefox/webkit/setup, which already win the race, take the same fast path with no behavior change.

#PMS-592
fix(e2e): settle hub login form before fill + URL-based 2FA advance signal
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 37s
Check / fmt + clippy + build + tests (pull_request) Successful in 1m34s
Create release / Gate (release-branch merges only) (pull_request) Successful in 1s
Create release / Create release from merged PR (pull_request) Has been skipped
Integration / integration tests (pull_request) Successful in 5m39s
4cf23bda07
The PMS-592 chromium credential race fix verified the typed values survived right before the submit click, but run 2874 still failed the same way: on chromium the hub's server-rendered login form re-renders (hydration / htmx swap) in the window between the click and the POST being serialised, so the body went out empty, the hub bounced back to a fresh `/login`, and re-filling into a form that was itself mid-re-render lost the next attempt identically. firefox/webkit win the race and pass.

Two changes close the race in `submitCredentials`. First, settle the form before each fill: drain in-flight network from the hydration/swap on a short 3s budget, then give a synchronous client re-render one 300ms frame to land, so we type into the form the hub will actually submit rather than one a frame from being replaced. Second, treat the credential step as consumed on EITHER the password field detaching OR the URL advancing into `/login/2fa`, raced so it only resolves true on success and false at the per-signal timeout; on chromium the post-submit DOM teardown and the navigation do not always land in the same order, so a single DOM-only signal flapped. Bumped the retry budget from 3 to 4 for a little margin now that each attempt converges.

tsc --noEmit and `just check` both green; the chromium form-validation e2e can only be exercised by the CI run against staging.

#PMS-595
nrupard deleted branch fix/PMS-595-chromium-credential-resubmit-settle 2026-06-30 16:22:44 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!409
No description provided.