Skip to content

Commit 36ee721

Browse files
authored
feat: allow connecting via connect_options (#269)
1 parent a69386c commit 36ee721

File tree

6 files changed

+146
-4
lines changed

6 files changed

+146
-4
lines changed

.github/workflows/ci.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ jobs:
7272
python-version: 3.9
7373
channels: microsoft,conda-forge
7474
- name: Prepare
75-
run: conda install conda-build conda-verify
75+
run: |
76+
conda install conda-build conda-verify
77+
# Until https://github.com/anaconda/conda-anaconda-telemetry/issues/87 has been fixed
78+
conda remove --name base conda-anaconda-telemetry
7679
- name: Build pytest-playwright
7780
run: conda build .
7881
- name: Build pytest-playwright-asyncio

.github/workflows/python-publish.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ jobs:
1818
python-version: 3.9
1919
channels: microsoft,conda-forge
2020
- name: Prepare
21-
run: conda install anaconda-client conda-build conda-verify
21+
run: |
22+
conda install anaconda-client conda-build conda-verify
23+
# Until https://github.com/anaconda/conda-anaconda-telemetry/issues/87 has been fixed
24+
conda remove --name base conda-anaconda-telemetry
2225
- name: Build and Upload
2326
env:
2427
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_API_TOKEN }}

pytest-playwright-asyncio/pytest_playwright_asyncio/pytest_playwright.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import hashlib
16+
import json
1617
import shutil
1718
import os
1819
import sys
@@ -247,14 +248,33 @@ def browser_type(playwright: Playwright, browser_name: str) -> BrowserType:
247248
return getattr(playwright, browser_name)
248249

249250

251+
@pytest.fixture(scope="session")
252+
def connect_options() -> Optional[Dict]:
253+
return None
254+
255+
250256
@pytest.fixture(scope="session")
251257
def launch_browser(
252258
browser_type_launch_args: Dict,
253259
browser_type: BrowserType,
260+
connect_options: Optional[Dict],
254261
) -> Callable[..., Awaitable[Browser]]:
255262
async def launch(**kwargs: Dict) -> Browser:
256263
launch_options = {**browser_type_launch_args, **kwargs}
257-
browser = await browser_type.launch(**launch_options)
264+
if connect_options:
265+
browser = await browser_type.connect(
266+
**(
267+
{
268+
**connect_options,
269+
"headers": {
270+
"x-playwright-launch-options": json.dumps(launch_options),
271+
**(connect_options.get("headers") or {}),
272+
},
273+
}
274+
)
275+
)
276+
else:
277+
browser = await browser_type.launch(**launch_options)
258278
return browser
259279

260280
return launch

pytest-playwright/pytest_playwright/pytest_playwright.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import hashlib
16+
import json
1617
import shutil
1718
import os
1819
import sys
@@ -244,14 +245,33 @@ def browser_type(playwright: Playwright, browser_name: str) -> BrowserType:
244245
return getattr(playwright, browser_name)
245246

246247

248+
@pytest.fixture(scope="session")
249+
def connect_options() -> Optional[Dict]:
250+
return None
251+
252+
247253
@pytest.fixture(scope="session")
248254
def launch_browser(
249255
browser_type_launch_args: Dict,
250256
browser_type: BrowserType,
257+
connect_options: Optional[Dict],
251258
) -> Callable[..., Browser]:
252259
def launch(**kwargs: Dict) -> Browser:
253260
launch_options = {**browser_type_launch_args, **kwargs}
254-
browser = browser_type.launch(**launch_options)
261+
if connect_options:
262+
browser = browser_type.connect(
263+
**(
264+
{
265+
**connect_options,
266+
"headers": {
267+
"x-playwright-launch-options": json.dumps(launch_options),
268+
**(connect_options.get("headers") or {}),
269+
},
270+
}
271+
)
272+
)
273+
else:
274+
browser = browser_type.launch(**launch_options)
255275
return browser
256276

257277
return launch

tests/test_asyncio.py

+50
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# limitations under the License.
1414

