Skip to content

Commit c06ba86

Browse files
committed
Get the hatch test command working
1 parent 3353d48 commit c06ba86

File tree

10 files changed

+110
-71
lines changed

10 files changed

+110
-71
lines changed

.github/workflows/test-python.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ jobs:
2828
- name: Install Python Dependencies
2929
run: pip install --upgrade pip hatch uv
3030
- name: Run Tests
31-
run: hatch run test:python --python ${{ matrix.python-version }}
31+
run: hatch test --python ${{ matrix.python-version }}

pyproject.toml

+52-19
Original file line numberDiff line numberDiff line change
@@ -78,28 +78,68 @@ commands = [
7878
artifacts = []
7979

8080
# >>> Hatch Test Suite <<<
81-
[tool.hatch.envs.test]
82-
detached = true
81+
[tool.hatch.envs.hatch-test]
8382
extra-dependencies = [
83+
"pytest-sugar",
84+
"pytest-django",
8485
"playwright",
85-
"twisted",
8686
"channels[daphne]>=4.0.0",
87+
"twisted",
8788
"tblib",
88-
"whitenoise", # TODO: Switch to ServeStatic
89+
"servestatic",
8990
]
91+
matrix-name-format = "{variable}-{value}"
92+
93+
# Django 4.2
94+
[[tool.hatch.envs.hatch-test.matrix]]
95+
python = ["3.9", "3.10", "3.11", "3.12"]
96+
django = ["4.2"]
97+
98+
# Django 5.0
99+
[[tool.hatch.envs.hatch-test.matrix]]
100+
python = ["3.10", "3.11", "3.12"]
101+
django = ["5.0"]
102+
103+
# Django 5.1
104+
[[tool.hatch.envs.hatch-test.matrix]]
105+
python = ["3.10", "3.11", "3.12", "3.13"]
106+
django = ["5.1"]
107+
108+
[tool.hatch.envs.hatch-test.overrides]
109+
matrix.django.dependencies = [
110+
{ if = [
111+
"4.2",
112+
], value = "django~=4.2" },
113+
{ if = [
114+
"5.0",
115+
], value = "django~=5.0" },
116+
{ if = [
117+
"5.1",
118+
], value = "django~=5.1" },
119+
]
120+
121+
[tool.pytest.ini_options]
122+
addopts = """\
123+
--strict-config
124+
--strict-markers
125+
--reuse-db
126+
"""
127+
django_find_project = false
128+
DJANGO_SETTINGS_MODULE = "test_app.settings_single_db"
129+
pythonpath = [".", "tests/"]
90130

91-
[tool.hatch.envs.test.scripts]
92-
python = [
93-
"pip install -e . -U",
94-
"playwright install chromium",
95-
"cd tests && python manage.py test --noinput --settings='test_app.settings_single_db'",
96-
"cd tests && python manage.py test --noinput --settings='test_app.settings_multi_db'",
131+
132+
# >>> Hatch Django Scripts <<<
133+
[tool.hatch.envs.django]
134+
extra-dependencies = ["channels[daphne]>=4.0.0", "twisted", "servestatic"]
135+
136+
[tool.hatch.envs.django.scripts]
137+
runserver = [
138+
"cd tests && python manage.py migrate --noinput && python manage.py runserver",
97139
]
98-
runserver = ["cd tests && python manage.py runserver"]
99140

100141

101142
# >>> Hatch Documentation Scripts <<<
102-
103143
[tool.hatch.envs.docs]
104144
template = "docs"
105145
detached = true
@@ -138,7 +178,6 @@ detached = true
138178
check = ["cd src/js && bun install && bun run check"]
139179

140180
# >>> Generic Tools <<<
141-
142181
[tool.ruff]
143182
extend-exclude = ["*/migrations/*", ".venv/*", ".eggs/*", ".nox/*", "build/*"]
144183
line-length = 120
@@ -156,9 +195,3 @@ lint.extend-ignore = [
156195
]
157196
lint.preview = true
158197
lint.isort.known-first-party = ["src", "tests"]
159-
160-
[tool.pytest.ini_options]
161-
addopts = """\
162-
--strict-config
163-
--strict-markers
164-
"""

tests/test_app/prerender/components.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
from time import sleep
22

3-
import reactpy_django
43
from reactpy import component, html
54

5+
import reactpy_django
6+
7+
SLEEP_TIME = 0.25
8+
69

710
@component
811
def prerender_string():
912
scope = reactpy_django.hooks.use_scope()
1013

11-
sleep(0.5)
14+
if scope.get("type") != "http":
15+
sleep(SLEEP_TIME)
16+
1217
return (
1318
"prerender_string: Fully Rendered"
1419
if scope.get("type") == "websocket"

tests/test_app/settings_multi_db.py

+14-25
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
SECRET_KEY = "django-insecure-n!bd1#+7ufw5#9ipayu9k(lyu@za$c2ajbro7es(v8_7w1$=&c"
1313

1414
# Run in production mode when using a real web server
15-
DEBUG = all(
16-
not sys.argv[0].endswith(webserver_name)
17-
for webserver_name in {"hypercorn", "uvicorn", "daphne"}
15+
DEBUG = not any(
16+
sys.argv[0].endswith(webserver_name)
17+
for webserver_name in ["hypercorn", "uvicorn", "daphne"]
1818
)
1919
ALLOWED_HOSTS = ["*"]
2020

@@ -66,39 +66,26 @@
6666
DATABASES = {
6767
"default": {
6868
"ENGINE": "django.db.backends.sqlite3",
69-
# Changing NAME is needed due to a bug related to `manage.py test`
70-
"NAME": os.path.join(
71-
BASE_DIR,
72-
f"test_{DB_NAME}.sqlite3" if "test" in sys.argv else f"{DB_NAME}.sqlite3",
73-
),
69+
"NAME": os.path.join(BASE_DIR, f"{DB_NAME}.sqlite3"),
7470
"TEST": {
75-
"NAME": os.path.join(BASE_DIR, f"test_{DB_NAME}.sqlite3"),
71+
"NAME": os.path.join(BASE_DIR, f"{DB_NAME}.sqlite3"),
7672
"OPTIONS": {"timeout": 20},
7773
"DEPENDENCIES": [],
7874
},
7975
"OPTIONS": {"timeout": 20},
8076
},
81-
}
82-
if "test" in sys.argv:
83-
DATABASES["reactpy"] = {
77+
"reactpy": {
8478
"ENGINE": "django.db.backends.sqlite3",
85-
# Changing NAME is needed due to a bug related to `manage.py test`
86-
"NAME": os.path.join(
87-
BASE_DIR,
88-
(
89-
f"test_{DB_NAME}_2.sqlite3"
90-
if "test" in sys.argv
91-
else f"{DB_NAME}_2.sqlite3"
92-
),
93-
),
79+
"NAME": os.path.join(BASE_DIR, f"{DB_NAME}_2.sqlite3"),
9480
"TEST": {
95-
"NAME": os.path.join(BASE_DIR, f"test_{DB_NAME}_2.sqlite3"),
81+
"NAME": os.path.join(BASE_DIR, f"{DB_NAME}_2.sqlite3"),
9682
"OPTIONS": {"timeout": 20},
9783
"DEPENDENCIES": [],
9884
},
9985
"OPTIONS": {"timeout": 20},
100-
}
101-
REACTPY_DATABASE = "reactpy"
86+
},
87+
}
88+
REACTPY_DATABASE = "reactpy"
10289
DATABASE_ROUTERS = ["reactpy_django.database.Router"]
10390

10491
# Cache
@@ -161,4 +148,6 @@
161148
CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"}}
162149

163150
# ReactPy-Django Settings
164-
REACTPY_BACKHAUL_THREAD = "test" not in sys.argv and "runserver" not in sys.argv
151+
REACTPY_BACKHAUL_THREAD = any(
152+
sys.argv[0].endswith(webserver_name) for webserver_name in ["hypercorn", "uvicorn"]
153+
)

tests/test_app/settings_single_db.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
SECRET_KEY = "django-insecure-n!bd1#+7ufw5#9ipayu9k(lyu@za$c2ajbro7es(v8_7w1$=&c"
1313

1414
# Run in production mode when using a real web server
15-
DEBUG = all(
16-
not sys.argv[0].endswith(webserver_name)
17-
for webserver_name in {"hypercorn", "uvicorn", "daphne"}
15+
DEBUG = not any(
16+
sys.argv[0].endswith(webserver_name)
17+
for webserver_name in ["hypercorn", "uvicorn", "daphne"]
1818
)
1919
ALLOWED_HOSTS = ["*"]
2020

@@ -66,13 +66,9 @@
6666
DATABASES = {
6767
"default": {
6868
"ENGINE": "django.db.backends.sqlite3",
69-
# Changing NAME is needed due to a bug related to `manage.py test`
70-
"NAME": os.path.join(
71-
BASE_DIR,
72-
f"test_{DB_NAME}.sqlite3" if "test" in sys.argv else f"{DB_NAME}.sqlite3",
73-
),
69+
"NAME": os.path.join(BASE_DIR, f"{DB_NAME}.sqlite3"),
7470
"TEST": {
75-
"NAME": os.path.join(BASE_DIR, f"test_{DB_NAME}.sqlite3"),
71+
"NAME": os.path.join(BASE_DIR, f"{DB_NAME}.sqlite3"),
7672
"OPTIONS": {"timeout": 20},
7773
"DEPENDENCIES": [],
7874
},
@@ -140,4 +136,6 @@
140136
CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"}}
141137

142138
# ReactPy-Django Settings
143-
REACTPY_BACKHAUL_THREAD = "test" not in sys.argv and "runserver" not in sys.argv
139+
REACTPY_BACKHAUL_THREAD = any(
140+
sys.argv[0].endswith(webserver_name) for webserver_name in ["hypercorn", "uvicorn"]
141+
)

tests/test_app/tests/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
from . import * # noqa: F401, F403

tests/test_app/tests/conftest.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from __future__ import annotations
2+
3+
import os
4+
from pathlib import Path
5+
6+
import pytest
7+
8+
os.chdir(Path(__file__).parent.parent.parent)
9+
10+
11+
@pytest.fixture(autouse=True)
12+
def enable_db_access_for_all_tests(db):
13+
pass

tests/test_app/tests/test_components.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222

2323
class ComponentTests(ChannelsLiveServerTestCase):
24-
from django.db import DEFAULT_DB_ALIAS
2524

2625
from reactpy_django import config
2726

@@ -71,6 +70,8 @@ def setUpClass(cls):
7170

7271
@classmethod
7372
def tearDownClass(cls):
73+
from django.db import DEFAULT_DB_ALIAS
74+
7475
from reactpy_django import config
7576

7677
# Close the Playwright browser
@@ -86,7 +87,7 @@ def tearDownClass(cls):
8687

8788
# Repurposed from ChannelsLiveServerTestCase._post_teardown
8889
cls._live_server_modified_settings.disable()
89-
for db_name in {"default", config.REACTPY_DATABASE}:
90+
for db_name in [DEFAULT_DB_ALIAS, config.REACTPY_DATABASE]:
9091
call_command(
9192
"flush",
9293
verbosity=0,
@@ -369,13 +370,12 @@ def test_prerender(self):
369370
use_user_http = new_page.locator("#use-user-http[data-success=True]")
370371
use_user_ws = new_page.locator("#use-user-ws[data-success=true]")
371372

373+
# Check if the prerender occurred properly
372374
string.wait_for()
373375
vdom.wait_for()
374376
component.wait_for()
375377
use_root_id_http.wait_for()
376378
use_user_http.wait_for()
377-
378-
# Check if the prerender occurred
379379
self.assertEqual(
380380
string.all_inner_texts(), ["prerender_string: Prerendered"]
381381
)
@@ -387,7 +387,7 @@ def test_prerender(self):
387387
self.assertEqual(len(root_id_value), 36)
388388

389389
# Check if the full render occurred
390-
sleep(1)
390+
sleep(2)
391391
self.assertEqual(
392392
string.all_inner_texts(), ["prerender_string: Fully Rendered"]
393393
)

tests/test_app/tests/test_database.py

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import dill as pickle
66
from django.test import TransactionTestCase
7+
78
from reactpy_django import clean
89
from reactpy_django.models import ComponentSession, UserDataModel
910
from reactpy_django.types import ComponentParams

tests/test_app/tests/test_regex.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import re
22

33
from django.test import TestCase
4+
45
from reactpy_django.utils import COMMENT_REGEX, COMPONENT_REGEX
56

67

@@ -21,10 +22,10 @@ def test_component_regex(self):
2122
)
2223
self.assertRegex(
2324
r"""{%
24-
component
25-
"my.component"
26-
class="my_thing"
27-
attr="attribute"
25+
component
26+
"my.component"
27+
class="my_thing"
28+
attr="attribute"
2829
2930
%}""", # noqa: W291
3031
COMPONENT_REGEX,
@@ -84,10 +85,10 @@ def test_comment_regex(self):
8485
COMMENT_REGEX,
8586
)
8687
self.assertRegex(
87-
r"""<!--
88+
r"""<!--
8889
a comment
8990
another comments
90-
drink some cement
91+
drink some cement
9192
-->""", # noqa: W291
9293
COMMENT_REGEX,
9394
)
@@ -138,8 +139,8 @@ def test_comment_regex(self):
138139
COMMENT_REGEX.sub(
139140
"",
140141
r"""<!--
141-
{% component "my.component" %}
142-
{% component "my.component" %}
142+
{% component "my.component" %}
143+
{% component "my.component" %}
143144
-->""", # noqa: W291
144145
),
145146
"",

0 commit comments

Comments
 (0)