Skip to content

Commit c63406c

Browse files
authored
Merge branch 'SeleniumHQ:trunk' into py-server-standalone-control
2 parents a08d084 + 169ce63 commit c63406c

File tree

7 files changed

+69
-38
lines changed

7 files changed

+69
-38
lines changed

py/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,13 @@ def clean_driver(request):
362362

363363
@pytest.fixture
364364
def firefox_options(request):
365+
try:
366+
driver_option = request.config.option.drivers[0]
367+
except (AttributeError, TypeError):
368+
raise Exception("This test requires a --driver to be specified")
369+
# skip tests in the 'remote' directory if run with a local driver
370+
if request.node.path.parts[-2] == "remote" and get_driver_class(driver_option) != "Remote":
371+
pytest.skip(f"Remote tests can't be run with driver '{driver_option}'")
365372
options = webdriver.FirefoxOptions()
366373
if request.config.option.headless:
367374
options.add_argument("-headless")

py/selenium/webdriver/remote/client_config.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17+
1718
import base64
1819
import os
1920
import socket
@@ -96,24 +97,14 @@ def __init__(
9697
self.proxy = proxy
9798
self.ignore_certificates = ignore_certificates
9899
self.init_args_for_pool_manager = init_args_for_pool_manager or {}
99-
self.timeout = timeout
100+
self.timeout = socket.getdefaulttimeout() if timeout is None else timeout
100101
self.username = username
101102
self.password = password
102103
self.auth_type = auth_type
103104
self.token = token
104105
self.user_agent = user_agent
105106
self.extra_headers = extra_headers
106107

107-
self.timeout = (
108-
(
109-
float(os.getenv("GLOBAL_DEFAULT_TIMEOUT", str(socket.getdefaulttimeout())))
110-
if os.getenv("GLOBAL_DEFAULT_TIMEOUT") is not None
111-
else socket.getdefaulttimeout()
112-
)
113-
if timeout is None
114-
else timeout
115-
)
116-
117108
self.ca_certs = (
118109
(os.getenv("REQUESTS_CA_BUNDLE") if "REQUESTS_CA_BUNDLE" in os.environ else certifi.where())
119110
if ca_certs is None

py/selenium/webdriver/remote/remote_connection.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,7 @@ class RemoteConnection:
152152

153153
import certifi
154154

155-
_timeout = (
156-
float(os.getenv("GLOBAL_DEFAULT_TIMEOUT", str(socket.getdefaulttimeout())))
157-
if os.getenv("GLOBAL_DEFAULT_TIMEOUT") is not None
158-
else socket.getdefaulttimeout()
159-
)
155+
_timeout = socket.getdefaulttimeout()
160156
_ca_certs = os.getenv("REQUESTS_CA_BUNDLE") if "REQUESTS_CA_BUNDLE" in os.environ else certifi.where()
161157
_client_config: ClientConfig = None
162158

@@ -168,6 +164,10 @@ class RemoteConnection:
168164
extra_headers = None
169165
user_agent = f"selenium/{__version__} (python {system})"
170166

167+
@property
168+
def client_config(self):
169+
return self._client_config
170+
171171
@classmethod
172172
def get_timeout(cls):
173173
""":Returns:
@@ -176,7 +176,7 @@ def get_timeout(cls):
176176
Remote Connection
177177
"""
178178
warnings.warn(
179-
"get_timeout() in RemoteConnection is deprecated, get timeout from ClientConfig instance instead",
179+
"get_timeout() in RemoteConnection is deprecated, get timeout from client_config instead",
180180
DeprecationWarning,
181181
stacklevel=2,
182182
)
@@ -190,7 +190,7 @@ def set_timeout(cls, timeout):
190190
- timeout - timeout value for http requests in seconds
191191
"""
192192
warnings.warn(
193-
"set_timeout() in RemoteConnection is deprecated, set timeout to ClientConfig instance in constructor instead",
193+
"set_timeout() in RemoteConnection is deprecated, set timeout in client_config instead",
194194
DeprecationWarning,
195195
stacklevel=2,
196196
)
@@ -200,7 +200,7 @@ def set_timeout(cls, timeout):
200200
def reset_timeout(cls):
201201
"""Reset the http request timeout to socket._GLOBAL_DEFAULT_TIMEOUT."""
202202
warnings.warn(
203-
"reset_timeout() in RemoteConnection is deprecated, use reset_timeout() in ClientConfig instance instead",
203+
"reset_timeout() in RemoteConnection is deprecated, use reset_timeout() in client_config instead",
204204
DeprecationWarning,
205205
stacklevel=2,
206206
)
@@ -215,7 +215,7 @@ def get_certificate_bundle_path(cls):
215215
REQUESTS_CA_BUNDLE env variable if set.
216216
"""
217217
warnings.warn(
218-
"get_certificate_bundle_path() in RemoteConnection is deprecated, get ca_certs from ClientConfig instance instead",
218+
"get_certificate_bundle_path() in RemoteConnection is deprecated, get ca_certs from client_config instead",
219219
DeprecationWarning,
220220
stacklevel=2,
221221
)
@@ -231,7 +231,7 @@ def set_certificate_bundle_path(cls, path):
231231
- path - path of a .pem encoded certificate chain.
232232
"""
233233
warnings.warn(
234-
"set_certificate_bundle_path() in RemoteConnection is deprecated, set ca_certs to ClientConfig instance in constructor instead",
234+
"set_certificate_bundle_path() in RemoteConnection is deprecated, set ca_certs in client_config instead",
235235
DeprecationWarning,
236236
stacklevel=2,
237237
)
@@ -328,35 +328,35 @@ def __init__(
328328

329329
if remote_server_addr:
330330
warnings.warn(
331-
"setting remote_server_addr in RemoteConnection() is deprecated, set in ClientConfig instance instead",
331+
"setting remote_server_addr in RemoteConnection() is deprecated, set in client_config instead",
332332
DeprecationWarning,
333333
stacklevel=2,
334334
)
335335

336336
if not keep_alive:
337337
warnings.warn(
338-
"setting keep_alive in RemoteConnection() is deprecated, set in ClientConfig instance instead",
338+
"setting keep_alive in RemoteConnection() is deprecated, set in client_config instead",
339339
DeprecationWarning,
340340
stacklevel=2,
341341
)
342342

343343
if ignore_certificates:
344344
warnings.warn(
345-
"setting ignore_certificates in RemoteConnection() is deprecated, set in ClientConfig instance instead",
345+
"setting ignore_certificates in RemoteConnection() is deprecated, set in client_config instead",
346346
DeprecationWarning,
347347
stacklevel=2,
348348
)
349349

350350
if init_args_for_pool_manager:
351351
warnings.warn(
352-
"setting init_args_for_pool_manager in RemoteConnection() is deprecated, set in ClientConfig instance instead",
352+
"setting init_args_for_pool_manager in RemoteConnection() is deprecated, set in client_config instead",
353353
DeprecationWarning,
354354
stacklevel=2,
355355
)
356356

357357
if ignore_proxy:
358358
warnings.warn(
359-
"setting ignore_proxy in RemoteConnection() is deprecated, set in ClientConfig instance instead",
359+
"setting ignore_proxy in RemoteConnection() is deprecated, set in client_config instead",
360360
DeprecationWarning,
361361
stacklevel=2,
362362
)

py/test/selenium/webdriver/common/timeout_tests.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
1918
import pytest
2019

2120
from selenium.webdriver.common.timeouts import Timeouts

py/test/selenium/webdriver/common/webdriverwait_tests.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import time
1919

2020
import pytest
21+
from urllib3.exceptions import ReadTimeoutError
2122

2223
from selenium.common.exceptions import InvalidElementStateException
2324
from selenium.common.exceptions import InvalidSelectorException
@@ -357,3 +358,14 @@ def test_expected_condition_attribute_to_be_include_in_element(driver, pages):
357358
WebDriverWait(driver, 0.01).until(EC.element_attribute_to_include((By.ID, "inputRequired"), "test"))
358359
value = WebDriverWait(driver, 5).until(EC.element_attribute_to_include((By.ID, "inputRequired"), "value"))
359360
assert value is not None
361+
362+
363+
def test_driver_with_http_timeout(driver, pages):
364+
"""This test starts a webdriver with an http client timeout set less than the implicit
365+
wait, and verifies the http timeout is triggered first when waiting for an element.
366+
"""
367+
pages.load("simpleTest.html")
368+
driver.command_executor.client_config.timeout = 6
369+
driver.implicitly_wait(8)
370+
with pytest.raises(ReadTimeoutError):
371+
driver.find_element(By.ID, "no_element_to_be_found")

py/test/selenium/webdriver/remote/remote_connection_tests.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
import base64
1919

2020
import filetype
21+
import pytest
22+
from urllib3.exceptions import ReadTimeoutError
23+
24+
from selenium import webdriver
25+
from selenium.webdriver.common.by import By
26+
from selenium.webdriver.remote.client_config import ClientConfig
2127

2228

2329
def test_browser_specific_method(driver, pages):
@@ -27,3 +33,20 @@ def test_browser_specific_method(driver, pages):
2733
result = base64.b64decode(screenshot)
2834
kind = filetype.guess(result)
2935
assert kind is not None and kind.mime == "image/png"
36+
37+
38+
def test_remote_webdriver_with_http_timeout(firefox_options, webserver):
39+
"""This test starts a remote webdriver with an http client timeout
40+
set less than the implicit wait timeout, and verifies the http timeout
41+
is triggered first when waiting for an element.
42+
"""
43+
http_timeout = 6
44+
wait_timeout = 8
45+
server_addr = f"http://{webserver.host}:{webserver.port}"
46+
client_config = ClientConfig(remote_server_addr=server_addr, timeout=http_timeout)
47+
assert client_config.timeout == http_timeout
48+
with webdriver.Remote(options=firefox_options, client_config=client_config) as driver:
49+
driver.get(f"{server_addr}/simpleTest.html")
50+
driver.implicitly_wait(wait_timeout)
51+
with pytest.raises(ReadTimeoutError):
52+
driver.find_element(By.ID, "no_element_to_be_found")

py/test/unit/selenium/webdriver/remote/remote_connection_tests.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def test_get_remote_connection_headers_adds_keep_alive_if_requested():
8787
def test_get_proxy_url_http(mock_proxy_settings):
8888
proxy = "http://http_proxy.com:8080"
8989
remote_connection = RemoteConnection("http://remote", keep_alive=False)
90-
proxy_url = remote_connection._client_config.get_proxy_url()
90+
proxy_url = remote_connection.client_config.get_proxy_url()
9191
assert proxy_url == proxy
9292

9393

@@ -96,7 +96,7 @@ def test_get_auth_header_if_client_config_pass_basic_auth():
9696
remote_server_addr="http://remote", keep_alive=True, username="user", password="pass", auth_type=AuthType.BASIC
9797
)
9898
remote_connection = RemoteConnection(custom_config.remote_server_addr, client_config=custom_config)
99-
headers = remote_connection._client_config.get_auth_header()
99+
headers = remote_connection.client_config.get_auth_header()
100100
assert headers.get("Authorization") == "Basic dXNlcjpwYXNz"
101101

102102

@@ -105,7 +105,7 @@ def test_get_auth_header_if_client_config_pass_bearer_token():
105105
remote_server_addr="http://remote", keep_alive=True, auth_type=AuthType.BEARER, token="dXNlcjpwYXNz"
106106
)
107107
remote_connection = RemoteConnection(custom_config.remote_server_addr, client_config=custom_config)
108-
headers = remote_connection._client_config.get_auth_header()
108+
headers = remote_connection.client_config.get_auth_header()
109109
assert headers.get("Authorization") == "Bearer dXNlcjpwYXNz"
110110

111111

@@ -114,14 +114,14 @@ def test_get_auth_header_if_client_config_pass_x_api_key():
114114
remote_server_addr="http://remote", keep_alive=True, auth_type=AuthType.X_API_KEY, token="abcdefgh123456789"
115115
)
116116
remote_connection = RemoteConnection(custom_config.remote_server_addr, client_config=custom_config)
117-
headers = remote_connection._client_config.get_auth_header()
117+
headers = remote_connection.client_config.get_auth_header()
118118
assert headers.get("X-API-Key") == "abcdefgh123456789"
119119

120120

121121
def test_get_proxy_url_https(mock_proxy_settings):
122122
proxy = "http://https_proxy.com:8080"
123123
remote_connection = RemoteConnection("https://remote", keep_alive=False)
124-
proxy_url = remote_connection._client_config.get_proxy_url()
124+
proxy_url = remote_connection.client_config.get_proxy_url()
125125
assert proxy_url == proxy
126126

127127

@@ -162,7 +162,7 @@ def test_get_proxy_direct_via_client_config():
162162
remote_connection = RemoteConnection(client_config=client_config)
163163
conn = remote_connection._get_connection_manager()
164164
assert isinstance(conn, urllib3.PoolManager)
165-
proxy_url = remote_connection._client_config.get_proxy_url()
165+
proxy_url = remote_connection.client_config.get_proxy_url()
166166
assert proxy_url is None
167167

168168

@@ -176,19 +176,19 @@ def test_get_proxy_system_matches_no_proxy_via_client_config():
176176
remote_connection = RemoteConnection(client_config=client_config)
177177
conn = remote_connection._get_connection_manager()
178178
assert isinstance(conn, urllib3.PoolManager)
179-
proxy_url = remote_connection._client_config.get_proxy_url()
179+
proxy_url = remote_connection.client_config.get_proxy_url()
180180
assert proxy_url is None
181181

182182

183183
def test_get_proxy_url_none(mock_proxy_settings_missing):
184184
remote_connection = RemoteConnection("https://remote", keep_alive=False)
185-
proxy_url = remote_connection._client_config.get_proxy_url()
185+
proxy_url = remote_connection.client_config.get_proxy_url()
186186
assert proxy_url is None
187187

188188

189189
def test_get_proxy_url_http_auth(mock_proxy_auth_settings):
190190
remote_connection = RemoteConnection("http://remote", keep_alive=False)
191-
proxy_url = remote_connection._client_config.get_proxy_url()
191+
proxy_url = remote_connection.client_config.get_proxy_url()
192192
raw_proxy_url, basic_auth_string = remote_connection._separate_http_proxy_auth()
193193
assert proxy_url == "http://user:password@http_proxy.com:8080"
194194
assert raw_proxy_url == "http://http_proxy.com:8080"
@@ -197,7 +197,7 @@ def test_get_proxy_url_http_auth(mock_proxy_auth_settings):
197197

198198
def test_get_proxy_url_https_auth(mock_proxy_auth_settings):
199199
remote_connection = RemoteConnection("https://remote", keep_alive=False)
200-
proxy_url = remote_connection._client_config.get_proxy_url()
200+
proxy_url = remote_connection.client_config.get_proxy_url()
201201
raw_proxy_url, basic_auth_string = remote_connection._separate_http_proxy_auth()
202202
assert proxy_url == "https://user:password@https_proxy.com:8080"
203203
assert raw_proxy_url == "https://https_proxy.com:8080"
@@ -489,7 +489,6 @@ def test_get_connection_manager_ignores_certificates():
489489
assert conn.connection_pool_kw["timeout"] == 10
490490
assert conn.connection_pool_kw["cert_reqs"] == "CERT_NONE"
491491
assert isinstance(conn, urllib3.PoolManager)
492-
493492
remote_connection.reset_timeout()
494493
assert remote_connection.get_timeout() is None
495494

0 commit comments

Comments
 (0)