diff --git a/moli-benchmark/README.md b/moli-benchmark/README.md index 28d54f3df0..7d39647285 100644 --- a/moli-benchmark/README.md +++ b/moli-benchmark/README.md @@ -130,7 +130,7 @@ them. The runner waits for load, fonts, two animation frames, and removal of `crashtest` with zero subtests. An outstanding wait remains a timeout, and a renderer crash is reported even when the browser process stays alive. -Run testdriver input cases explicitly with `--mode cdp`. +Explicit cases that reference `testdriver.js` use CDP in `--mode auto`. The CDP runner delivers trusted keyboard and mouse/pen input on an independent connection, so input can finish while a harness probe awaits a JavaScript promise. It supports `click`, ASCII and WebDriver special keys in `send_keys`, diff --git a/moli-benchmark/moli_benchmark/wpt_cross/__main__.py b/moli-benchmark/moli_benchmark/wpt_cross/__main__.py index 90d3e86f20..2ba4d7c55f 100644 --- a/moli-benchmark/moli_benchmark/wpt_cross/__main__.py +++ b/moli-benchmark/moli_benchmark/wpt_cross/__main__.py @@ -28,6 +28,7 @@ import time from collections import Counter from pathlib import Path from typing import Any +from urllib.parse import urlsplit from .case_set import ( ANY_JS_GLOBAL_CHOICES, @@ -57,6 +58,22 @@ from ..config import clear_current_proxy_env REPO_CASE_LIST_DIR = Path(__file__).resolve().parents[2] / "wpt-cross-current" WPT_CROSS_CASE_TIMEOUT_SECONDS = 120.0 WPT_CROSS_PARALLELISM = 50 + + +def _case_references_testdriver(wpt_root: Path, case: WptCase) -> bool: + path = urlsplit(case.case_path).path.lstrip("/") + for suffix, source_suffix in ((".any.html", ".any.js"), (".window.html", ".window.js")): + if path.endswith(suffix): + path = path.removesuffix(suffix) + source_suffix + break + source = (wpt_root / path).resolve() + try: + source.relative_to(wpt_root.resolve()) + return b"/resources/testdriver" in source.read_bytes() + except (OSError, ValueError): + return False + + WPT_CROSS_PROFILES = ( "default", "layout-testharness", @@ -664,7 +681,13 @@ def main(argv: list[str] | None = None) -> int: if has_crashtests and args.mode == "cli": print("error: crashtests require CDP mode to observe readiness and crashes", file=sys.stderr) return 4 - requires_cdp = fixed_layout_viewport or has_crashtests + native_input_required = args.mode != "cdp" and any( + _case_references_testdriver(args.wpt_root, case) for case in cases + ) + if native_input_required and args.mode == "cli": + print("error: testdriver cases require CDP mode for native input", file=sys.stderr) + return 4 + requires_cdp = fixed_layout_viewport or has_crashtests or native_input_required if fixed_layout_viewport and args.mode == "cli": print( "error: layout profiles and reftests require CDP mode for fixed viewport screenshots", diff --git a/moli-benchmark/tests/test_wpt_native_input.py b/moli-benchmark/tests/test_wpt_native_input.py index 10b2793827..3dbbd0c496 100644 --- a/moli-benchmark/tests/test_wpt_native_input.py +++ b/moli-benchmark/tests/test_wpt_native_input.py @@ -9,6 +9,7 @@ from types import SimpleNamespace from unittest.mock import AsyncMock from moli_benchmark.raw_cdp import RawCdpConnectionClosed +from moli_benchmark.wpt_cross.__main__ import _case_references_testdriver from moli_benchmark.wpt_cross.case_set import WptCase from moli_benchmark.wpt_cross.native_input import NativeInput, Pointer, key_description @@ -173,6 +174,17 @@ class NativeInputTests(unittest.IsolatedAsyncioTestCase): class NativeInputSelectionTests(unittest.TestCase): + def test_testdriver_detection_in_html_and_generated_variants(self): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + (root / "input.html").write_text('') + (root / "keys.any.js").write_text('// META: script=/resources/testdriver.js\n') + (root / "plain.html").write_text('') + self.assertTrue(_case_references_testdriver(root, WptCase("input.html?variant"))) + self.assertTrue(_case_references_testdriver(root, WptCase("keys.any.html?variant"))) + self.assertFalse(_case_references_testdriver(root, WptCase("plain.html"))) + self.assertFalse(_case_references_testdriver(root, WptCase("../input.html"))) + def test_special_keys_preserve_physical_location(self): self.assertEqual((key_description("\ue007").code, key_description("\ue007").location), ("NumpadEnter", 3)) self.assertEqual((key_description("\ue050").code, key_description("\ue050").location), ("ShiftRight", 2))