summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webdriver
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /testing/web-platform/tests/webdriver
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webdriver')
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/__init__.py31
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/browsing_context/classic_interop/window_handle.py7
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/locator.py232
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py62
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/invalid.py11
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/set_permission.py54
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/integration/__init__.py (renamed from testing/web-platform/tests/webdriver/tests/bidi/browsing_context/classic_interop/__init__.py)0
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/integration/cookies_with_network_events.py201
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/network/__init__.py22
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/contexts.py74
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent.py23
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/network/conftest.py102
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/network/provide_response/request.py12
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed.py25
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started.py25
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/script/__init__.py8
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/partition.py4
-rw-r--r--testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/support/black_dot.pngbin0 -> 70 bytes
-rw-r--r--testing/web-platform/tests/webdriver/tests/classic/element_click/interactability.py14
-rw-r--r--testing/web-platform/tests/webdriver/tests/classic/element_click/scroll_into_view.py8
-rw-r--r--testing/web-platform/tests/webdriver/tests/classic/switch_to_parent_frame/switch.py34
-rw-r--r--testing/web-platform/tests/webdriver/tests/interop/__init__.py (renamed from testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/__init__.py)0
-rw-r--r--testing/web-platform/tests/webdriver/tests/interop/frames.py37
-rw-r--r--testing/web-platform/tests/webdriver/tests/interop/shared_id_node.py (renamed from testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/node_shared_id.py)0
-rw-r--r--testing/web-platform/tests/webdriver/tests/interop/shared_id_window.py (renamed from testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/window_reference.py)4
-rw-r--r--testing/web-platform/tests/webdriver/tests/support/fixtures_bidi.py110
-rw-r--r--testing/web-platform/tests/webdriver/tests/support/inline.py2
27 files changed, 765 insertions, 337 deletions
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/__init__.py
index 98b670f89f..c8715183b0 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/__init__.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/__init__.py
@@ -71,6 +71,15 @@ def int_interval(start: int, end: int) -> Callable[[Any], None]:
return _
+def assert_cookies(cookies, expected_cookies):
+ assert len(cookies) == len(expected_cookies)
+
+ expected = sorted(expected_cookies, key=lambda cookie: cookie["name"])
+ actual = sorted(cookies, key=lambda cookie: cookie["name"])
+
+ recursive_compare(expected, actual)
+
+
def assert_handle(obj: Mapping[str, Any], should_contain_handle: bool) -> None:
if should_contain_handle:
assert "handle" in obj, f"Result should contain `handle`. Actual: {obj}"
@@ -128,13 +137,21 @@ async def get_element_dimensions(bidi_session, context, element):
return remote_mapping_to_dict(result["value"])
-async def get_viewport_dimensions(bidi_session, context: str):
- expression = """
- ({
- height: window.innerHeight || document.documentElement.clientHeight,
- width: window.innerWidth || document.documentElement.clientWidth,
- });
- """
+async def get_viewport_dimensions(bidi_session, context: str, with_scrollbar: bool = True):
+ if with_scrollbar == True:
+ expression = """
+ ({
+ height: window.innerHeight,
+ width: window.innerWidth,
+ });
+ """
+ else:
+ expression = """
+ ({
+ height: document.documentElement.clientHeight,
+ width: document.documentElement.clientWidth,
+ });
+ """
result = await bidi_session.script.evaluate(
expression=expression,
target=ContextTarget(context["context"]),
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/classic_interop/window_handle.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/classic_interop/window_handle.py
deleted file mode 100644
index 4f36fba197..0000000000
--- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/classic_interop/window_handle.py
+++ /dev/null
@@ -1,7 +0,0 @@
-import pytest
-
-pytestmark = pytest.mark.asyncio
-
-
-async def test_top_level_context_id_equals_window_handle(top_context, current_session):
- assert top_context["context"] == current_session.window_handle
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/locator.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/locator.py
index 656eaddc1f..e560fa9239 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/locator.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/locator.py
@@ -48,134 +48,88 @@ async def test_find_by_locator(bidi_session, inline, top_context, type, value):
recursive_compare(expected, result["nodes"])
-@pytest.mark.parametrize("ignore_case,match_type,max_depth,value,expected", [
- (True, "full", None, "bar", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 1,
- "children": [],
- "localName": "strong",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- },
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 1,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- ),
- (False, "full", None, "BAR", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 1,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- ),
- (True, "partial", None, "ba", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 1,
- "localName": "strong",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- },
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 1,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- ),
- (False, "partial", None, "ba", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 1,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- ),
- (True, "full", 0, "foobarbarbaz", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 4,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- ),
- (False, "full", 0, "foobarBARbaz", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 4,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- ),
- (True, "partial", 0, "bar", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 4,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- ),
- (False, "partial", 0, "BAR", [
- {
- "type": "node",
- "sharedId": any_string,
- "value": {
- "attributes": {},
- "childNodeCount": 4,
- "localName": "span",
- "namespaceURI": "http://www.w3.org/1999/xhtml",
- "nodeType": 1,
- }
- }]
- )
+@pytest.mark.parametrize("locator,expected_nodes_values", [
+ ({
+ "type": "innerText",
+ "ignoreCase": True,
+ "matchType": "full",
+ "value": "bar"
+ }, ["strong", "span"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": False,
+ "matchType": "full",
+ "value": "BAR"
+ }, ["span"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": True,
+ "matchType": "partial",
+ "value": "ba"
+ }, ["strong", "span"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": False,
+ "matchType": "partial",
+ "value": "ba"
+ }, ["strong"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": True,
+ "matchType": "full",
+ "maxDepth": 0,
+ "value": "foobarbarbaz"
+ }, ["body"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": False,
+ "matchType": "full",
+ "maxDepth": 0,
+ "value": "foobarBARbaz"
+ }, ["body"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": True,
+ "matchType": "partial",
+ "maxDepth": 0,
+ "value": "bar"
+ }, ["body"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": False,
+ "matchType": "partial",
+ "maxDepth": 0,
+ "value": "BAR"
+ }, ["body"]),
+ ({
+
+ "type": "innerText",
+ "ignoreCase": True,
+ "matchType": "full",
+ "maxDepth": 1,
+ "value": "foobarbarbaz"
+ }, ["div"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": False,
+ "matchType": "full",
+ "maxDepth": 1,
+ "value": "foobarBARbaz"
+ }, ["div"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": True,
+ "matchType": "partial",
+ "maxDepth": 1,
+ "value": "bar"
+ }, ["div"]),
+ ({
+ "type": "innerText",
+ "ignoreCase": False,
+ "matchType": "partial",
+ "maxDepth": 1,
+ "value": "BAR"
+ }, ["div"]),
], ids=[
"ignore_case_true_full_match_no_max_depth",
"ignore_case_false_full_match_no_max_depth",
@@ -185,23 +139,29 @@ async def test_find_by_locator(bidi_session, inline, top_context, type, value):
"ignore_case_false_full_match_max_depth_zero",
"ignore_case_true_partial_match_max_depth_zero",
"ignore_case_false_partial_match_max_depth_zero",
+ "ignore_case_true_full_match_max_depth_one",
+ "ignore_case_false_full_match_max_depth_one",
+ "ignore_case_true_partial_match_max_depth_one",
+ "ignore_case_false_partial_match_max_depth_one",
])
@pytest.mark.asyncio
-async def test_find_by_inner_text(bidi_session, inline, top_context, ignore_case, match_type, max_depth, value, expected):
+async def test_find_by_inner_text(bidi_session, inline, top_context, locator, expected_nodes_values):
url = inline("""<div>foo<span><strong>bar</strong></span><span>BAR</span>baz</div>""")
await bidi_session.browsing_context.navigate(
context=top_context["context"], url=url, wait="complete"
)
+ # Construct expected nodes list with the expected nodes values emitting other fields.
+ expected = [{
+ "type": "node",
+ "value": {
+ "localName": node_value,
+ }
+ } for node_value in expected_nodes_values]
+
result = await bidi_session.browsing_context.locate_nodes(
context=top_context["context"],
- locator={
- "type": "innerText",
- "value": value,
- "ignoreCase": ignore_case,
- "matchType": match_type,
- "maxDepth": max_depth
- }
+ locator=locator
)
recursive_compare(expected, result["nodes"])
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py
index 60f9e47040..2e8126b1f8 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py
@@ -184,3 +184,65 @@ async def test_persists_on_reload(bidi_session, inline, new_tab):
)
assert await get_viewport_dimensions(bidi_session, new_tab) == test_viewport
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize(
+ "use_horizontal_scrollbar, use_vertical_scrollbar",
+ [
+ (True, False),
+ (False, True),
+ (True, True),
+ ],
+ ids=["horizontal", "vertical", "both"],
+)
+@pytest.mark.parametrize(
+ "doctype",
+ ["html", "html_quirks"],
+ ids=["standard", "quirks"],
+)
+async def test_with_scrollbars(
+ bidi_session,
+ inline,
+ new_tab,
+ use_horizontal_scrollbar,
+ use_vertical_scrollbar,
+ doctype,
+):
+ viewport_dimensions = await get_viewport_dimensions(bidi_session, new_tab)
+
+ width = 100
+ if use_horizontal_scrollbar:
+ width = viewport_dimensions["width"] + 100
+
+ height = 100
+ if use_vertical_scrollbar:
+ height = viewport_dimensions["height"] + 100
+
+ html = f"""<div style="width: {width}px; height: {height}px;">foo</div>"""
+ page_url = inline(html, doctype=doctype)
+
+ await bidi_session.browsing_context.navigate(
+ context=new_tab["context"], url=page_url, wait="complete"
+ )
+
+ test_viewport = {"width": 499, "height": 599}
+
+ assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
+
+ await bidi_session.browsing_context.set_viewport(
+ context=new_tab["context"], viewport=test_viewport
+ )
+
+ assert await get_viewport_dimensions(bidi_session, new_tab) == test_viewport
+
+ viewport_without_scrollbar = await get_viewport_dimensions(
+ bidi_session, new_tab, with_scrollbar=False
+ )
+
+ # The side which has scrollbar takes up space on the other side
+ # (e.g. if we have a horizontal scroll height is going to be smaller than viewport height)
+ if use_horizontal_scrollbar:
+ assert viewport_without_scrollbar["height"] < test_viewport["height"]
+ if use_vertical_scrollbar:
+ assert viewport_without_scrollbar["width"] < test_viewport["width"]
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/invalid.py
index 0ace04e8bc..5397dc7b62 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/invalid.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/invalid.py
@@ -52,3 +52,14 @@ async def test_params_origin_invalid_type(bidi_session, origin):
state="granted",
origin=origin,
)
+
+
+@pytest.mark.parametrize("user_context", [False, 42, {}, [], None])
+async def test_params_origin_invalid_type(bidi_session, user_context):
+ with pytest.raises(error.InvalidArgumentException):
+ await bidi_session.permissions.set_permission(
+ descriptor={"name": "geolocation"},
+ state="granted",
+ origin="https://example.com",
+ user_context=user_context,
+ )
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/set_permission.py b/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/set_permission.py
index 92ebed1e63..45c50dbf88 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/set_permission.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/external/permissions/set_permission/set_permission.py
@@ -16,7 +16,7 @@ async def test_set_permission(bidi_session, new_tab, url):
origin = await get_context_origin(bidi_session, new_tab)
- assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
await bidi_session.permissions.set_permission(
descriptor={"name": "geolocation"},
@@ -24,7 +24,7 @@ async def test_set_permission(bidi_session, new_tab, url):
origin=origin,
)
- assert await get_permission_state(bidi_session, new_tab, "geolocation") == "granted"
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "granted"
await bidi_session.permissions.set_permission(
descriptor={"name": "geolocation"},
@@ -32,7 +32,7 @@ async def test_set_permission(bidi_session, new_tab, url):
origin=origin,
)
- assert await get_permission_state(bidi_session, new_tab, "geolocation") == "denied"
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "denied"
await bidi_session.permissions.set_permission(
descriptor={"name": "geolocation"},
@@ -40,7 +40,7 @@ async def test_set_permission(bidi_session, new_tab, url):
origin=origin,
)
- assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
@pytest.mark.asyncio
@@ -73,7 +73,7 @@ async def test_set_permission_new_context(bidi_session, new_tab, url):
origin = await get_context_origin(bidi_session, new_tab)
- assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
await bidi_session.permissions.set_permission(
descriptor={"name": "geolocation"},
@@ -81,7 +81,7 @@ async def test_set_permission_new_context(bidi_session, new_tab, url):
origin=origin,
)
- assert await get_permission_state(bidi_session, new_tab, "geolocation") == "granted"
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "granted"
new_context = await bidi_session.browsing_context.create(type_hint="tab")
assert new_tab["context"] != new_context["context"]
@@ -92,7 +92,7 @@ async def test_set_permission_new_context(bidi_session, new_tab, url):
)
# See https://github.com/w3c/permissions/issues/437.
- assert await get_permission_state(bidi_session, new_context, "geolocation") == "granted"
+ assert await get_permission_state(bidi_session, new_context, "geolocation") == "granted"
@pytest.mark.parametrize("origin", ['UNKNOWN', ''])
@@ -117,4 +117,42 @@ async def test_set_permission_origin_unknown(bidi_session, new_tab, origin, url)
state="granted",
origin=origin,
)
- assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
+
+
+@pytest.mark.asyncio
+async def test_set_permission_user_context(bidi_session, new_tab, url, create_user_context):
+ test_url = url("/common/blank.html", protocol="https")
+
+ user_context = await create_user_context()
+ # new_tab is in the default user context. new_tab2 is in the non-default user context.
+ new_tab2 = await bidi_session.browsing_context.create(type_hint="tab", user_context=user_context)
+
+ # Navigate a context in the default user context.
+ await bidi_session.browsing_context.navigate(
+ context=new_tab["context"],
+ url=test_url,
+ wait="complete",
+ )
+
+ # Navigate a context in the non-default user context.
+ await bidi_session.browsing_context.navigate(
+ context=new_tab2["context"],
+ url=test_url,
+ wait="complete",
+ )
+
+ origin = await get_context_origin(bidi_session, new_tab)
+
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
+ assert await get_permission_state(bidi_session, new_tab2, "geolocation") == "prompt"
+
+ await bidi_session.permissions.set_permission(
+ descriptor={"name": "geolocation"},
+ state="granted",
+ origin=origin,
+ user_context=user_context,
+ )
+
+ assert await get_permission_state(bidi_session, new_tab, "geolocation") == "prompt"
+ assert await get_permission_state(bidi_session, new_tab2, "geolocation") == "granted"
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/classic_interop/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/integration/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/classic_interop/__init__.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/integration/__init__.py
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/integration/cookies_with_network_events.py b/testing/web-platform/tests/webdriver/tests/bidi/integration/cookies_with_network_events.py
new file mode 100644
index 0000000000..e7fddbb1c4
--- /dev/null
+++ b/testing/web-platform/tests/webdriver/tests/bidi/integration/cookies_with_network_events.py
@@ -0,0 +1,201 @@
+import pytest
+
+from webdriver.bidi.modules.script import ContextTarget
+from webdriver.bidi.modules.storage import BrowsingContextPartitionDescriptor
+
+from .. import assert_cookies
+
+pytestmark = pytest.mark.asyncio
+
+PNG_BLACK_DOT = "/webdriver/tests/bidi/storage/get_cookies/support/black_dot.png"
+
+
+async def test_top_context(
+ bidi_session,
+ new_tab,
+ inline,
+ setup_network_test,
+ wait_for_event,
+ wait_for_future_safe,
+):
+ cookie_name = "foo"
+ cookie_value = "bar"
+ url = inline(
+ "<div>with cookies</div>",
+ parameters={"pipe": f"header(Set-Cookie, {cookie_name}={cookie_value})"},
+ )
+
+ await bidi_session.browsing_context.navigate(
+ context=new_tab["context"], url=url, wait="complete"
+ )
+
+ BEFORE_REQUEST_SENT_EVENT = "network.beforeRequestSent"
+ network_events = await setup_network_test(events=[BEFORE_REQUEST_SENT_EVENT])
+ events = network_events[BEFORE_REQUEST_SENT_EVENT]
+ on_before_request_sent = wait_for_event(BEFORE_REQUEST_SENT_EVENT)
+
+ await bidi_session.browsing_context.reload(
+ context=new_tab["context"], wait="complete"
+ )
+
+ await wait_for_future_safe(on_before_request_sent)
+
+ result = await bidi_session.storage.get_cookies(
+ partition=BrowsingContextPartitionDescriptor(new_tab["context"])
+ )
+
+ assert_cookies(result["cookies"], events[0]["request"]["cookies"])
+
+ await bidi_session.storage.delete_cookies()
+
+
+@pytest.mark.parametrize("domain_1", ["", "alt"], ids=["same_origin", "cross_origin"])
+async def test_iframe(
+ bidi_session,
+ new_tab,
+ inline,
+ setup_network_test,
+ wait_for_event,
+ wait_for_future_safe,
+ domain_1,
+):
+ cookie_name = "bar"
+ cookie_value = "foo"
+ iframe_url = inline(
+ "<div id='in-iframe'>with cookies</div>",
+ domain=domain_1,
+ parameters={"pipe": f"header(Set-Cookie, {cookie_name}={cookie_value})"},
+ )
+
+ await bidi_session.browsing_context.navigate(
+ context=new_tab["context"], url=iframe_url, wait="complete"
+ )
+
+ BEFORE_REQUEST_SENT_EVENT = "network.beforeRequestSent"
+ network_events = await setup_network_test(events=[BEFORE_REQUEST_SENT_EVENT])
+ events = network_events[BEFORE_REQUEST_SENT_EVENT]
+ on_before_request_sent = wait_for_event(BEFORE_REQUEST_SENT_EVENT)
+
+ page_url = inline(f"<iframe src='{iframe_url}'></iframe>")
+ await bidi_session.browsing_context.navigate(
+ context=new_tab["context"], url=page_url, wait="complete"
+ )
+
+ await wait_for_future_safe(on_before_request_sent)
+
+ all_contexts = await bidi_session.browsing_context.get_tree(root=new_tab["context"])
+ iframe_context = all_contexts[0]["children"][0]["context"]
+
+ result = await bidi_session.storage.get_cookies(
+ partition=BrowsingContextPartitionDescriptor(iframe_context)
+ )
+
+ # Find the network event which belongs to the iframe.
+ event_for_iframe = next(
+ event for event in events if event["context"] == iframe_context
+ )
+
+ assert_cookies(result["cookies"], event_for_iframe["request"]["cookies"])
+
+ # Remove the coookie.
+ await bidi_session.storage.delete_cookies()
+
+
+@pytest.mark.parametrize("domain_1", ["", "alt"], ids=["same_origin", "cross_origin"])
+async def test_fetch(
+ bidi_session,
+ new_tab,
+ setup_network_test,
+ wait_for_event,
+ fetch,
+ wait_for_future_safe,
+ url,
+ domain_1,
+):
+ # Clean up cookies in case some other tests failed before cleaning up.
+ await bidi_session.storage.delete_cookies()
+
+ cookie_name = "foo"
+ cookie_value = "bar"
+ # Add `Access-Control-Allow-Origin` header for cross-origin request to work.
+ request_url = url(
+ "/webdriver/tests/support/http_handlers/headers.py?header=Access-Control-Allow-Origin:*",
+ domain=domain_1,
+ )
+
+ await bidi_session.script.evaluate(
+ expression=f"document.cookie = '{cookie_name}={cookie_value}';",
+ target=ContextTarget(new_tab["context"]),
+ await_promise=False,
+ )
+
+ BEFORE_REQUEST_SENT_EVENT = "network.beforeRequestSent"
+ network_events = await setup_network_test(events=[BEFORE_REQUEST_SENT_EVENT])
+ events = network_events[BEFORE_REQUEST_SENT_EVENT]
+
+ on_before_request_sent = wait_for_event(BEFORE_REQUEST_SENT_EVENT)
+ await fetch(request_url, method="GET")
+ await wait_for_future_safe(on_before_request_sent)
+
+ result = await bidi_session.storage.get_cookies(
+ partition=BrowsingContextPartitionDescriptor(new_tab["context"])
+ )
+ assert_cookies(result["cookies"], events[0]["request"]["cookies"])
+
+ # Remove the coookie.
+ await bidi_session.storage.delete_cookies()
+
+
+@pytest.mark.parametrize("domain_1", ["", "alt"], ids=["same_origin", "cross_origin"])
+async def test_image(
+ bidi_session,
+ new_tab,
+ setup_network_test,
+ wait_for_event,
+ wait_for_future_safe,
+ url,
+ inline,
+ domain_1,
+):
+ # Clean up cookies in case some other tests failed before cleaning up.
+ await bidi_session.storage.delete_cookies()
+
+ cookie_name = "bar"
+ cookie_value = "foo"
+
+ image_url = url(PNG_BLACK_DOT)
+
+ await bidi_session.browsing_context.navigate(
+ context=new_tab["context"], url=image_url, wait="complete"
+ )
+
+ await bidi_session.script.evaluate(
+ expression=f"document.cookie = '{cookie_name}={cookie_value}';",
+ target=ContextTarget(new_tab["context"]),
+ await_promise=False,
+ )
+
+ BEFORE_REQUEST_SENT_EVENT = "network.beforeRequestSent"
+ network_events = await setup_network_test(events=[BEFORE_REQUEST_SENT_EVENT])
+ events = network_events[BEFORE_REQUEST_SENT_EVENT]
+
+ page_with_image = inline(f"<img src='{image_url}'>", domain=domain_1)
+
+ on_before_request_sent = wait_for_event(BEFORE_REQUEST_SENT_EVENT)
+ await bidi_session.browsing_context.navigate(
+ context=new_tab["context"], url=page_with_image, wait="complete"
+ )
+ await wait_for_future_safe(on_before_request_sent)
+
+ result = await bidi_session.storage.get_cookies(
+ partition=BrowsingContextPartitionDescriptor(new_tab["context"])
+ )
+
+ # Find the network event which belongs to the image.
+ event_for_image = next(
+ event for event in events if event["request"]["url"] == image_url
+ )
+ assert_cookies(result["cookies"], event_for_image["request"]["cookies"])
+
+ # Remove the coookie.
+ await bidi_session.storage.delete_cookies()
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/network/__init__.py
index 9bbc6f5daf..2e6376287b 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/network/__init__.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/network/__init__.py
@@ -6,6 +6,7 @@ from .. import (
any_list,
any_string,
any_string_or_null,
+ assert_cookies,
recursive_compare,
)
@@ -15,21 +16,6 @@ def assert_bytes_value(bytes_value):
any_string(bytes_value["value"])
-def assert_cookies(event_cookies, expected_cookies):
- assert len(event_cookies) == len(expected_cookies)
-
- # Simple helper to find a cookie by key and value only.
- def match_cookie(cookie, expected):
- for key in expected:
- if cookie[key] != expected[key]:
- return False
-
- return True
-
- for cookie in expected_cookies:
- assert next(c for c in event_cookies if match_cookie(c, cookie)) is not None
-
-
def assert_headers(event_headers, expected_headers):
# The browser sets request headers, only assert that the expected headers
# are included in the request's headers.
@@ -349,3 +335,9 @@ BEFORE_REQUEST_SENT_EVENT = "network.beforeRequestSent"
FETCH_ERROR_EVENT = "network.fetchError"
RESPONSE_COMPLETED_EVENT = "network.responseCompleted"
RESPONSE_STARTED_EVENT = "network.responseStarted"
+
+PHASE_TO_EVENT_MAP = {
+ "authRequired": [AUTH_REQUIRED_EVENT, assert_response_event],
+ "beforeRequestSent": [BEFORE_REQUEST_SENT_EVENT, assert_before_request_sent_event],
+ "responseStarted": [RESPONSE_STARTED_EVENT, assert_response_event],
+}
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/contexts.py b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/contexts.py
index 83dfa5560f..7606b2368b 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/contexts.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/contexts.py
@@ -5,15 +5,69 @@ from webdriver.bidi.modules.script import ScriptEvaluateResultException
from .. import (
assert_before_request_sent_event,
+ assert_response_event,
PAGE_EMPTY_HTML,
PAGE_EMPTY_TEXT,
BEFORE_REQUEST_SENT_EVENT,
RESPONSE_COMPLETED_EVENT,
RESPONSE_STARTED_EVENT,
+ PHASE_TO_EVENT_MAP,
)
@pytest.mark.asyncio
+@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
+@pytest.mark.parametrize("phase", ["beforeRequestSent", "responseStarted"])
+async def test_frame_context(
+ bidi_session,
+ url,
+ inline,
+ top_context,
+ add_intercept,
+ fetch,
+ setup_network_test,
+ wait_for_event,
+ wait_for_future_safe,
+ domain,
+ phase
+):
+ await setup_network_test(
+ events=[
+ BEFORE_REQUEST_SENT_EVENT,
+ RESPONSE_STARTED_EVENT,
+ RESPONSE_COMPLETED_EVENT,
+ ],
+ contexts=[top_context["context"]],
+ )
+
+ frame_url = inline("<div>foo</div>")
+ test_url = inline(f"<iframe src='{frame_url}'></iframe>", domain=domain)
+ await bidi_session.browsing_context.navigate(
+ url=test_url, context=top_context["context"], wait="complete"
+ )
+
+ # Retrieve the context for the iframe.
+ contexts = await bidi_session.browsing_context.get_tree(root=top_context["context"])
+ assert len(contexts[0]["children"]) == 1
+ frame = contexts[0]["children"][0]
+
+ # Add an intercept.
+ text_url = url(PAGE_EMPTY_TEXT)
+ await add_intercept(
+ phases=[phase],
+ url_patterns=[{"type": "string", "pattern": text_url}],
+ contexts=[top_context["context"]],
+ )
+
+ # Request in the iframe context should be blocked.
+ [event_name, assert_network_event] = PHASE_TO_EVENT_MAP[phase]
+ on_network_event = wait_for_event(event_name)
+ asyncio.ensure_future(fetch(text_url, context=frame))
+ event = await wait_for_future_safe(on_network_event)
+ assert_network_event(event, is_blocked=True)
+
+
+@pytest.mark.asyncio
@pytest.mark.parametrize("phase", ["beforeRequestSent", "responseStarted"])
async def test_other_context(
bidi_session,
@@ -22,7 +76,9 @@ async def test_other_context(
add_intercept,
fetch,
setup_network_test,
- phase,
+ wait_for_event,
+ wait_for_future_safe,
+ phase
):
# Subscribe to network events only in top_context
await setup_network_test(
@@ -47,13 +103,17 @@ async def test_other_context(
url_patterns=[{"type": "string", "pattern": text_url}],
)
- # Request to top_context should be blocked and throw a ScriptEvaluateResultException
- # from the AbortController.
- with pytest.raises(ScriptEvaluateResultException):
- await fetch(text_url, context=top_context)
- # Request to other_context should not be blocked.
- await fetch(text_url, context=other_context)
+ # Request to top_context should be blocked.
+ [event_name, assert_network_event] = PHASE_TO_EVENT_MAP[phase]
+ on_network_event = wait_for_event(event_name)
+ asyncio.ensure_future(fetch(text_url, context=top_context))
+ event = await wait_for_future_safe(on_network_event)
+ assert_network_event(event, is_blocked=True)
+
+ # Request to other_context should not be blocked because we are not
+ # subscribed to network events. Wait for fetch to resolve successfully.
+ await asyncio.ensure_future(fetch(text_url, context=other_context))
@pytest.mark.asyncio
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent.py b/testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent.py
index c92337e507..95a790e37c 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent.py
@@ -393,3 +393,26 @@ async def test_redirect_navigation(
# Check that both requests share the same requestId
assert events[0]["request"]["request"] == events[1]["request"]["request"]
+
+
+@pytest.mark.asyncio
+async def test_url_with_fragment(
+ url, wait_for_event, wait_for_future_safe, fetch, setup_network_test
+):
+ fragment_url = url(f"{PAGE_EMPTY_HTML}#foo")
+
+ network_events = await setup_network_test(events=[BEFORE_REQUEST_SENT_EVENT])
+ events = network_events[BEFORE_REQUEST_SENT_EVENT]
+
+ on_before_request_sent = wait_for_event(BEFORE_REQUEST_SENT_EVENT)
+ await fetch(fragment_url, method="GET")
+ await wait_for_future_safe(on_before_request_sent)
+
+ assert len(events) == 1
+
+ # Assert that the event contains the full fragment URL in requestData.
+ assert_before_request_sent_event(
+ events[0],
+ expected_request={"method": "GET", "url": fragment_url},
+ redirect_count=0,
+ )
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/conftest.py b/testing/web-platform/tests/webdriver/tests/bidi/network/conftest.py
index 7813530c4c..424fa8b5c7 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/network/conftest.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/network/conftest.py
@@ -1,13 +1,9 @@
-import json
-
import asyncio
-import pytest
import pytest_asyncio
from webdriver.bidi.error import NoSuchInterceptException
-from webdriver.bidi.modules.script import ContextTarget
-from . import PAGE_EMPTY_HTML, PAGE_EMPTY_TEXT, RESPONSE_COMPLETED_EVENT
+from . import PAGE_EMPTY_TEXT
@pytest_asyncio.fixture
@@ -40,102 +36,6 @@ async def add_intercept(bidi_session):
pass
-@pytest.fixture
-def fetch(bidi_session, top_context, configuration):
- """Perform a fetch from the page of the provided context, default to the
- top context.
- """
-
- async def fetch(
- url, method="GET", headers=None, context=top_context, timeout_in_seconds=3
- ):
- method_arg = f"method: '{method}',"
-
- headers_arg = ""
- if headers is not None:
- headers_arg = f"headers: {json.dumps(headers)},"
-
- timeout_in_seconds = timeout_in_seconds * configuration["timeout_multiplier"]
-
- # Wait for fetch() to resolve a response and for response.text() to
- # resolve as well to make sure the request/response is completed when
- # the helper returns.
- await bidi_session.script.evaluate(
- expression=f"""
- {{
- const controller = new AbortController();
- setTimeout(() => controller.abort(), {timeout_in_seconds * 1000});
- fetch("{url}", {{
- {method_arg}
- {headers_arg}
- signal: controller.signal
- }}).then(response => response.text());
- }}""",
- target=ContextTarget(context["context"]),
- await_promise=True,
- )
-
- return fetch
-
-
-@pytest_asyncio.fixture
-async def setup_network_test(
- bidi_session,
- subscribe_events,
- wait_for_event,
- wait_for_future_safe,
- top_context,
- url,
-):
- """Navigate the current top level context to the provided url and subscribe
- to network.beforeRequestSent.
-
- Returns an `events` dictionary in which the captured network events will be added.
- The keys of the dictionary are network event names (eg. "network.beforeRequestSent"),
- and the value is an array of collected events.
- """
- listeners = []
-
- async def _setup_network_test(events, test_url=url(PAGE_EMPTY_HTML), contexts=None):
- nonlocal listeners
-
- # Listen for network.responseCompleted for the initial navigation to
- # make sure this event will not be captured unexpectedly by the tests.
- await bidi_session.session.subscribe(
- events=[RESPONSE_COMPLETED_EVENT], contexts=[top_context["context"]]
- )
- on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
-
- await bidi_session.browsing_context.navigate(
- context=top_context["context"],
- url=test_url,
- wait="complete",
- )
- await wait_for_future_safe(on_response_completed)
- await bidi_session.session.unsubscribe(
- events=[RESPONSE_COMPLETED_EVENT], contexts=[top_context["context"]]
- )
-
- await subscribe_events(events, contexts)
-
- network_events = {}
- for event in events:
- network_events[event] = []
-
- async def on_event(method, data, event=event):
- network_events[event].append(data)
-
- listeners.append(bidi_session.add_event_listener(event, on_event))
-
- return network_events
-
- yield _setup_network_test
-
- # cleanup
- for remove_listener in listeners:
- remove_listener()
-
-
@pytest_asyncio.fixture
async def setup_blocked_request(
bidi_session,
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/provide_response/request.py b/testing/web-platform/tests/webdriver/tests/bidi/network/provide_response/request.py
index de9492f0a5..f8cc3fb676 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/network/provide_response/request.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/network/provide_response/request.py
@@ -11,7 +11,7 @@ pytestmark = pytest.mark.asyncio
@pytest.mark.parametrize("navigate", [False, True], ids=["fetch", "navigate"])
async def test_provide_response_auth_required(
- setup_blocked_request, subscribe_events, wait_for_event, bidi_session, navigate
+ setup_blocked_request, subscribe_events, wait_for_event, bidi_session, navigate, wait_for_future_safe
):
request = await setup_blocked_request("authRequired", navigate=navigate)
@@ -28,13 +28,13 @@ async def test_provide_response_auth_required(
await bidi_session.network.provide_response(request=request)
- await on_auth_required
+ await wait_for_future_safe(on_auth_required)
@pytest.mark.parametrize("phase", ["beforeRequestSent", "responseStarted"])
@pytest.mark.parametrize("navigate", [False, True], ids=["fetch", "navigate"])
async def test_provide_response_phase(
- setup_blocked_request, subscribe_events, wait_for_event, bidi_session, phase, navigate
+ setup_blocked_request, subscribe_events, wait_for_event, bidi_session, phase, navigate, wait_for_future_safe
):
request = await setup_blocked_request(phase, navigate=navigate)
@@ -58,10 +58,10 @@ async def test_provide_response_phase(
await bidi_session.network.provide_response(request=request)
- await on_response_completed
+ await wait_for_future_safe(on_response_completed)
if phase == "beforeRequestSent":
- await on_response_started
+ await wait_for_future_safe(on_response_started)
if navigate:
- await on_load
+ await wait_for_future_safe(on_load)
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed.py b/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed.py
index b9b4ae727e..56b9461642 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed.py
@@ -368,3 +368,28 @@ async def test_redirect_document(
# Check that the last 2 requests share the same request id
assert events[1]["request"]["request"] == events[2]["request"]["request"]
+
+
+@pytest.mark.asyncio
+async def test_url_with_fragment(
+ url, wait_for_event, wait_for_future_safe, fetch, setup_network_test
+):
+ fragment_url = url(f"{PAGE_EMPTY_HTML}#foo")
+
+ network_events = await setup_network_test(events=[RESPONSE_COMPLETED_EVENT])
+ events = network_events[RESPONSE_COMPLETED_EVENT]
+
+ on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
+ await fetch(fragment_url, method="GET")
+ await wait_for_future_safe(on_response_completed)
+
+ assert len(events) == 1
+
+ # Assert that the event contains the full fragment URL both in requestData
+ # and responseData
+ assert_response_event(
+ events[0],
+ expected_request={"method": "GET", "url": fragment_url},
+ expected_response={"url": fragment_url},
+ redirect_count=0,
+ )
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started.py b/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started.py
index fb99073fb3..6c10714ca8 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started.py
@@ -311,3 +311,28 @@ async def test_redirect(bidi_session, url, fetch, setup_network_test):
# Check that both requests share the same requestId
assert events[0]["request"]["request"] == events[1]["request"]["request"]
+
+
+@pytest.mark.asyncio
+async def test_url_with_fragment(
+ url, wait_for_event, wait_for_future_safe, fetch, setup_network_test
+):
+ fragment_url = url(f"{PAGE_EMPTY_HTML}#foo")
+
+ network_events = await setup_network_test(events=[RESPONSE_STARTED_EVENT])
+ events = network_events[RESPONSE_STARTED_EVENT]
+
+ on_response_started = wait_for_event(RESPONSE_STARTED_EVENT)
+ await fetch(fragment_url, method="GET")
+ await wait_for_future_safe(on_response_started)
+
+ assert len(events) == 1
+
+ # Assert that the event contains the full fragment URL both in requestData
+ # and responseData
+ assert_response_event(
+ events[0],
+ expected_request={"method": "GET", "url": fragment_url},
+ expected_response={"url": fragment_url},
+ redirect_count=0,
+ )
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/script/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/script/__init__.py
index 7feae91f27..4971737f8c 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/script/__init__.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/script/__init__.py
@@ -155,16 +155,16 @@ REMOTE_VALUES: list[tuple[str, dict]] = [
("new WeakSet()", {"type": "weakset", },),
("new Error('SOME_ERROR_TEXT')", {"type": "error"},),
("[1, 2][Symbol.iterator]()", {
- "type": "iterator",
+ "type": "object",
}),
("'mystring'[Symbol.iterator]()", {
- "type": "iterator",
+ "type": "object",
}),
("(new Set([1,2]))[Symbol.iterator]()", {
- "type": "iterator",
+ "type": "object",
}),
("(new Map([[1,2]]))[Symbol.iterator]()", {
- "type": "iterator",
+ "type": "object",
}),
("new Proxy({}, {})", {
"type": "proxy",
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/partition.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/partition.py
index 632e7ffa26..dbe882b8cf 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/partition.py
+++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/partition.py
@@ -159,7 +159,7 @@ async def test_partition_context_with_different_domain(
partition=BrowsingContextPartitionDescriptor(new_tab["context"])
)
- assert result["cookies"] == [
+ recursive_compare([
{
"domain": cookie_domain,
"httpOnly": False,
@@ -170,7 +170,7 @@ async def test_partition_context_with_different_domain(
"size": 6,
"value": {"type": "string", "value": cookie_value},
}
- ]
+ ], result["cookies"])
@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/support/black_dot.png b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/support/black_dot.png
new file mode 100644
index 0000000000..613754cfaf
--- /dev/null
+++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/support/black_dot.png
Binary files differ
diff --git a/testing/web-platform/tests/webdriver/tests/classic/element_click/interactability.py b/testing/web-platform/tests/webdriver/tests/classic/element_click/interactability.py
index d55860c874..65f8a9015e 100644
--- a/testing/web-platform/tests/webdriver/tests/classic/element_click/interactability.py
+++ b/testing/web-platform/tests/webdriver/tests/classic/element_click/interactability.py
@@ -42,8 +42,22 @@ def test_disabled(session, inline):
assert_success(response)
+@pytest.mark.parametrize("transform", ["translate(100px, 100px)", "rotate(50deg)"])
+def test_element_interactable_css_transform(session, inline, transform):
+ # The button is transformed within the viewport.
+ session.url = inline("""
+ <div style="width: 500px; height: 100px; position: absolute; left: 50px; top: 200px;
+ background-color: blue; transform: {transform};">
+ <input type=button>
+ </div>""".format(transform=transform))
+ element = session.find.css("input", all=False)
+ response = element_click(session, element)
+ assert_success(response)
+
+
@pytest.mark.parametrize("transform", ["translate(-100px, -100px)", "rotate(50deg)"])
def test_element_not_interactable_css_transform(session, inline, transform):
+ # The button is transformed outside of the viewport.
session.url = inline("""
<div style="width: 500px; height: 100px;
background-color: blue; transform: {transform};">
diff --git a/testing/web-platform/tests/webdriver/tests/classic/element_click/scroll_into_view.py b/testing/web-platform/tests/webdriver/tests/classic/element_click/scroll_into_view.py
index 591847e881..041f0dee6a 100644
--- a/testing/web-platform/tests/webdriver/tests/classic/element_click/scroll_into_view.py
+++ b/testing/web-platform/tests/webdriver/tests/classic/element_click/scroll_into_view.py
@@ -31,9 +31,9 @@ def test_scroll_into_view(session, inline):
assert session.execute_script("""
let input = arguments[0];
rect = input.getBoundingClientRect();
- return rect["top"] >= 0 && rect["left"] >= 0 &&
- (rect["top"] + rect["height"]) <= window.innerHeight &&
- (rect["left"] + rect["width"]) <= window.innerWidth;
+ return rect.top >= 0 && rect.left >= 0 &&
+ Math.floor(rect.bottom) <= window.innerHeight &&
+ Math.floor(rect.right) <= window.innerWidth;
""", args=(element,)) is True
@@ -69,4 +69,4 @@ def test_partially_visible_does_not_scroll(session, offset, inline):
assert_success(response)
assert session.execute_script("return window.scrollY || document.documentElement.scrollTop") == 0
click_point = assert_one_click(session)
- assert click_point == center_point(target)
+ assert click_point == pytest.approx(center_point(target), abs=1.0)
diff --git a/testing/web-platform/tests/webdriver/tests/classic/switch_to_parent_frame/switch.py b/testing/web-platform/tests/webdriver/tests/classic/switch_to_parent_frame/switch.py
index f777d6a767..184dc4234e 100644
--- a/testing/web-platform/tests/webdriver/tests/classic/switch_to_parent_frame/switch.py
+++ b/testing/web-platform/tests/webdriver/tests/classic/switch_to_parent_frame/switch.py
@@ -1,9 +1,8 @@
import pytest
-from webdriver import NoSuchElementException, NoSuchWindowException
+from webdriver import NoSuchElementException
from tests.support.asserts import assert_error, assert_success
-from tests.support.sync import Poll
def switch_to_parent_frame(session):
@@ -35,37 +34,6 @@ def test_no_top_browsing_context(session, url):
assert_error(response, "no such window")
-def test_no_parent_browsing_context(session, url):
- session.url = url("/webdriver/tests/support/html/frames.html")
-
- subframe = session.find.css("#sub-frame", all=False)
- session.switch_frame(subframe)
-
- deleteframe = session.find.css("#delete-frame", all=False)
- session.switch_frame(deleteframe)
-
- button = session.find.css("#remove-top", all=False)
- button.click()
-
- def is_window_closed(s):
- try:
- s.find.css("#remove-top", all=False)
- return False
- except NoSuchWindowException:
- return True
-
- # Wait until iframe is gone.
- wait = Poll(
- session,
- timeout=5,
- message="Iframe is still present",
- )
- wait.until(lambda s: is_window_closed(s))
-
- response = switch_to_parent_frame(session)
- assert_error(response, "no such window")
-
-
def test_no_browsing_context(session, closed_frame):
response = switch_to_parent_frame(session)
assert_success(response)
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/__init__.py b/testing/web-platform/tests/webdriver/tests/interop/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/__init__.py
+++ b/testing/web-platform/tests/webdriver/tests/interop/__init__.py
diff --git a/testing/web-platform/tests/webdriver/tests/interop/frames.py b/testing/web-platform/tests/webdriver/tests/interop/frames.py
new file mode 100644
index 0000000000..b2cafb4987
--- /dev/null
+++ b/testing/web-platform/tests/webdriver/tests/interop/frames.py
@@ -0,0 +1,37 @@
+import pytest
+from webdriver.error import NoSuchWindowException
+
+from tests.support.sync import AsyncPoll
+
+pytestmark = pytest.mark.asyncio
+
+
+async def test_classic_switch_to_parent_no_browsing_context(bidi_session, current_session, url):
+ # With WebDriver classic it cannot be checked if the parent frame is already
+ # gone before switching to it. To prevent race conditions such a check needs
+ # to be done via WebDriver BiDi.
+ current_session.url = url("/webdriver/tests/support/html/frames.html")
+
+ subframe = current_session.find.css("#sub-frame", all=False)
+ current_session.switch_frame(subframe)
+
+ deleteframe = current_session.find.css("#delete-frame", all=False)
+ current_session.switch_frame(deleteframe)
+
+ button = current_session.find.css("#remove-top", all=False)
+ button.click()
+
+ async def is_frame_removed(_):
+ contexts = await bidi_session.browsing_context.get_tree(root=current_session.window_handle)
+ return not contexts[0]["children"]
+
+ # Wait until IFrame is gone.
+ wait = AsyncPoll(
+ current_session,
+ timeout=5,
+ message="IFrame that should be closed is still open",
+ )
+ await wait.until(is_frame_removed)
+
+ with pytest.raises(NoSuchWindowException):
+ current_session.switch_frame("parent")
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/node_shared_id.py b/testing/web-platform/tests/webdriver/tests/interop/shared_id_node.py
index aeb2bc4597..aeb2bc4597 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/node_shared_id.py
+++ b/testing/web-platform/tests/webdriver/tests/interop/shared_id_node.py
diff --git a/testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/window_reference.py b/testing/web-platform/tests/webdriver/tests/interop/shared_id_window.py
index 1588303be0..d13262b4e5 100644
--- a/testing/web-platform/tests/webdriver/tests/bidi/script/classic_interop/window_reference.py
+++ b/testing/web-platform/tests/webdriver/tests/interop/shared_id_window.py
@@ -6,6 +6,10 @@ from webdriver.bidi.modules.script import ContextTarget
pytestmark = pytest.mark.asyncio
+async def test_top_level_context_id_equals_window_handle(top_context, current_session):
+ assert top_context["context"] == current_session.window_handle
+
+
async def test_web_window_reference_created_in_classic(
bidi_session,
current_session,
diff --git a/testing/web-platform/tests/webdriver/tests/support/fixtures_bidi.py b/testing/web-platform/tests/webdriver/tests/support/fixtures_bidi.py
index 7f3e4f9a9a..32919210bf 100644
--- a/testing/web-platform/tests/webdriver/tests/support/fixtures_bidi.py
+++ b/testing/web-platform/tests/webdriver/tests/support/fixtures_bidi.py
@@ -1,15 +1,16 @@
-import base64
-
-from tests.support.asserts import assert_pdf
-from tests.support.image import cm_to_px, png_dimensions, ImageDifference
-from typing import Any, Coroutine, Mapping
-
import asyncio
+import base64
import copy
+import json
+import time
from datetime import datetime, timedelta
+from typing import Any, Coroutine, Mapping
+
import pytest
import pytest_asyncio
-import time
+
+from tests.support.asserts import assert_pdf
+from tests.support.image import cm_to_px, png_dimensions, ImageDifference
from webdriver.bidi.error import (
InvalidArgumentException,
NoSuchFrameException,
@@ -528,3 +529,98 @@ def domain_value(server_config):
return server_config["domains"][domain][subdomain]
return domain_value
+
+
+@pytest.fixture
+def fetch(bidi_session, top_context, configuration):
+ """Perform a fetch from the page of the provided context, default to the
+ top context.
+ """
+
+ async def fetch(
+ url, method="GET", headers=None, context=top_context, timeout_in_seconds=3
+ ):
+ method_arg = f"method: '{method}',"
+
+ headers_arg = ""
+ if headers is not None:
+ headers_arg = f"headers: {json.dumps(headers)},"
+
+ timeout_in_seconds = timeout_in_seconds * configuration["timeout_multiplier"]
+ # Wait for fetch() to resolve a response and for response.text() to
+ # resolve as well to make sure the request/response is completed when
+ # the helper returns.
+ await bidi_session.script.evaluate(
+ expression=f"""
+ {{
+ const controller = new AbortController();
+ setTimeout(() => controller.abort(), {timeout_in_seconds * 1000});
+ fetch("{url}", {{
+ {method_arg}
+ {headers_arg}
+ signal: controller.signal,
+ }}).then(response => response.text());
+ }}""",
+ target=ContextTarget(context["context"]),
+ await_promise=True,
+ )
+
+ return fetch
+
+
+@pytest_asyncio.fixture
+async def setup_network_test(
+ bidi_session,
+ subscribe_events,
+ wait_for_event,
+ wait_for_future_safe,
+ top_context,
+ url,
+):
+ """Navigate the current top level context to the provided url and subscribe
+ to network.beforeRequestSent.
+
+ Returns an `events` dictionary in which the captured network events will be added.
+ The keys of the dictionary are network event names (eg. "network.beforeRequestSent"),
+ and the value is an array of collected events.
+ """
+ listeners = []
+
+ async def _setup_network_test(events, test_url=url("/webdriver/tests/bidi/network/support/empty.html"), contexts=None):
+ nonlocal listeners
+
+ # Listen for network.responseCompleted for the initial navigation to
+ # make sure this event will not be captured unexpectedly by the tests.
+ await bidi_session.session.subscribe(
+ events=["network.responseCompleted"], contexts=[top_context["context"]]
+ )
+ on_response_completed = wait_for_event("network.responseCompleted")
+
+ await bidi_session.browsing_context.navigate(
+ context=top_context["context"],
+ url=test_url,
+ wait="complete",
+ )
+ await wait_for_future_safe(on_response_completed)
+ await bidi_session.session.unsubscribe(
+ events=["network.responseCompleted"], contexts=[top_context["context"]]
+ )
+
+ await subscribe_events(events, contexts)
+
+ network_events = {}
+ for event in events:
+ network_events[event] = []
+
+ async def on_event(method, data, event=event):
+ network_events[event].append(data)
+
+ listeners.append(bidi_session.add_event_listener(event, on_event))
+
+ return network_events
+
+ yield _setup_network_test
+
+ # cleanup
+ for remove_listener in listeners:
+ remove_listener()
diff --git a/testing/web-platform/tests/webdriver/tests/support/inline.py b/testing/web-platform/tests/webdriver/tests/support/inline.py
index ecb2a2587b..8364e0590e 100644
--- a/testing/web-platform/tests/webdriver/tests/support/inline.py
+++ b/testing/web-platform/tests/webdriver/tests/support/inline.py
@@ -6,6 +6,7 @@ from urllib.parse import urlencode
BOILERPLATES = {
"html": "<!doctype html>\n<meta charset={charset}>\n{src}",
+ "html_quirks": "{src}",
"xhtml": """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
@@ -22,6 +23,7 @@ BOILERPLATES = {
}
MIME_TYPES = {
"html": "text/html",
+ "html_quirks": "text/html",
"xhtml": "application/xhtml+xml",
"xml": "text/xml",
"js": "text/javascript",