mirror of
https://github.com/feder-cr/invisible_playwright.git
synced 2026-06-07 08:35:12 +02:00
test(e2e): add 4 Linux launcher-routing tests for Phase 9
E9-E12 exercise the launcher's Linux code paths without spawning a real Firefox binary or Xvfb. They monkeypatch ``sys.platform`` and stub ``make_virtual_display`` / ``_binary_on_path`` so the tests run on any host: - E9 ``_build_prefs(headless=True)`` on Linux passes ``virtual_display=False`` to the translator, so the Win32-only ``security.sandbox.gpu.level`` workaround never leaks into Linux prefs (Xvfb handles window hiding instead). - E10 ``_resolve_headless`` on Linux + headless=True invokes the dispatcher and stores the returned object on ``self._virtual_display``. - E11 ``_teardown`` stops the Linux virtual display, clears the reference, and is idempotent on a second call. - E12 With Xvfb missing from PATH, ``_resolve_headless`` raises a clear ``RuntimeError`` mentioning ``Xvfb`` instead of a cryptic FileNotFoundError. Suite on Linux/WSL: 286 passed, 5 skipped (4 binary-gated E2E lifecycle tests + 1 Win32 ctypes test). Binary-gated E1/E2/E5/E8 remain ready to run on Linux once the patched Firefox tar.gz is fetched locally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b8139c2873
commit
70c1ca464f
1 changed files with 100 additions and 0 deletions
|
|
@ -141,3 +141,103 @@ def test_e8_new_context_defaults_from_profile(firefox_binary):
|
|||
assert vp["height"] > 0
|
||||
finally:
|
||||
ctx.close()
|
||||
|
||||
|
||||
# ────────────────────────────────────────────────────────────────────
|
||||
# Linux-specific lifecycle tests (no Firefox binary required).
|
||||
#
|
||||
# These exercise the launcher's Linux code paths without spawning real
|
||||
# Firefox or Xvfb. They monkeypatch ``sys.platform`` and (where needed)
|
||||
# the ``make_virtual_display`` dispatcher so the tests run on any host
|
||||
# — including Windows hosts that ship the production CI for this repo.
|
||||
# ────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@pytest.mark.e2e
|
||||
def test_e9_linux_build_prefs_omits_windows_sandbox_key(monkeypatch):
|
||||
"""E9: ``_build_prefs(headless=True)`` on Linux must pass
|
||||
``virtual_display=False`` to the prefs translator. The Win32-only
|
||||
``security.sandbox.gpu.level`` workaround targets the alt-desktop
|
||||
GPU sandbox bug and MUST NOT leak into Linux prefs, where Xvfb
|
||||
handles window hiding instead."""
|
||||
import sys as _sys
|
||||
monkeypatch.setattr(_sys, "platform", "linux")
|
||||
ip = InvisiblePlaywright(seed=42, headless=True)
|
||||
prefs = ip._build_prefs()
|
||||
assert "security.sandbox.gpu.level" not in prefs
|
||||
|
||||
|
||||
@pytest.mark.e2e
|
||||
def test_e10_linux_resolve_headless_invokes_xvfb_dispatcher(monkeypatch):
|
||||
"""E10: ``_resolve_headless`` with ``headless=True`` on Linux must
|
||||
call ``make_virtual_display().start()`` and store the result on
|
||||
``self._virtual_display``. We stub the dispatcher so no real Xvfb
|
||||
is spawned — the dispatcher's platform routing is covered separately
|
||||
in ``test_headless.py``."""
|
||||
import sys as _sys
|
||||
monkeypatch.setattr(_sys, "platform", "linux")
|
||||
|
||||
events: list[str] = []
|
||||
|
||||
class _FakeDisplay:
|
||||
def start(self) -> None:
|
||||
events.append("start")
|
||||
|
||||
def stop(self) -> None:
|
||||
events.append("stop")
|
||||
|
||||
from invisible_playwright import launcher as _l
|
||||
monkeypatch.setattr(_l, "make_virtual_display", lambda: _FakeDisplay())
|
||||
|
||||
ip = InvisiblePlaywright(seed=42, headless=True)
|
||||
result = ip._resolve_headless()
|
||||
assert result is False
|
||||
assert events == ["start"]
|
||||
assert ip._virtual_display is not None
|
||||
|
||||
|
||||
@pytest.mark.e2e
|
||||
def test_e11_linux_teardown_stops_virtual_display_and_is_idempotent(monkeypatch):
|
||||
"""E11: ``_teardown`` stops the Linux virtual display, clears the
|
||||
reference, and a second invocation is a no-op. Guards the cleanup
|
||||
path used by ``__exit__`` so a failed ``__enter__`` cannot leak Xvfb."""
|
||||
import sys as _sys
|
||||
monkeypatch.setattr(_sys, "platform", "linux")
|
||||
|
||||
stops: list[bool] = []
|
||||
|
||||
class _FakeDisplay:
|
||||
def start(self) -> None:
|
||||
pass
|
||||
|
||||
def stop(self) -> None:
|
||||
stops.append(True)
|
||||
|
||||
from invisible_playwright import launcher as _l
|
||||
monkeypatch.setattr(_l, "make_virtual_display", lambda: _FakeDisplay())
|
||||
|
||||
ip = InvisiblePlaywright(seed=42, headless=True)
|
||||
ip._resolve_headless()
|
||||
ip._teardown()
|
||||
assert stops == [True]
|
||||
assert ip._virtual_display is None
|
||||
ip._teardown()
|
||||
assert stops == [True]
|
||||
|
||||
|
||||
@pytest.mark.e2e
|
||||
def test_e12_linux_resolve_headless_without_xvfb_raises_clear_error(monkeypatch):
|
||||
"""E12: On Linux with ``headless=True`` and ``Xvfb`` missing from
|
||||
``PATH``, ``_resolve_headless`` must surface a clear, actionable
|
||||
``RuntimeError`` instead of a cryptic FileNotFoundError. Verifies
|
||||
the early-check path in ``_LinuxVirtualDisplay.start``."""
|
||||
import sys as _sys
|
||||
monkeypatch.setattr(_sys, "platform", "linux")
|
||||
|
||||
from invisible_playwright import _headless as _h
|
||||
monkeypatch.setattr(_h, "_binary_on_path", lambda name: False)
|
||||
|
||||
ip = InvisiblePlaywright(seed=42, headless=True)
|
||||
with pytest.raises(RuntimeError, match="Xvfb"):
|
||||
ip._resolve_headless()
|
||||
assert ip._virtual_display is None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue