Skip to content

Commit 0c63629

Browse files
committed
Move test dep configuration out of Pytest and into Hatch
1 parent 02cb5ab commit 0c63629

File tree

5 files changed

+23
-80
lines changed

5 files changed

+23
-80
lines changed

pyproject.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ artifacts = []
8888
#############################
8989
# >>> Hatch Test Runner <<< #
9090
#############################
91+
[tool.hatch.envs.hatch-test.scripts]
92+
run = [
93+
"hatch --env default build -t wheel",
94+
"playwright install chromium",
95+
"playwright install-deps",
96+
"pytest{env:HATCH_TEST_ARGS:} {args}",
97+
]
9198

9299
[tool.hatch.envs.hatch-test]
93100
extra-dependencies = [
@@ -98,7 +105,6 @@ extra-dependencies = [
98105
"exceptiongroup",
99106
"jsonpointer",
100107
"starlette",
101-
"filelock",
102108
]
103109
features = ["all"]
104110

src/build_scripts/clean_js_dir.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import pathlib
1212
import shutil
1313

14+
print("Cleaning JS source directory...") # noqa: T201
15+
1416
# Get the path to the JS source directory
1517
js_src_dir = pathlib.Path(__file__).parent.parent / "js"
1618
static_output_dir = pathlib.Path(__file__).parent.parent / "reactpy" / "static"

src/reactpy/testing/__init__.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
from reactpy.testing.backend import BackendFixture
2-
from reactpy.testing.common import (
3-
HookCatcher,
4-
StaticEventHandler,
5-
clear_reactpy_web_modules_dir,
6-
poll,
7-
)
2+
from reactpy.testing.common import HookCatcher, StaticEventHandler, poll
83
from reactpy.testing.display import DisplayFixture
94
from reactpy.testing.logs import (
105
LogAssertionError,
@@ -22,6 +17,5 @@
2217
"assert_reactpy_did_log",
2318
"assert_reactpy_did_not_log",
2419
"capture_reactpy_logs",
25-
"clear_reactpy_web_modules_dir",
2620
"poll",
2721
]

src/reactpy/testing/common.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,18 @@
33
import asyncio
44
import inspect
55
import os
6-
import shutil
76
import time
87
from collections.abc import Awaitable, Callable, Coroutine
98
from functools import wraps
109
from typing import Any, Generic, ParamSpec, TypeVar, cast
1110
from uuid import uuid4
1211
from weakref import ref
1312

14-
from reactpy.config import REACTPY_TESTS_DEFAULT_TIMEOUT, REACTPY_WEB_MODULES_DIR
13+
from reactpy.config import REACTPY_TESTS_DEFAULT_TIMEOUT
1514
from reactpy.core._life_cycle_hook import HOOK_STACK, LifeCycleHook
1615
from reactpy.core.events import EventHandler, to_event_handler_function
1716
from reactpy.utils import str_to_bool
1817

19-
20-
def clear_reactpy_web_modules_dir() -> None:
21-
"""Clear the directory where ReactPy stores registered web modules"""
22-
for path in REACTPY_WEB_MODULES_DIR.current.iterdir():
23-
shutil.rmtree(path) if path.is_dir() else path.unlink()
24-
25-
2618
_P = ParamSpec("_P")
2719
_R = TypeVar("_R")
2820

tests/conftest.py

Lines changed: 12 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
from __future__ import annotations
22

3-
import contextlib
43
import os
5-
import subprocess
64

75
import pytest
86
from _pytest.config.argparsing import Parser
9-
from filelock import FileLock
107

118
from reactpy.config import (
129
REACTPY_ASYNC_RENDERING,
@@ -16,7 +13,6 @@
1613
BackendFixture,
1714
DisplayFixture,
1815
capture_reactpy_logs,
19-
clear_reactpy_web_modules_dir,
2016
)
2117
from reactpy.testing.common import GITHUB_ACTIONS
2218

@@ -33,59 +29,6 @@ def pytest_addoption(parser: Parser) -> None:
3329
)
3430

