tests: fix rAF-stall flakes in headless chromium; login form submits on Enter

Headless Chromium 151 stops generating animation frames on idle pages,
which stalls Playwright's rAF-based waits (wait_for_function default
polling, click actionability 'stable' check). Fixes:
- wait_for_function: explicit timer polling (100ms/250ms)
- video readyState wait: 120s (cold upstream/CDN starts)
- .card click: force=True
- login: form submit handler (Enter key works, was button-only)
- test asserts the seeded entry, not a section header that only
  appeared via an API-test side effect
This commit is contained in:
jozamudi committed 2026-08-19 17:17:36 +00:00
1 parent 2efb537edc
commit 2b7eb4cdd1
2 files changed
+19 -11

No files matched your search

+16 -8
View File
@@ -11,6 +11,10 @@ from playwright.async_api import async_playwright
BASE = "http://127.0.0.1:8399"
LAUNCH_ARGS = ["--autoplay-policy=no-user-gesture-required"]
# This headless Chromium stops generating animation frames on idle pages,
# which stalls rAF-based Playwright waits (wait_for_function's default
# polling, click actionability). Poll by timer instead; force the one click.
POLL = 100
async def _login(page, user, pw):
@@ -19,10 +23,14 @@ async def _login(page, user, pw):
assert "create account" not in await page.content(), "self-signup UI must be absent"
await page.fill("#user", user)
await page.fill("#pw", pw)
await page.click("#go")
# Enter instead of clicking #go: this playwright/chromium combo's
# "element stable" actionability check hangs non-deterministically;
# fill() leaves focus on the field, so a bare keypress submits.
await page.keyboard.press("Enter")
await page.wait_for_selector("#q", timeout=15000)
await page.wait_for_function(
f"document.getElementById('me').textContent.includes('{user}')", timeout=5000)
f"document.getElementById('me').textContent.includes('{user}')",
timeout=5000, polling=POLL)
async def test_login_ui():
@@ -40,14 +48,14 @@ async def test_login_ui():
# wrong password -> inline error
await page.fill("#user", "admin")
await page.fill("#pw", "wrong")
await page.click("#go")
await page.keyboard.press("Enter")
await page.wait_for_function("document.querySelector('#err').textContent.length > 0",
timeout=10000)
timeout=10000, polling=POLL)
assert "wrong" in await page.inner_text("#err")
# correct -> home with user chip
await page.fill("#pw", "adminpw12345")
await page.click("#go")
await page.keyboard.press("Enter")
await _login_settled(page)
assert await page.inner_text("#me") == "hi, admin"
assert "Seed Anime" in await page.inner_text("#main"), "seeded history must show"
@@ -59,7 +67,7 @@ async def test_login_ui():
async def _login_settled(page):
await page.wait_for_selector("#q", timeout=15000)
await page.wait_for_function(
"document.getElementById('me').textContent.length > 0", timeout=5000)
"document.getElementById('me').textContent.length > 0", timeout=5000, polling=POLL)
async def test_video_plays_behind_auth():
@@ -74,11 +82,11 @@ async def test_video_plays_behind_auth():
await page.fill("#q", "chainsaw")
await page.keyboard.press("Enter")
await page.wait_for_selector(".card", timeout=30000)
await page.click(".card")
await page.click(".card", force=True)
await page.wait_for_selector("video", timeout=30000)
await page.wait_for_function(
"document.querySelector('video').readyState >= 4 && document.querySelector('video').currentTime > 1",
timeout=60000)
timeout=120000, polling=250) # 120s: cold CDN/upstream starts can be slow
real_errors = [e for e in errors if "401" not in e]
assert not real_errors, real_errors
await browser.close()