Skip to content

Commit d942194

Browse files
authored
[py] do not use global var for devtools, allows multiple devtools to run (#15881)
1 parent 31ffb78 commit d942194

File tree

3 files changed

+52
-31
lines changed

3 files changed

+52
-31
lines changed

py/conftest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,19 @@ def clean_driver(request):
443443
except (AttributeError, TypeError):
444444
raise Exception("This test requires a --driver to be specified.")
445445
driver_reference = getattr(webdriver, driver_class)
446+
447+
# conditionally mark tests as expected to fail based on driver
448+
marker = request.node.get_closest_marker(f"xfail_{driver_class.lower()}")
449+
if marker is not None:
450+
if "run" in marker.kwargs:
451+
if marker.kwargs["run"] is False:
452+
pytest.skip()
453+
yield
454+
return
455+
if "raises" in marker.kwargs:
456+
marker.kwargs.pop("raises")
457+
pytest.xfail(**marker.kwargs)
458+
446459
yield driver_reference
447460
if request.node.get_closest_marker("no_driver_after_test"):
448461
driver_reference = None

py/selenium/webdriver/remote/webdriver.py

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
1817
"""The WebDriver implementation."""
1918

2019
import base64
@@ -75,7 +74,6 @@
7574
from .websocket_connection import WebSocketConnection
7675

7776
cdp = None
78-
devtools = None
7977

8078

8179
def import_cdp():
@@ -267,6 +265,7 @@ def __init__(
267265
self._storage = None
268266
self._webextension = None
269267
self._permissions = None
268+
self._devtools = None
270269

271270
def __repr__(self):
272271
return f'<{type(self).__module__}.{type(self).__name__} (session="{self.session_id}")>'
@@ -1182,32 +1181,28 @@ def orientation(self, value) -> None:
11821181
raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'")
11831182

11841183
def start_devtools(self):
1185-
global devtools
1186-
if self._websocket_connection:
1187-
return devtools, self._websocket_connection
1184+
global cdp
1185+
import_cdp()
1186+
if self.caps.get("se:cdp"):
1187+
ws_url = self.caps.get("se:cdp")
1188+
version = self.caps.get("se:cdpVersion").split(".")[0]
11881189
else:
1189-
global cdp
1190-
import_cdp()
1191-
1192-
if not devtools:
1193-
if self.caps.get("se:cdp"):
1194-
ws_url = self.caps.get("se:cdp")
1195-
version = self.caps.get("se:cdpVersion").split(".")[0]
1196-
else:
1197-
version, ws_url = self._get_cdp_details()
1198-
1199-
if not ws_url:
1200-
raise WebDriverException("Unable to find url to connect to from capabilities")
1201-
1202-
devtools = cdp.import_devtools(version)
1203-
if self.caps["browserName"].lower() == "firefox":
1204-
raise RuntimeError("CDP support for Firefox has been removed. Please switch to WebDriver BiDi.")
1205-
self._websocket_connection = WebSocketConnection(ws_url)
1206-
targets = self._websocket_connection.execute(devtools.target.get_targets())
1207-
target_id = targets[0].target_id
1208-
session = self._websocket_connection.execute(devtools.target.attach_to_target(target_id, True))
1209-
self._websocket_connection.session_id = session
1210-
return devtools, self._websocket_connection
1190+
version, ws_url = self._get_cdp_details()
1191+
1192+
if not ws_url:
1193+
raise WebDriverException("Unable to find url to connect to from capabilities")
1194+
1195+
self._devtools = cdp.import_devtools(version)
1196+
if self._websocket_connection:
1197+
return self._devtools, self._websocket_connection
1198+
if self.caps["browserName"].lower() == "firefox":
1199+
raise RuntimeError("CDP support for Firefox has been removed. Please switch to WebDriver BiDi.")
1200+
self._websocket_connection = WebSocketConnection(ws_url)
1201+
targets = self._websocket_connection.execute(self._devtools.target.get_targets())
1202+
target_id = targets[0].target_id
1203+
session = self._websocket_connection.execute(self._devtools.target.attach_to_target(target_id, True))
1204+
self._websocket_connection.session_id = session
1205+
return self._devtools, self._websocket_connection
12111206

12121207
@asynccontextmanager
12131208
async def bidi_connection(self):
@@ -1282,9 +1277,8 @@ def browser(self):
12821277

12831278
@property
12841279
def _session(self):
1285-
"""
1286-
Returns the BiDi session object for the current WebDriver session.
1287-
"""
1280+
"""Returns the BiDi session object for the current WebDriver
1281+
session."""
12881282
if not self._websocket_connection:
12891283
self._start_bidi()
12901284

@@ -1295,7 +1289,8 @@ def _session(self):
12951289

12961290
@property
12971291
def browsing_context(self):
1298-
"""Returns a browsing context module object for BiDi browsing context commands.
1292+
"""Returns a browsing context module object for BiDi browsing context
1293+
commands.
12991294
13001295
Returns:
13011296
--------

py/test/selenium/webdriver/common/devtools_tests.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,16 @@ def test_check_console_messages(driver, pages, recwarn):
3838
assert console_api_calls[0].args[0].value == "I love cheese"
3939
assert console_api_calls[1].type_ == "error"
4040
assert console_api_calls[1].args[0].value == "I love bread"
41+
42+
43+
@pytest.mark.xfail_safari
44+
@pytest.mark.xfail_firefox
45+
@pytest.mark.xfail_remote
46+
def test_check_start_twice(clean_driver, clean_options):
47+
driver1 = clean_driver(options=clean_options)
48+
devtools1, connection1 = driver1.start_devtools()
49+
driver1.quit()
50+
51+
driver2 = clean_driver(options=clean_options)
52+
devtools2, connection2 = driver2.start_devtools()
53+
driver2.quit()

0 commit comments

Comments
 (0)