Skip to content

Commit 13175f3

Browse files
committed
Fix test runtime warnings
1 parent 21c99a1 commit 13175f3

File tree

4 files changed

+48
-44
lines changed

4 files changed

+48
-44
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ extra-dependencies = [
171171
"types-requests",
172172
"types-lxml",
173173
"jsonpointer",
174+
"pytest",
174175
]
175176

176177
[tool.hatch.envs.python.scripts]

src/reactpy/testing/display.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
import os
44
from contextlib import AsyncExitStack
55
from types import TracebackType
6-
from typing import Any
6+
from typing import TYPE_CHECKING, Any
77

88
from playwright.async_api import Browser, Page, async_playwright, expect
99

10-
from reactpy.config import REACTPY_TESTS_DEFAULT_TIMEOUT
10+
from reactpy.config import REACTPY_TESTS_DEFAULT_TIMEOUT as DEFAULT_TIMEOUT
1111
from reactpy.testing.backend import BackendFixture
12-
from reactpy.testing.common import GITHUB_ACTIONS
1312
from reactpy.types import RootComponentConstructor
1413

14+
if TYPE_CHECKING:
15+
import pytest
16+
1517

1618
class DisplayFixture:
1719
"""A fixture for running web-based tests using ``playwright``"""
@@ -35,9 +37,7 @@ def __init__(
3537
self.browser_is_external = True
3638
self.browser = browser
3739

38-
self.timeout = (
39-
timeout if timeout is not None else REACTPY_TESTS_DEFAULT_TIMEOUT.current
40-
)
40+
self.timeout = DEFAULT_TIMEOUT.current if timeout is None else timeout
4141
self.headless = headless
4242

4343
async def show(
@@ -52,33 +52,31 @@ async def goto(self, path: str, query: Any | None = None) -> None:
5252
await self.page.goto(self.backend.url(path, query))
5353

5454
async def __aenter__(self) -> DisplayFixture:
55-
self.browser_exit_stack = AsyncExitStack()
56-
self.backend_exit_stack = AsyncExitStack()
55+
self.exit_stack = AsyncExitStack()
5756

5857
if not hasattr(self, "browser"):
59-
pw = await self.browser_exit_stack.enter_async_context(async_playwright())
60-
self.browser = await pw.chromium.launch(
61-
headless=self.headless
62-
or os.environ.get("PLAYWRIGHT_HEADLESS") == "1"
63-
or GITHUB_ACTIONS
58+
pw = await self.exit_stack.enter_async_context(async_playwright())
59+
self.browser = await self.exit_stack.enter_async_context(
60+
await pw.chromium.launch(headless=not _playwright_visible())
6461
)
6562

6663
expect.set_options(timeout=self.timeout * 1000)
6764
await self.configure_page()
6865

6966
if not hasattr(self, "backend"): # nocov
7067
self.backend = BackendFixture()
71-
await self.backend_exit_stack.enter_async_context(self.backend)
68+
await self.exit_stack.enter_async_context(self.backend)
7269

7370
return self
7471

7572
async def configure_page(self) -> None:
7673
if getattr(self, "page", None) is None:
7774
self.page = await self.browser.new_page()
75+
self.page = await self.exit_stack.enter_async_context(self.page)
7876
self.page.set_default_navigation_timeout(self.timeout * 1000)
7977
self.page.set_default_timeout(self.timeout * 1000)
80-
self.page.on("console", lambda msg: print(f"BROWSER CONSOLE: {msg.text}")) # noqa: T201
81-
self.page.on("pageerror", lambda exc: print(f"BROWSER ERROR: {exc}")) # noqa: T201
78+
self.page.on("console", lambda x: print(f"BROWSER CONSOLE: {x.text}")) # noqa: T201
79+
self.page.on("pageerror", lambda x: print(f"BROWSER ERROR: {x}")) # noqa: T201
8280

8381
async def __aexit__(
8482
self,
@@ -87,9 +85,13 @@ async def __aexit__(
8785
traceback: TracebackType | None,
8886
) -> None:
8987
self.backend.mount(None)
90-
if getattr(self, "page", None) is not None:
91-
await self.page.close()
92-
if not self.browser_is_external:
93-
await self.browser_exit_stack.aclose()
94-
if not self.backend_is_external:
95-
await self.backend_exit_stack.aclose()
88+
await self.exit_stack.aclose()
89+
90+
91+
def _playwright_visible(pytestconfig: pytest.Config | None = None) -> bool:
92+
if (pytestconfig and pytestconfig.getoption("visible")) or os.environ.get(
93+
"PLAYWRIGHT_VISIBLE"
94+
) == "1":
95+
os.environ.setdefault("PLAYWRIGHT_VISIBLE", "1")
96+
return True
97+
return False

tests/conftest.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from __future__ import annotations
22

3-
import os
4-
53
import pytest
64
from _pytest.config.argparsing import Parser
75

@@ -14,18 +12,18 @@
1412
DisplayFixture,
1513
capture_reactpy_logs,
1614
)
17-
from reactpy.testing.common import GITHUB_ACTIONS
15+
from reactpy.testing.display import _playwright_visible
1816

1917
REACTPY_ASYNC_RENDERING.set_current(True)
2018
REACTPY_DEBUG.set_current(True)
2119

2220

2321
def pytest_addoption(parser: Parser) -> None:
2422
parser.addoption(
25-
"--headless",
26-
dest="headless",
23+
"--visible",
24+
dest="visible",
2725
action="store_true",
28-
help="Don't open a browser window when running web-based tests",
26+
help="Open a browser window when running web-based tests",
2927
)
3028

3129

@@ -46,7 +44,10 @@ async def browser(pytestconfig: pytest.Config):
4644
from playwright.async_api import async_playwright
4745

4846
async with async_playwright() as pw:
49-
yield await pw.chromium.launch(headless=_headless_environ(pytestconfig))
47+
async with await pw.chromium.launch(
48+
headless=not _playwright_visible(pytestconfig)
49+
) as browser:
50+
yield browser
5051

5152

5253
@pytest.fixture(autouse=True)
@@ -59,14 +60,3 @@ def assert_no_logged_exceptions():
5960
raise r.exc_info[1]
6061
finally:
6162
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

tests/test_testing.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,20 +237,28 @@ async def test_display_fixture_headless_logic():
237237
mock_context_manager.__aenter__.return_value = mock_playwright_instance
238238

239239
mock_browser = AsyncMock()
240+
mock_browser.__aenter__ = AsyncMock(return_value=mock_browser)
240241
mock_playwright_instance.chromium.launch.return_value = mock_browser
241242

242243
mock_page = AsyncMock()
243244
# Configure synchronous methods on page
244245
mock_page.set_default_timeout = MagicMock()
246+
mock_page.set_default_navigation_timeout = MagicMock()
245247
mock_page.on = MagicMock()
248+
mock_page.__aenter__ = AsyncMock(return_value=mock_page)
246249

247250
mock_browser.new_page.return_value = mock_page
248251

249-
# Case: headless=False, PLAYWRIGHT_HEADLESS='1'
250-
with patch.dict(os.environ, {"PLAYWRIGHT_HEADLESS": "1"}):
251-
async with DisplayFixture(headless=False):
252+
# Case: headless=False, PLAYWRIGHT_VISIBLE='1'
253+
with patch.dict(os.environ, {"PLAYWRIGHT_VISIBLE": "1"}):
254+
async with DisplayFixture():
255+
pass
256+
mock_playwright_instance.chromium.launch.assert_called_with(headless=False)
257+
258+
# Case: headless=True, PLAYWRIGHT_VISIBLE='0'
259+
with patch.dict(os.environ, {"PLAYWRIGHT_VISIBLE": "0"}):
260+
async with DisplayFixture():
252261
pass
253-
# Check that launch was called with headless=True
254262
mock_playwright_instance.chromium.launch.assert_called_with(headless=True)
255263

256264

@@ -265,11 +273,14 @@ async def test_display_fixture_internal_backend():
265273
mock_context_manager.__aenter__.return_value = mock_playwright_instance
266274

267275
mock_browser = AsyncMock()
276+
mock_browser.__aenter__ = AsyncMock(return_value=mock_browser)
268277
mock_playwright_instance.chromium.launch.return_value = mock_browser
269278

270279
mock_page = AsyncMock()
271280
mock_page.set_default_timeout = MagicMock()
281+
mock_page.set_default_navigation_timeout = MagicMock()
272282
mock_page.on = MagicMock()
283+
mock_page.__aenter__ = AsyncMock(return_value=mock_page)
273284
mock_browser.new_page.return_value = mock_page
274285

275286
# We also need to mock BackendFixture to avoid starting real server

0 commit comments

Comments
 (0)