diff --git a/render/src/pixelrag_render/chrome.py b/render/src/pixelrag_render/chrome.py index e2a44d6..bcae582 100644 --- a/render/src/pixelrag_render/chrome.py +++ b/render/src/pixelrag_render/chrome.py @@ -16,6 +16,7 @@ import json import os import platform +import re import subprocess import sys import tarfile @@ -34,6 +35,17 @@ ) +def _playwright_revision(path: str) -> int: + """Integer Playwright Chromium revision embedded in ``path``. + + Playwright caches browsers under ``chromium-`` with a plain + monotonically-increasing integer revision. Paths without a recognizable + revision sort last (``-1``) rather than raising. + """ + m = re.search(r"chromium-(\d+)", path) + return int(m.group(1)) if m else -1 + + def _candidate_chrome_paths(system: str | None = None) -> list[str]: """Ordered Chrome binary candidates for the given OS (default: this OS). @@ -55,8 +67,11 @@ def _candidate_chrome_paths(system: str | None = None) -> list[str]: paths.append(str(INSTALL_DIR / "headless_shell")) def add_playwright(cache_dir: Path, rel_glob: str) -> None: - # Newest chromium-NNNN first. - paths.extend(sorted(glob.glob(str(cache_dir / rel_glob)), reverse=True)) + # Newest chromium-NNNN first. Sort by integer revision, not lexically: + # a string sort ranks "chromium-999" above "chromium-1187" once the + # revision crosses the 3→4 digit boundary, picking an older browser. + matches = glob.glob(str(cache_dir / rel_glob)) + paths.extend(sorted(matches, key=_playwright_revision, reverse=True)) if system == "Darwin": add_playwright( diff --git a/tests/test_chrome_paths.py b/tests/test_chrome_paths.py index 41037d7..7c54b55 100644 --- a/tests/test_chrome_paths.py +++ b/tests/test_chrome_paths.py @@ -31,3 +31,30 @@ def test_find_chrome_returns_executable(): # On any supported dev box this resolves to an installed/usable binary. path = find_chrome() assert os.path.isfile(path) and os.access(path, os.X_OK) + + +def test_playwright_chromium_sorted_by_revision_not_lexically(monkeypatch): + """Newer Playwright Chromium revisions must rank ahead of older ones. + + Playwright caches browsers under ``chromium-`` with a plain + integer revision. A lexicographic sort ranks ``chromium-999`` above + ``chromium-1187`` once revisions cross the 3→4 digit boundary, so the + resolver would pick an *older* browser. Sorting by integer revision fixes + that — assert the candidate list is newest-first regardless of digit count. + """ + import glob + + found = [ + "/home/u/.cache/ms-playwright/chromium-999/chrome-linux/chrome", + "/home/u/.cache/ms-playwright/chromium-1208/chrome-linux/chrome", + "/home/u/.cache/ms-playwright/chromium-1187/chrome-linux/chrome", + ] + monkeypatch.setattr(glob, "glob", lambda pattern: list(found)) + + paths = _candidate_chrome_paths("Linux") + revisions = [p for p in paths if "ms-playwright" in p] + assert revisions == [ + "/home/u/.cache/ms-playwright/chromium-1208/chrome-linux/chrome", + "/home/u/.cache/ms-playwright/chromium-1187/chrome-linux/chrome", + "/home/u/.cache/ms-playwright/chromium-999/chrome-linux/chrome", + ]