@@ -42,29 +42,29 @@ async def _run_chromium_devtools() -> Tuple[subprocess.Popen, str]:
4242 return proc , devtools_url
4343
4444
45- def _run_playwright_browser_server () -> Tuple [subprocess .Popen , str ]:
45+ def _run_chromium_browser_server () -> Tuple [subprocess .Popen , str ]:
4646 """Start a Playwright server in a separate process, return the process
4747 object and a string with its websocket endpoint.
4848 Pass fixed port and ws path as arguments instead of allowing Playwright
4949 to choose, for some reason I was unable to capture stdout/stderr :shrug:
5050 """
5151 port = str (random .randint (60_000 , 63_000 ))
5252 ws_path = str (uuid .uuid4 ())
53- launch_server_script_path = str (Path (__file__ ).parent .parent / "launch_browser_server .js" )
53+ launch_server_script_path = str (Path (__file__ ).parent .parent / "launch_chromium_server .js" )
5454 command = ["node" , launch_server_script_path , port , ws_path ]
5555 proc = subprocess .Popen (command ) # pylint: disable=consider-using-with
5656 return proc , f"ws://localhost:{ port } /{ ws_path } "
5757
5858
5959@asynccontextmanager
60- async def remote_browser ( is_chrome_devtools_protocol : bool = True ):
60+ async def remote_chromium ( with_devtools_protocol : bool = True ):
6161 """Launch a remote browser that lasts while in the context."""
6262 proc = url = None
6363 try :
64- if is_chrome_devtools_protocol :
64+ if with_devtools_protocol :
6565 proc , url = await _run_chromium_devtools ()
6666 else :
67- proc , url = _run_playwright_browser_server ()
67+ proc , url = _run_chromium_browser_server ()
6868 await asyncio .sleep (1 ) # allow some time for the browser to start
6969 except Exception :
7070 pass
@@ -77,15 +77,15 @@ async def remote_browser(is_chrome_devtools_protocol: bool = True):
7777 proc .communicate ()
7878
7979
80- class TestRemote (IsolatedAsyncioTestCase ):
80+ class TestRemoteBrowser (IsolatedAsyncioTestCase ):
8181 @pytest .fixture (autouse = True )
8282 def inject_fixtures (self , caplog ):
8383 caplog .set_level (logging .DEBUG )
8484 self ._caplog = caplog
8585
8686 @allow_windows
8787 async def test_connect_devtools (self ):
88- async with remote_browser ( is_chrome_devtools_protocol = True ) as devtools_url :
88+ async with remote_chromium ( with_devtools_protocol = True ) as devtools_url :
8989 settings_dict = {
9090 "PLAYWRIGHT_CDP_URL" : devtools_url ,
9191 "PLAYWRIGHT_LAUNCH_OPTIONS" : {"headless" : True },
@@ -103,7 +103,7 @@ async def test_connect_devtools(self):
103103
104104 @allow_windows
105105 async def test_connect (self ):
106- async with remote_browser ( is_chrome_devtools_protocol = False ) as browser_url :
106+ async with remote_chromium ( with_devtools_protocol = False ) as browser_url :
107107 settings_dict = {
108108 "PLAYWRIGHT_CONNECT_URL" : browser_url ,
109109 "PLAYWRIGHT_LAUNCH_OPTIONS" : {"headless" : True },
@@ -128,3 +128,47 @@ async def test_connect(self):
128128 logging .WARNING ,
129129 "Connecting to remote browser, ignoring PLAYWRIGHT_LAUNCH_OPTIONS" ,
130130 ) in self ._caplog .record_tuples
131+
132+
133+ class TestBrowserReconnect (IsolatedAsyncioTestCase ):
134+ @pytest .fixture (autouse = True )
135+ def inject_fixtures (self , caplog ):
136+ caplog .set_level (logging .DEBUG )
137+ self ._caplog = caplog
138+
139+ @allow_windows
140+ async def test_restart_browser (self ):
141+ spider = Spider ("foo" )
142+ async with make_handler () as handler :
143+ with StaticMockServer () as server :
144+ req1 = Request (
145+ server .urljoin ("/index.html" ),
146+ meta = {"playwright" : True , "playwright_include_page" : True },
147+ )
148+ resp1 = await handler ._download_request (req1 , spider )
149+ page = resp1 .meta ["playwright_page" ]
150+ await page .context .browser .close ()
151+ req2 = Request (server .urljoin ("/gallery.html" ), meta = {"playwright" : True })
152+ resp2 = await handler ._download_request (req2 , spider )
153+ assert_correct_response (resp1 , req1 )
154+ assert_correct_response (resp2 , req2 )
155+ assert (
156+ self ._caplog .record_tuples .count (
157+ (
158+ "scrapy-playwright" ,
159+ logging .DEBUG ,
160+ "Browser disconnected" ,
161+ )
162+ )
163+ == 2 # one mid-crawl after calling Browser.close() manually, one at the end
164+ )
165+ assert (
166+ self ._caplog .record_tuples .count (
167+ (
168+ "scrapy-playwright" ,
169+ logging .INFO ,
170+ "Launching browser chromium" ,
171+ )
172+ )
173+ == 2 # one at the beginning, one after calling Browser.close() manually
174+ )
0 commit comments