feat: added BrowserType.connect#630
Conversation
d2cd2df to
e0c873d
Compare
e0c873d to
d212d33
Compare
d212d33 to
7895112
Compare
5cb2cd3 to
bd6820d
Compare
ad3eebb to
d779566
Compare
9322212 to
8b5a21f
Compare
|
I was able to fix the last skipped test def test_browser_type_connect_should_reject_navigation_when_browser_closes(
server: Server, browser_type: BrowserType, launch_server
):
import greenlet
remote_server = launch_server()
browser = browser_type.connect(remote_server.ws_endpoint)
page = browser.new_page()
server.set_route("/one-style.css", lambda r: None)
g = greenlet.greenlet(browser.close)
page.on("request", lambda: g.switch())
with pytest.raises(Error) as exc_info:
page.goto(server.PREFIX + "/one-style.html")
assert "Playwright connection closed" in exc_info.value.message |
02bb278 to
4b6490b
Compare
kumaraditya303
left a comment
There was a problem hiding this comment.
The failing tests seems flaky
|
Let me summarize the test failures:
So its only the second one which is relevant but causes 3 bots to fail. Will take a more detailed look now. |
927f992 to
a7847ed
Compare
playwright/_impl/_browser.py
Outdated
| return page | ||
|
|
||
| async def close(self) -> None: | ||
| if self._is_connected_over_websocket: |
There was a problem hiding this comment.
Do you want to move it to under _is_closed_or_closing = True? Also, why is logic different from the one in TS? Does TS close the browser on browser.close?
To me, the ideal workflow would be: close terminates the underlying connection, connection termination calls _on_close everywhere. That way, terminating connection due to networking issues would result in the same proper cleanup.
There was a problem hiding this comment.
move it below it.
TS does it via an event, see here in another place: https://github.com/microsoft/playwright/blob/fff1f3d45c243bec65c7e6c43e6fe5e36607dc59/src/client/browserType.ts#L163-L179
playwright/_impl/_browser.py
Outdated
| raise e | ||
|
|
||
| def _notify_remote_closed(self) -> None: | ||
| # Emulate all pages, contexts and the browser closing upon disconnect. |
There was a problem hiding this comment.
I.e I would expect this to be called on web socket disconnect somehow.
There was a problem hiding this comment.
the naming came originally from Java, but open to change.
There was a problem hiding this comment.
So I looked at the TS version, looks like you don't need any special code here, just close the browser. But our server seems to be missing the connection termination upon close for some reason.
|
|
||
| def stop(self) -> None: | ||
| self._stopped = True | ||
| self._loop.create_task(self._connection.close()) |
There was a problem hiding this comment.
Declare self._connection in init, did our mypy break?
There was a problem hiding this comment.
Yes its broken currently (only the impl folder - most important one...), will follow up to fix it.
There was a problem hiding this comment.
It can automatically infer that I set it in WebSocketTransport.run()
But yes your assumption was also correct that mypy was broken. Fixed in #643
| pre_launched_browser = playwright._initializer.get("preLaunchedBrowser") | ||
| assert pre_launched_browser | ||
| browser = cast(Browser, from_channel(pre_launched_browser)) | ||
| browser._is_remote = True |
There was a problem hiding this comment.
Now that you are adding it, we need to introduce the code that depends on it. That would be our artifacts, namely 'download' and 'video'.
There was a problem hiding this comment.
good catch, added it.
79b8d72 to
ae908a3
Compare
d4adea9 to
3349e4d
Compare
| self._is_connected = True | ||
| self._is_closed_or_closing = False | ||
| self._is_remote = False | ||
| self._is_connected_over_websocket = False |
There was a problem hiding this comment.
It seems like you can use is_remote here.
There was a problem hiding this comment.
remote is also used for connect_over_cdp, we only want to close the underlying connection when connect is used.
| assert pre_launched_browser | ||
| browser = cast(Browser, from_channel(pre_launched_browser)) | ||
| browser._is_remote = True | ||
| browser._is_connected_over_websocket = True |
There was a problem hiding this comment.
Yeah, it looks the same as is_remote...
| browser._is_remote = True | ||
| browser._is_connected_over_websocket = True | ||
|
|
||
| transport.once("close", browser._on_close) |
There was a problem hiding this comment.
nit: this looks like a layering violation, should go transport -> connection -> browser. Not a big deal though.
|
I check the code from master(9d79662), but import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.connect("ws://127.0.0.1:12345/9c2251a08a8f1092b72af9b0f9d035bf")
print(browser)
page = await browser.new_page()
print(page)
await page.goto('http://whatsmyuseragent.org/')
await browser.close()
asyncio.run(main()) |
|
Good catch, will take a look. |
Closes #529
Quite an early implementation, need to think about the last skipped test.