Skip to content

Commit f79f7c2

Browse files
authored
Merge branch 'trunk' into selenium_manager
2 parents 26efb88 + 8c50418 commit f79f7c2

4 files changed

Lines changed: 61 additions & 23 deletions

File tree

py/test/selenium/webdriver/common/api_example_tests.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,19 +243,21 @@ def test_is_element_displayed(driver, pages):
243243
@pytest.mark.xfail_safari
244244
def test_move_window_position(driver, pages):
245245
pages.load("blank.html")
246-
loc = driver.get_window_position()
246+
original = driver.get_window_position()
247247
# note can't test 0,0 since some OS's dont allow that location
248248
# because of system toolbars
249249
new_x = 50
250250
new_y = 50
251-
if loc["x"] == new_x:
251+
if original["x"] == new_x:
252252
new_x += 10
253-
if loc["y"] == new_y:
253+
if original["y"] == new_y:
254254
new_y += 10
255255
driver.set_window_position(new_x, new_y)
256256
loc = driver.get_window_position()
257-
assert loc["x"] == new_x
258-
assert loc["y"] == new_y
257+
# The window manager may clamp the requested position to the usable area of
258+
# the current display (e.g. below the menu bar / toolbar), so assert the
259+
# window moved rather than that it landed at an exact coordinate.
260+
assert loc["x"] != original["x"] or loc["y"] != original["y"]
259261

260262

261263
@pytest.mark.xfail_edge(reason="Window sometimes does not resize")

py/test/selenium/webdriver/common/bidi_network_tests.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ def callback(request: Request):
9898
# origin, suppressing authRequired challenges in later tests — restart the
9999
# driver afterwards so challenge-dependent tests start clean.
100100
@pytest.mark.needs_fresh_driver
101-
def test_continue_with_auth(driver):
101+
def test_continue_with_auth(driver, pages):
102102
callback_id = driver.network.add_auth_handler("postman", "password")
103103
assert callback_id is not None, "Request handler not added"
104104
driver.browsing_context.navigate(
105-
context=driver.current_window_handle, url="https://postman-echo.com/basic-auth", wait=ReadinessState.COMPLETE
105+
context=driver.current_window_handle, url=pages.url("basic-auth"), wait=ReadinessState.COMPLETE
106106
)
107107
assert "authenticated" in driver.page_source, "Authorization failed"
108108

@@ -410,32 +410,32 @@ def test_request_and_response_handlers_compose(driver, pages):
410410
# needs_fresh_driver: successful authentication warms the browser's HTTP auth
411411
# cache for the origin, which would suppress the challenge in later tests.
412412
@pytest.mark.needs_fresh_driver
413-
def test_provide_credentials_for_matching_url(driver):
413+
def test_provide_credentials_for_matching_url(driver, pages):
414414
def handle_authentication(auth):
415415
auth.provide_credentials("postman", "password")
416416

417-
handler_id = driver.network.add_authentication_handler(["https://postman-echo.com/**"], handle_authentication)
417+
handler_id = driver.network.add_authentication_handler(["**/basic-auth"], handle_authentication)
418418
try:
419-
_navigate(driver, "https://postman-echo.com/basic-auth")
419+
_navigate(driver, pages.url("basic-auth"))
420420
assert "authenticated" in driver.page_source, "Authorization failed"
421421
finally:
422422
driver.network.remove_authentication_handler(handler_id)
423423

424424

425-
def test_cancel_authentication_challenge(driver):
425+
def test_cancel_authentication_challenge(driver, pages):
426426
def handle_authentication(auth):
427427
auth.cancel()
428428

429429
handler_id = driver.network.add_authentication_handler(handle_authentication)
430430
try:
431-
_navigate(driver, "https://postman-echo.com/basic-auth")
431+
_navigate(driver, pages.url("basic-auth"))
432432
assert "authenticated" not in driver.page_source, "Cancelled challenge still authenticated"
433433
finally:
434434
driver.network.remove_authentication_handler(handler_id)
435435

436436

437437
@pytest.mark.needs_fresh_driver
438-
def test_authentication_handler_observes_challenge_details(driver):
438+
def test_authentication_handler_observes_challenge_details(driver, pages):
439439
challenges = []
440440

441441
def handle_authentication(auth):
@@ -444,9 +444,9 @@ def handle_authentication(auth):
444444

445445
handler_id = driver.network.add_authentication_handler(handle_authentication)
446446
try:
447-
_navigate(driver, "https://postman-echo.com/basic-auth")
447+
_navigate(driver, pages.url("basic-auth"))
448448
assert challenges, "Authentication handler did not run"
449-
assert challenges[0][0].startswith("https://postman-echo.com/basic-auth")
449+
assert challenges[0][0].endswith("/basic-auth")
450450
finally:
451451
driver.network.remove_authentication_handler(handler_id)
452452

@@ -472,21 +472,21 @@ def test_clear_authentication_handlers_removes_all_intercepts(driver):
472472
# ---------------------------------------------------------------------------
473473

474474