3531

36-
def headless_environ(pytestconfig: pytest.Config):
37-
if (
38-
pytestconfig.getoption("headless")
39-
or os.environ.get("PLAYWRIGHT_HEADLESS") == "1"
40-
or GITHUB_ACTIONS
41-
):
42-
os.environ["PLAYWRIGHT_HEADLESS"] = "1"
43-
return True
44-
return False
45-
46-
47-
def get_lock_dir(tmp_path_factory, worker_id):
48-
if worker_id == "master":
49-
return tmp_path_factory.getbasetemp()
50-
return tmp_path_factory.getbasetemp().parent
51-
52-
53-
@pytest.fixture(autouse=True, scope="session")
54-
def install_playwright(tmp_path_factory, worker_id):
55-
root_tmp_dir = get_lock_dir(tmp_path_factory, worker_id)
56-
fn = root_tmp_dir / "playwright_install.lock"
57-
flag = root_tmp_dir / "playwright_install.done"
58-
59-
with FileLock(str(fn)):
60-
if not flag.exists():
61-
subprocess.run(["playwright", "install", "chromium"], check=True) # noqa: S607
62-
# Try to install system deps, but don't fail if already installed or no root access
63-
with contextlib.suppress(subprocess.CalledProcessError):
64-
subprocess.run(["playwright", "install-deps"], check=True) # noqa: S607
65-
flag.touch()
66-
67-
68-
@pytest.fixture(autouse=True, scope="session")
69-
def rebuild(tmp_path_factory, worker_id):
70-
# When running inside `hatch test`, the `HATCH_ENV_ACTIVE` environment variable
71-
# is set. If we try to run `hatch build` with this variable set, Hatch will
72-
# complain that the current environment is not a builder environment.
73-
# To fix this, we remove `HATCH_ENV_ACTIVE` from the environment variables
74-
# passed to the subprocess.
75-
env = os.environ.copy()
76-
env.pop("HATCH_ENV_ACTIVE", None)
77-
78-
root_tmp_dir = get_lock_dir(tmp_path_factory, worker_id)
79-
fn = root_tmp_dir / "build.lock"
80-
flag = root_tmp_dir / "build.done"
81-
82-
# Whoever gets the lock first performs the build.
83-
with FileLock(str(fn)):
84-
if not flag.exists():
85-
subprocess.run(["hatch", "build", "-t", "wheel"], check=True, env=env) # noqa: S607
86-
flag.touch()
87-
88-
8932
@pytest.fixture(scope="session")
9033
async def display(server, browser):
9134
async with DisplayFixture(backend=server, browser=browser) as display:
@@ -103,12 +46,7 @@ async def browser(pytestconfig: pytest.Config):
10346
from playwright.async_api import async_playwright
10447

10548
async with async_playwright() as pw:
106-
yield await pw.chromium.launch(headless=headless_environ(pytestconfig))
107-
108-
109-
@pytest.fixture(autouse=True)
110-
def clear_web_modules_dir_after_test():
111-
clear_reactpy_web_modules_dir()
49+
yield await pw.chromium.launch(headless=_headless_environ(pytestconfig))
11250

11351

11452
@pytest.fixture(autouse=True)
@@ -121,3 +59,14 @@ def assert_no_logged_exceptions():
12159
raise r.exc_info[1]
12260
finally:
12361
records.clear()
62+
63+
64+
def _headless_environ(pytestconfig: pytest.Config):
65+
if (
66+
pytestconfig.getoption("headless")
67+
or os.environ.get("PLAYWRIGHT_HEADLESS") == "1"
68+
or GITHUB_ACTIONS
69+
):
70+
os.environ["PLAYWRIGHT_HEADLESS"] = "1"
71+
return True
72+
return False

0 commit comments

Comments
 (0)