ci(mac): wait_for_load_state before change-password form + drop pre-fill shoot
Run 25497245250 / job 74820324136 (commit f3e541d) failed with:
Page.fill: Timeout 60000ms exceeded.
Call log:
- waiting for locator("#new-password")
This was AFTER `page.locator("#new-password").wait_for(state="visible")`
returned successfully. So the element WAS visible at that moment,
then disappeared from the DOM 60s before page.fill could grab it.
Root cause: on macos-14 free runners under --single-process
Chromium, the change-password page's bootstrap-state poll
(/api/auth/status) and React router both finish AFTER wait_for()
returns. If they decide the user is "already authenticated" or
"no longer must change password", the route rerenders and the
#new-password input is unmounted. Page.fill then waits the full
60s for an element that's gone.
Two changes (both playwright_chat_ui.py and playwright_extra_ui.py):
1. Add `page.wait_for_load_state("networkidle", timeout=30_000)`
AFTER page.goto, BEFORE wait_for(). This lets the bootstrap
dispatch settle so the route is committed before we touch the
form. Wrapped in try/except so a slow `networkidle` (e.g. SSE
keepalives) doesn't block forever -- best-effort.
2. Drop the `shoot("01-change-password-initial")` call between
wait_for() and fill(). The screenshot's font-load wait is
another window for the React form to detach. The
`02-change-password-filled` shoot AFTER the fill is sufficient
for diagnostics. Use locator API + explicit per-call timeouts.
This commit is contained in:
parent
f3e541dd12
commit
9bf0c6ff09
2 changed files with 35 additions and 8 deletions
|
|
@ -257,11 +257,30 @@ with sync_playwright() as p:
|
|||
# ─────────────────────────────────────────────────────
|
||||
step("change-password through UI (Setup your account)")
|
||||
page.goto(f"{BASE}/change-password")
|
||||
page.locator("#new-password").wait_for(state = "visible", timeout = 60_000)
|
||||
shoot("01-change-password-initial")
|
||||
page.fill("#new-password", NEW)
|
||||
page.fill("#confirm-password", NEW)
|
||||
shoot("02-change-password-filled")
|
||||
# Wait for the network to settle before touching the form. Without
|
||||
# this, on macos-14 free runners under --single-process Chromium,
|
||||
# the page sometimes redirects mid-test (the bootstrap state poll
|
||||
# finishes after wait_for() returns, the React router decides
|
||||
# we're "already authenticated" or "no longer must-change", and
|
||||
# rerenders without #new-password). Letting the network idle first
|
||||
# gives the bootstrap dispatch a chance to settle BEFORE we
|
||||
# commit to the form path. Run 25497245250 / job 74820324136
|
||||
# showed this exact sequence: wait_for() returned then
|
||||
# page.fill('#new-password') timed out 60s later because the
|
||||
# form had been replaced.
|
||||
try:
|
||||
page.wait_for_load_state("networkidle", timeout = 30_000)
|
||||
except Exception:
|
||||
pass # best-effort -- proceed even if network never idles
|
||||
pw_field = page.locator("#new-password")
|
||||
pw_field.wait_for(state = "visible", timeout = 60_000)
|
||||
# NOTE: do NOT call shoot() between wait_for and fill -- the
|
||||
# screenshot's font-load wait gives the React form a chance to
|
||||
# detach if any background state-poll fires. Take screenshots
|
||||
# AFTER the form is committed instead.
|
||||
pw_field.fill(NEW, timeout = 60_000)
|
||||
page.fill("#confirm-password", NEW, timeout = 60_000)
|
||||
shoot("01-change-password-filled")
|
||||
page.locator('button[type="submit"]').click()
|
||||
|
||||
# ─────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -182,9 +182,17 @@ with sync_playwright() as p:
|
|||
# ─────────────────────────────────────────────────────
|
||||
step("setup: change-password + model load")
|
||||
page.goto(f"{BASE}/change-password")
|
||||
page.locator("#new-password").wait_for(state = "visible", timeout = 60_000)
|
||||
page.fill("#new-password", NEW)
|
||||
page.fill("#confirm-password", NEW)
|
||||
# See playwright_chat_ui.py -- wait for networkidle before
|
||||
# touching the form to dodge the bootstrap-poll-induced
|
||||
# rerender on slow macos-14 runners.
|
||||
try:
|
||||
page.wait_for_load_state("networkidle", timeout = 30_000)
|
||||
except Exception:
|
||||
pass
|
||||
pw_field = page.locator("#new-password")
|
||||
pw_field.wait_for(state = "visible", timeout = 60_000)
|
||||
pw_field.fill(NEW, timeout = 60_000)
|
||||
page.fill("#confirm-password", NEW, timeout = 60_000)
|
||||
page.locator('button[type="submit"]').click()
|
||||
composer = page.locator('textarea[aria-label="Message input"]')
|
||||
composer.wait_for(state = "visible", timeout = 60_000)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue