Files
teng-lin--notebooklm-py/tests/unit/test_playwright_marker_hook.py
wehub-resource-sync 09e9f3545f
Test / Code Quality (push) Has been cancelled
Test / Test (macos-latest, Python 3.10) (push) Has been cancelled
Test / Test (macos-latest, Python 3.11) (push) Has been cancelled
Test / Test (macos-latest, Python 3.12) (push) Has been cancelled
Test / Test (macos-latest, Python 3.13) (push) Has been cancelled
Test / Test (macos-latest, Python 3.14) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.10) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.11) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.12) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.13) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.14) (push) Has been cancelled
Test / Test (windows-latest, Python 3.10) (push) Has been cancelled
Test / Test (windows-latest, Python 3.11) (push) Has been cancelled
Test / Test (windows-latest, Python 3.12) (push) Has been cancelled
Test / Test (windows-latest, Python 3.13) (push) Has been cancelled
Test / Test (windows-latest, Python 3.14) (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
dependency-audit / pip-audit (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:30:13 +08:00

136 lines
4.3 KiB
Python

"""pytester regression test for the ``requires_playwright`` marker hook.
``tests/conftest.py`` registers a ``pytest_collection_modifyitems`` hook that
auto-skips items carrying ``@pytest.mark.requires_playwright`` when the
``playwright`` Python package is not installed. This file pins that behavior
end-to-end via ``pytester`` so the hook does not silently regress.
Three scenarios:
1. **Playwright installed** — a marked test runs normally (no skip).
2. **Playwright missing** — the same marked test is skipped with the
install-hint reason.
3. **Playwright missing + unmarked test** — the hook leaves it alone.
Each scenario builds a self-contained synthetic project via ``pytester`` and
inlines a faithful copy of the hook so the regression test does NOT depend on
importing the real conftest. The inlined hook is kept in lockstep with the
real one — if the production hook's detection logic changes, update
``HOOK_SOURCE`` here too.
"""
from __future__ import annotations
import textwrap
import pytest
pytest_plugins = ["pytester"]
# Faithful copy of the hook + the ``_PLAYWRIGHT_INSTALLED`` constant from
# ``tests/conftest.py``. The constant is parameterized via an env var so the
# scenarios below can flip it without mutating the real module. The
# production constant uses ``importlib.util.find_spec("playwright")`` — a
# pure boolean, equivalently shaped by the env var here.
HOOK_SOURCE = textwrap.dedent(
"""
import os
import pytest
_PLAYWRIGHT_INSTALLED = os.environ.get("FAKE_PLAYWRIGHT_INSTALLED") == "1"
def pytest_configure(config):
config.addinivalue_line(
"markers", "requires_playwright: skip when playwright is missing"
)
def pytest_collection_modifyitems(config, items):
if _PLAYWRIGHT_INSTALLED:
return
skip_marker = pytest.mark.skip(
reason="playwright not installed; install with: uv sync --extra browser"
)
for item in items:
if "requires_playwright" in item.keywords:
item.add_marker(skip_marker)
"""
).strip()
MARKED_TEST = textwrap.dedent(
"""
import pytest
@pytest.mark.requires_playwright
def test_marked():
assert True
"""
).strip()
UNMARKED_TEST = textwrap.dedent(
"""
def test_unmarked():
assert True
"""
).strip()
PYTEST_INI = textwrap.dedent(
"""
[pytest]
asyncio_default_fixture_loop_scope = function
"""
).strip()
def _scaffold(pytester: pytest.Pytester, *, test_body: str) -> None:
pytester.makeini(PYTEST_INI)
# ``pytester.makepyfile`` appends ``.py`` internally via
# ``Path.with_suffix(".py")``, so keys are passed *without* the
# extension (idiomatic per the pytest docs).
pytester.makepyfile(conftest=HOOK_SOURCE, test_under_test=test_body)
def test_marker_is_noop_when_playwright_installed(
pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch
) -> None:
"""``_PLAYWRIGHT_INSTALLED = True`` → marked test runs normally."""
monkeypatch.setenv("FAKE_PLAYWRIGHT_INSTALLED", "1")
_scaffold(pytester, test_body=MARKED_TEST)
result = pytester.runpytest("-v")
assert result.ret == 0
result.assert_outcomes(passed=1)
def test_marker_skips_when_playwright_missing(
pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch
) -> None:
"""``_PLAYWRIGHT_INSTALLED = False`` → marked test is skipped with the install hint."""
monkeypatch.setenv("FAKE_PLAYWRIGHT_INSTALLED", "0")
_scaffold(pytester, test_body=MARKED_TEST)
result = pytester.runpytest("-v", "-rs")
assert result.ret == 0
result.assert_outcomes(skipped=1)
# Skip reason must surface the install hint so users know how to enable.
assert "uv sync --extra browser" in result.stdout.str()
def test_unmarked_test_unaffected_when_playwright_missing(
pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch
) -> None:
"""The hook only touches marked items — unmarked tests run regardless.
Guards against the hook accidentally over-reaching to every test in the
suite when playwright is missing.
"""
monkeypatch.setenv("FAKE_PLAYWRIGHT_INSTALLED", "0")
_scaffold(pytester, test_body=UNMARKED_TEST)
result = pytester.runpytest("-v")
assert result.ret == 0
result.assert_outcomes(passed=1)