33import os
44from contextlib import AsyncExitStack
55from types import TracebackType
6- from typing import Any
6+ from typing import TYPE_CHECKING , Any
77
88from 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
1111from reactpy .testing .backend import BackendFixture
12- from reactpy .testing .common import GITHUB_ACTIONS
1312from reactpy .types import RootComponentConstructor
1413
14+ if TYPE_CHECKING :
15+ import pytest
16+
1517
1618class 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
0 commit comments