1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""JavaScript module tests. Skipped unless pytest is run with --js-tests."""
from __future__ import annotations
import importlib.util
import sys
from collections.abc import Iterator
from pathlib import Path
from types import ModuleType
from typing import Any, cast
import pytest
from pygitweb.static_tests.js_runtime import JsPage, available_engines
class _FileModule(pytest.Module):
def _getobj(self) -> ModuleType:
name = "js_tests_" + self.path.stem.replace("-", "_")
spec = importlib.util.spec_from_file_location(name, self.path)
if spec is None or spec.loader is None:
raise ImportError(f"cannot load {self.path}")
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
@pytest.hookimpl(hookwrapper=True)
def pytest_collect_file(file_path: Path, parent: pytest.Collector) -> object:
outcome = yield
if file_path.suffix != ".py" or not file_path.name.startswith("test_") or "-" not in file_path.name:
return
# pytest 9 gathers every pytest_collect_file result, so the default collector
# would import this hyphenated module a second time.
cast(Any, outcome).force_result([_FileModule.from_parent(parent, path=file_path)])
def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
if "js" not in metafunc.fixturenames:
return
engines = available_engines()
if engines:
metafunc.parametrize("js", engines, indirect=True, ids=engines)
else:
metafunc.parametrize("js", ["none"], indirect=True)
@pytest.fixture
def js(request: pytest.FixtureRequest) -> Iterator[JsPage]:
if request.param == "none":
pytest.skip("No JS engine installed. uv sync --group pythonmonkey or uv sync --group stpyv8")
page = JsPage(str(request.param))
yield page
page.close()