fix: blocked autoplay left 'Loading…' parked over unreachable controls

The overlay only clears on 'playing', which never fires when the browser
blocks autoplay — and the overlay covers the native controls, so the
'swap to the native play button' assumption from the click-to-play
removal never held. A rejected v.play() is the signal: swap the dead
Loading… overlay for a tappable one (Play), and a second rejection
escalates to the Playback failed overlay.

Browser test fakes the policy (reject first gesture-less play()) since
headless Chromium allows autoplay. Logs showed the shape of it: six
loads of the same ep, 38-40 segments each, all 200, player never started.
This commit is contained in:
jozamudi committed 2026-08-24 02:51:05 +00:00
1 parent aae5857dba
commit db715be54b
2 files changed
+57 -5

No files matched your search

+47
View File
@@ -278,3 +278,50 @@ async def _episode_watch_state():
await page.wait_for_selector("#eps .ep.nextup", timeout=10000)
assert not errors, errors
await browser.close()
def test_autoplay_blocked_shows_tap_to_play():
asyncio.run(_autoplay_blocked())
async def _autoplay_blocked():
# Simulates the browser's autoplay policy (headless Chromium here allows
# autoplay, so the policy is faked): the first, gesture-less play()
# rejects; a later user-initiated one goes through. Regression: the
# "Loading…" overlay (which only clears on 'playing') used to sit over
# the unreachable native controls forever in that state.
async with async_playwright() as p:
browser = await p.chromium.launch()
context = await browser.new_context()
await context.add_init_script("""
const origPlay = HTMLMediaElement.prototype.play;
HTMLMediaElement.prototype.play = function () {
if (window.__firstPlayBlocked) {
window.__firstPlayBlocked = false;
return Promise.reject(new DOMException('blocked', 'NotAllowedError'));
}
return origPlay.call(this);
};
window.__firstPlayBlocked = true;
""")
page = await context.new_page()
errors = []
page.on("pageerror", lambda e: errors.append(str(e)))
await _login(page, "admin", "adminpw12345")
await page.goto(BASE + "/?anime=chainsaw-man-922")
await page.wait_for_selector("#eps .ep", timeout=30000)
# blocked autoplay: the dead "Loading…" must become a tappable overlay
await page.wait_for_function(
"document.querySelector('.pl-overlay') && "
"document.querySelector('.pl-overlay').textContent.includes('Tap to play')",
timeout=15000, polling=POLL)
# tapping (the gesture) starts real playback
await page.click(".pl-overlay .btn", force=True)
await page.wait_for_function(
"document.querySelector('video').currentTime > 0.5",
timeout=120000, polling=250)
assert not errors, errors
await browser.close()