ci: drive gate uses arrow-function evaluates (fixes win-CI eval-CSP block)

windows-latest failed both attempts with "Page.evaluate: call to eval() blocked
by CSP". Bare-string evaluates (page.evaluate("navigator.userAgent")) make
Playwright fall back to eval(), which a page CSP blocks. Pass arrow functions
instead (called via callFunction, never eval'd), and wire the click listener
with addEventListener instead of an inline onclick (also CSP-sensitive). Both
are Playwright best practice and platform-agnostic.
This commit is contained in:
feder-cr
2026-06-09 14:47:02 +02:00
parent 610f09d2c2
commit 2dd2224e73
+19 -11
View File
@@ -48,9 +48,11 @@ import sys
from playwright.sync_api import sync_playwright from playwright.sync_api import sync_playwright
# DOM built on about:blank (no data: URL to re-normalize → no spurious nav). # DOM built on about:blank (no data: URL to re-normalize → no spurious nav).
# No inline onclick — inline handlers are CSP-sensitive; we wire the listener
# via addEventListener inside the (function, not eval'd) setup call below.
BODY = ( BODY = (
"<h1 id=x>hello-drive</h1>" "<h1 id=x>hello-drive</h1>"
"<button id=b onclick=\"window.__clicked=1\">go</button>" "<button id=b>go</button>"
"<input id=inp>" "<input id=inp>"
) )
@@ -75,27 +77,33 @@ def _drive(exe: str) -> str:
try: try:
page = browser.new_page() page = browser.new_page()
page.goto("about:blank") # canonical, never re-navigates page.goto("about:blank") # canonical, never re-navigates
# Build the DOM + attach the mousemove counter in one shot. # Build the DOM + wire click/mousemove listeners in one shot. Passed
# as a FUNCTION (Playwright callFunction, not eval) so a page CSP that
# blocks eval()/inline-handlers can't break the gate. All evaluates
# below are arrow functions for the same reason.
page.evaluate( page.evaluate(
"(html) => { document.body.innerHTML = html;" "(html) => {"
" document.body.innerHTML = html;"
" document.getElementById('b').addEventListener('click', () => { window.__clicked = 1; });"
" window.__moves = 0;" " window.__moves = 0;"
" window.addEventListener('mousemove', () => { window.__moves++; }); }", " window.addEventListener('mousemove', () => { window.__moves++; });"
"}",
BODY, BODY,
) )
ua = page.evaluate("navigator.userAgent") ua = page.evaluate("() => navigator.userAgent")
webdriver = page.evaluate("navigator.webdriver") webdriver = page.evaluate("() => navigator.webdriver")
text = page.evaluate("() => document.getElementById('x').textContent") text = page.evaluate("() => document.getElementById('x').textContent")
# firefox-2 / issue-#9 catcher: real mouse + keyboard over juggler. # firefox-2 / issue-#9 catcher: real mouse + keyboard over juggler.
page.wait_for_selector("#b") page.wait_for_selector("#b")
page.mouse.move(20, 20) page.mouse.move(20, 20)
page.mouse.move(120, 90) # exercises synthesizeMouseEvent path page.mouse.move(120, 90) # exercises synthesizeMouseEvent path
page.click("#b") # mousedown/up/click → onclick fires page.click("#b") # mousedown/up/click → listener fires
page.click("#inp") page.click("#inp")
page.keyboard.type("ok") page.keyboard.type("ok")
clicked = page.evaluate("window.__clicked") clicked = page.evaluate("() => window.__clicked")
moves = page.evaluate("window.__moves") moves = page.evaluate("() => window.__moves")
typed = page.evaluate("() => document.getElementById('inp').value") typed = page.evaluate("() => document.getElementById('inp').value")
# stealth-determinism catcher: identical draw → identical dataURL. # stealth-determinism catcher: identical draw → identical dataURL.
@@ -103,8 +111,8 @@ def _drive(exe: str) -> str:
canvas_b = page.evaluate(CANVAS_DRAW) canvas_b = page.evaluate(CANVAS_DRAW)
# BotD navigator-surface tells (proxy-free subset). # BotD navigator-surface tells (proxy-free subset).
langs = page.evaluate("navigator.languages.length") langs = page.evaluate("() => navigator.languages.length")
plugins = page.evaluate("navigator.plugins instanceof PluginArray") plugins = page.evaluate("() => navigator.plugins instanceof PluginArray")
finally: finally:
browser.close() browser.close()