1515
import os
16+
import signal
17+
import subprocess
1618
import sys
1719

1820
import pytest
@@ -1019,3 +1021,51 @@ def test_with_page(page):
10191021
"test-results/test-output-path-via-pytest-runtest-makereport-hook-py-test-with-page-chromium"
10201022
).strpath,
10211023
]
1024+
1025+
1026+
def test_connect_options_should_work(testdir: pytest.Testdir) -> None:
1027+
server_process = None
1028+
try:
1029+
testdir.makeconftest(
1030+
"""
1031+
import pytest
1032+
1033+
@pytest.fixture(scope="session")
1034+
def connect_options():
1035+
return {
1036+
"ws_endpoint": "ws://localhost:1234",
1037+
}
1038+
"""
1039+
)
1040+
testdir.makepyfile(
1041+
"""
1042+
import pytest
1043+
1044+
@pytest.mark.asyncio(loop_scope="session")
1045+
async def test_connect_options(page):
1046+
assert await page.evaluate("1 + 1") == 2
1047+
"""
1048+
)
1049+
result = testdir.runpytest()
1050+
assert "connect ECONNREFUSED" in "".join(result.outlines)
1051+
server_process = subprocess.Popen(
1052+
["playwright", "run-server", "--port=1234"],
1053+
stdout=subprocess.PIPE,
1054+
stderr=subprocess.PIPE,
1055+
)
1056+
while True:
1057+
stdout = server_process.stdout
1058+
assert stdout
1059+
if "Listening on" in str(stdout.readline()):
1060+
break
1061+
result = testdir.runpytest()
1062+
result.assert_outcomes(passed=1)
1063+
finally:
1064+
assert server_process
1065+
# TODO: Playwright CLI on Windows via Python does not forward the signal
1066+
# hence we need to send it to the whole process group.
1067+
if sys.platform == "win32":
1068+
subprocess.run(["taskkill", "/F", "/T", "/PID", str(server_process.pid)])
1069+
else:
1070+
os.kill(server_process.pid, signal.SIGINT)
1071+
server_process.wait()

tests/test_sync.py

+46
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
import os
1616
from pathlib import Path
17+
import signal
18+
import subprocess
1719
import sys
1820

1921
import pytest
@@ -982,3 +984,47 @@ def test_with_page(page):
982984
"test-results/test-output-path-via-pytest-runtest-makereport-hook-py-test-with-page-chromium"
983985
).strpath,
984986
]
987+
988+
989+
def test_connect_options_should_work(testdir: pytest.Testdir) -> None:
990+
server_process = None
991+
try:
992+
testdir.makeconftest(
993+
"""
994+
import pytest
995+
996+
@pytest.fixture(scope="session")
997+
def connect_options():
998+
return {
999+
"ws_endpoint": "ws://localhost:1234",
1000+
}
1001+
"""
1002+
)
1003+
testdir.makepyfile(
1004+
"""
1005+
def test_connect_options(page):
1006+
assert page.evaluate("1 + 1") == 2
1007+
"""
1008+
)
1009+
result = testdir.runpytest()
1010+
assert "connect ECONNREFUSED" in "".join(result.outlines)
1011+
server_process = subprocess.Popen(
1012+
["playwright", "run-server", "--port=1234"],
1013+
stdout=subprocess.PIPE,
1014+
)
1015+
while True:
1016+
stdout = server_process.stdout
1017+
assert stdout
1018+
if "Listening on" in str(stdout.readline()):
1019+
break
1020+
result = testdir.runpytest()
1021+
result.assert_outcomes(passed=1)
1022+
finally:
1023+
assert server_process
1024+
# TODO: Playwright CLI on Windows via Python does not forward the signal
1025+
# hence we need to send it to the whole process group.
1026+
if sys.platform == "win32":
1027+
subprocess.run(["taskkill", "/F", "/T", "/PID", str(server_process.pid)])
1028+
else:
1029+
os.kill(server_process.pid, signal.SIGINT)
1030+
server_process.wait()

0 commit comments

Comments
 (0)