475-
def test_extra_header_is_sent_with_requests(driver):
475+
def test_extra_header_is_sent_with_requests(driver, pages):
476476
driver.network.add_extra_header("x-selenium-extra", "extra-header-value")
477477
try:
478-
_navigate(driver, "https://postman-echo.com/headers")
478+
_navigate(driver, pages.url("echo_headers"))
479479
assert "x-selenium-extra" in driver.page_source, "Extra header not sent"
480480
assert "extra-header-value" in driver.page_source, "Extra header value not sent"
481481
finally:
482482
driver.network.clear_extra_headers()
483483

484484

485-
def test_removed_extra_header_is_not_sent(driver):
485+
def test_removed_extra_header_is_not_sent(driver, pages):
486486
driver.network.add_extra_header("x-selenium-extra", "extra-header-value")
487487
driver.network.remove_extra_header("x-selenium-extra")
488488

489-
_navigate(driver, "https://postman-echo.com/headers")
489+
_navigate(driver, pages.url("echo_headers"))
490490
assert "x-selenium-extra" not in driver.page_source, "Removed extra header still sent"
491491
assert driver.network.intercepts == [], "Intercept not removed"
492492

py/test/selenium/webdriver/common/webserver.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
It serves the testing html pages that are needed by the webdriver unit tests.
2121
"""
2222

23+
import base64
2324
import contextlib
2425
import logging
2526
import os
@@ -45,6 +46,11 @@ def updir():
4546
DEFAULT_PORT = 8000
4647
HTML_ROOT = os.path.join(WEBDRIVER, "../../../../common/src/web")
4748

49+
# Credentials accepted by the /basic-auth endpoint. Tests that exercise
50+
# authentication handlers must provide these to be considered authenticated.
51+
AUTH_USERNAME = "postman"
52+
AUTH_PASSWORD = "password"
53+
4854
if not os.path.isdir(HTML_ROOT):
4955
raise Exception(
5056
"Can't find 'common_web' directory, try setting WEBDRIVER environment variable.\n"
@@ -80,6 +86,18 @@ def _serve_file(self, file_path):
8086
else:
8187
return content, "text/html"
8288

89+
def _is_authenticated(self):
90+
"""Return True when the request carries the expected Basic credentials."""
91+
auth_header = self.headers.get("Authorization", "")
92+
if not auth_header.startswith("Basic "):
93+
return False
94+
try:
95+
decoded = base64.b64decode(auth_header.removeprefix("Basic ")).decode("utf-8")
96+
except (ValueError, UnicodeDecodeError):
97+
return False
98+
username, _, password = decoded.partition(":")
99+
return username == AUTH_USERNAME and password == AUTH_PASSWORD
100+
83101
def _send_response(self, content_type="text/html"):
84102
"""Send a response."""
85103
self.send_response(200)
@@ -116,6 +134,20 @@ def do_GET(self):
116134
self.wfile.write(b"cookie set")
117135
return
118136

137+
if path == "basic-auth":
138+
if self._is_authenticated():
139+
self._send_response("application/json")
140+
self.wfile.write(b'{"authenticated": true}')
141+
else:
142+
self.send_response(401)
143+
self.send_header("WWW-Authenticate", 'Basic realm="Fake Realm"')
144+
self.send_header("Content-type", "text/plain")
145+
self.end_headers()
146+
# Body must not contain the substring "authenticated" — tests
147+
# assert its absence when an auth challenge is cancelled.
148+
self.wfile.write(b"Access denied")
149+
return
150+
119151
file_path = os.path.join(HTML_ROOT, path)
120152
if path.startswith("page/"):
121153
html = self._serve_page(path[5:])

py/test/selenium/webdriver/common/window_tests.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ def test_should_set_the_size_of_the_current_window(driver):
5858

5959
def test_should_get_the_position_of_the_current_window(driver):
6060
position = driver.get_window_position()
61-
assert position.get("x") >= 0
62-
assert position.get("y") >= 0
61+
# x/y may be negative on multi-monitor layouts (e.g. a display left of the
62+
# primary); the WebDriver spec places no lower bound on window coordinates.
63+
assert isinstance(position.get("x"), int)
64+
assert isinstance(position.get("y"), int)
6365

6466

6567
@pytest.mark.xfail_chrome
@@ -85,8 +87,10 @@ def test_should_set_the_position_of_the_current_window(driver):
8587
@pytest.mark.xfail_safari(raises=WebDriverException, reason="Get Window Rect command not implemented")
8688
def test_should_get_the_rect_of_the_current_window(driver):
8789
rect = driver.get_window_rect()
88-
assert rect.get("x") >= 0
89-
assert rect.get("y") >= 0
90+
# x/y may be negative on multi-monitor layouts; only width/height have a
91+
# genuine non-negative lower bound.
92+
assert isinstance(rect.get("x"), int)
93+
assert isinstance(rect.get("y"), int)
9094
assert rect.get("width") >= 0
9195
assert rect.get("height") >= 0
9296

0 commit comments

Comments
 (0)