From 086c044dc34dfc0f74fbe41f4ecb402b2cd34884 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:13:33 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- .../tests/bidi/browsing_context/__init__.py | 7 + .../bidi/browsing_context/activate/__init__.py | 3 +- .../bidi/browsing_context/activate/activate.py | 95 ++-- .../context_created/context_created.py | 50 ++ .../tests/bidi/browsing_context/create/type.py | 16 +- .../fragment_navigated/fragment_navigated.py | 2 +- .../bidi/browsing_context/locate_nodes/invalid.py | 35 -- .../browsing_context/locate_nodes/ownership.py | 26 -- .../bidi/browsing_context/locate_nodes/sandbox.py | 111 ----- .../external/permissions/set_permission/invalid.py | 2 +- .../permissions/set_permission/set_permission.py | 17 +- .../tests/bidi/input/perform_actions/invalid.py | 12 +- .../tests/bidi/input/set_files/__init__.py | 0 .../tests/bidi/input/set_files/conftest.py | 33 ++ .../tests/bidi/input/set_files/context.py | 80 ++++ .../webdriver/tests/bidi/input/set_files/files.py | 352 ++++++++++++++ .../tests/bidi/input/set_files/invalid.py | 232 ++++++++++ .../webdriver/tests/bidi/integration/navigation.py | 67 +++ .../bidi/network/add_intercept/add_intercept.py | 43 -- .../tests/bidi/network/add_intercept/contexts.py | 210 +++++++++ .../tests/bidi/network/add_intercept/invalid.py | 36 +- .../network/add_intercept/phase_auth_required.py | 19 +- .../bidi/network/add_intercept/url_patterns.py | 24 +- .../bidi/network/auth_required/auth_required.py | 24 +- .../bidi/network/auth_required/unsubscribe.py | 31 +- .../before_request_sent_cached.py | 123 +++++ .../tests/webdriver/tests/bidi/network/conftest.py | 11 +- .../bidi/network/continue_response/credentials.py | 26 +- .../bidi/network/continue_response/request.py | 16 +- .../bidi/network/continue_with_auth/action.py | 13 +- .../response_completed_cached.py | 72 +++ .../network/response_started/response_started.py | 12 +- .../response_started/response_started_cached.py | 74 +++ .../script/call_function/serialization_options.py | 28 +- .../webdriver/tests/bidi/session/new/connect.py | 9 +- .../webdriver/tests/bidi/session/status/status.py | 4 +- .../tests/bidi/session/subscribe/invalid.py | 81 ++-- .../tests/bidi/session/unsubscribe/invalid.py | 111 ++--- .../tests/webdriver/tests/bidi/storage/__init__.py | 10 +- .../tests/bidi/storage/delete_cookies/__init__.py | 3 + .../tests/bidi/storage/delete_cookies/filter.py | 514 +++++++++++++++++++++ .../tests/bidi/storage/delete_cookies/invalid.py | 163 +++++++ .../tests/bidi/storage/delete_cookies/partition.py | 308 ++++++++++++ .../tests/bidi/storage/get_cookies/filter.py | 30 +- .../tests/bidi/storage/get_cookies/invalid.py | 7 + .../tests/bidi/storage/get_cookies/partition.py | 168 ++++++- .../tests/bidi/storage/set_cookie/cookie_expiry.py | 8 +- .../bidi/storage/set_cookie/cookie_http_only.py | 4 +- .../tests/bidi/storage/set_cookie/cookie_path.py | 4 +- .../bidi/storage/set_cookie/cookie_same_site.py | 4 +- .../tests/bidi/storage/set_cookie/cookie_secure.py | 4 +- .../tests/bidi/storage/set_cookie/invalid.py | 8 +- .../bidi/storage/set_cookie/page_protocols.py | 4 +- .../tests/bidi/storage/set_cookie/partition.py | 52 ++- .../tests/classic/new_session/response.py | 7 + .../webdriver/tests/classic/new_window/new_tab.py | 26 +- .../tests/classic/new_window/new_window.py | 26 +- .../tests/webdriver/tests/support/fixtures_bidi.py | 4 +- .../tests/webdriver/tests/support/html/files.html | 28 ++ .../tests/support/http_handlers/cached.py | 9 +- 60 files changed, 2911 insertions(+), 587 deletions(-) delete mode 100644 testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/ownership.py delete mode 100644 testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/sandbox.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/input/set_files/__init__.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/input/set_files/conftest.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/input/set_files/context.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/input/set_files/files.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/input/set_files/invalid.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/integration/navigation.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/contexts.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent_cached.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/__init__.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/filter.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/invalid.py create mode 100644 testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/partition.py create mode 100644 testing/web-platform/tests/webdriver/tests/support/html/files.html (limited to 'testing/web-platform/tests/webdriver') diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/__init__.py index dbacac8cf8..51b3c64b42 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/__init__.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/__init__.py @@ -53,6 +53,13 @@ def assert_browsing_context( assert info["userContext"] == user_context +async def assert_document_status(bidi_session, context, visible, focused): + state = "visible" if visible else "hidden" + + assert await get_visibility_state(bidi_session, context) == state + assert await get_document_focus(bidi_session, context) is focused + + def assert_navigation_info(event, expected_navigation_info): recursive_compare( { diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/__init__.py index 5d0b52a5ac..86f9ace3ee 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/__init__.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/__init__.py @@ -3,7 +3,7 @@ from typing import Any, Mapping from webdriver.bidi.modules.script import ContextTarget -async def is_selector_focused(bidi_session, context: Mapping[str, Any], selector: str) -> bool: +async def is_element_focused(bidi_session, context: Mapping[str, Any], selector: str) -> bool: result = await bidi_session.script.call_function( function_declaration="""(selector) => { return document.querySelector(selector) === document.activeElement; @@ -13,4 +13,5 @@ async def is_selector_focused(bidi_session, context: Mapping[str, Any], selector ], target=ContextTarget(context["context"]), await_promise=False) + return result["value"] diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/activate.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/activate.py index 0abbbbac38..f6e5b9d27a 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/activate.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/activate/activate.py @@ -1,95 +1,62 @@ import pytest from webdriver.bidi.modules.script import ContextTarget -from . import is_selector_focused -from .. import get_document_focus, get_visibility_state +from . import is_element_focused +from .. import assert_document_status pytestmark = pytest.mark.asyncio -async def test_activate(bidi_session, new_tab, top_context): - assert await get_document_focus(bidi_session, top_context) is False - - await bidi_session.browsing_context.activate(context=top_context["context"]) - - assert await get_visibility_state(bidi_session, top_context) == 'visible' - assert await get_document_focus(bidi_session, top_context) is True +@pytest.mark.parametrize("type_hint", ["tab", "window"]) +async def test_switch_between_contexts(bidi_session, top_context, type_hint): + is_window = type_hint == "window" + new_context = await bidi_session.browsing_context.create(type_hint=type_hint) -async def test_deactivates_other_contexts(bidi_session, new_tab, top_context): await bidi_session.browsing_context.activate(context=top_context["context"]) + await assert_document_status(bidi_session, top_context, visible=True, focused=True) + await assert_document_status(bidi_session, new_context, visible=is_window, focused=False) - assert await get_visibility_state(bidi_session, top_context) == 'visible' - assert await get_document_focus(bidi_session, top_context) is True + await bidi_session.browsing_context.activate(context=new_context["context"]) + await assert_document_status(bidi_session, top_context, visible=is_window, focused=False) + await assert_document_status(bidi_session, new_context, visible=True, focused=True) - assert await get_document_focus(bidi_session, new_tab) is False - - await bidi_session.browsing_context.activate(context=new_tab["context"]) - assert await get_document_focus(bidi_session, top_context) is False - - assert await get_visibility_state(bidi_session, new_tab) == 'visible' - assert await get_document_focus(bidi_session, new_tab) is True - - -async def test_keeps_focused_area(bidi_session, inline, new_tab, top_context): - await bidi_session.browsing_context.activate(context=new_tab["context"]) - assert await get_visibility_state(bidi_session, new_tab) == 'visible' - assert await get_document_focus(bidi_session, new_tab) is True - - await bidi_session.browsing_context.navigate(context=new_tab["context"], - url=inline(""), - wait="complete") +async def test_keeps_element_focused(bidi_session, inline, new_tab, top_context): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=inline(""), + wait="complete") await bidi_session.script.evaluate( expression="""document.querySelector("input").focus()""", target=ContextTarget(new_tab["context"]), await_promise=False) - assert await is_selector_focused(bidi_session, new_tab, "input") + assert await is_element_focused(bidi_session, new_tab, "input") await bidi_session.browsing_context.activate(context=top_context["context"]) - assert await get_document_focus(bidi_session, new_tab) is False - assert await is_selector_focused(bidi_session, new_tab, "input") + assert await is_element_focused(bidi_session, new_tab, "input") await bidi_session.browsing_context.activate(context=new_tab["context"]) - assert await get_visibility_state(bidi_session, new_tab) == 'visible' - assert await get_document_focus(bidi_session, new_tab) is True - assert await is_selector_focused(bidi_session, new_tab, "input") + assert await is_element_focused(bidi_session, new_tab, "input") -async def test_double_activation(bidi_session, inline, new_tab): - await bidi_session.browsing_context.activate(context=new_tab["context"]) - assert await get_visibility_state(bidi_session, new_tab) == 'visible' - assert await get_document_focus(bidi_session, new_tab) is True +async def test_multiple_activation(bidi_session, inline, new_tab): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=inline( + ""), + wait="complete") - await bidi_session.browsing_context.navigate(context=new_tab["context"], - url=inline(""), - wait="complete") - assert await is_selector_focused(bidi_session, new_tab, "input") + await assert_document_status(bidi_session, new_tab, visible=True, focused=True) + assert await is_element_focused(bidi_session, new_tab, "input") await bidi_session.browsing_context.activate(context=new_tab["context"]) - assert await get_visibility_state(bidi_session, new_tab) == 'visible' - assert await get_document_focus(bidi_session, new_tab) is True - assert await is_selector_focused(bidi_session, new_tab, "input") + await assert_document_status(bidi_session, new_tab, visible=True, focused=True) + assert await is_element_focused(bidi_session, new_tab, "input") # Activate again. await bidi_session.browsing_context.activate(context=new_tab["context"]) - assert await get_visibility_state(bidi_session, new_tab) == 'visible' - assert await get_document_focus(bidi_session, new_tab) is True - assert await is_selector_focused(bidi_session, new_tab, "input") - - -async def test_activate_window(bidi_session): - new_window_1 = await bidi_session.browsing_context.create(type_hint="window") - new_window_2 = await bidi_session.browsing_context.create(type_hint="window") - - assert await get_visibility_state(bidi_session, new_window_2) == 'visible' - assert await get_document_focus(bidi_session, new_window_2) is True - - assert await get_document_focus(bidi_session, new_window_1) is False - - await bidi_session.browsing_context.activate(context=new_window_1["context"]) - - assert await get_visibility_state(bidi_session, new_window_1) == 'visible' - assert await get_document_focus(bidi_session, new_window_1) is True + await assert_document_status(bidi_session, new_tab, visible=True, focused=True) + assert await is_element_focused(bidi_session, new_tab, "input") diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/context_created/context_created.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/context_created/context_created.py index 464d83a8aa..b865a891ed 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/context_created/context_created.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/context_created/context_created.py @@ -92,6 +92,37 @@ async def test_evaluate_window_open_with_url(bidi_session, subscribe_events, wai ) +@pytest.mark.parametrize("type_hint", ["tab", "window"]) +async def test_event_emitted_before_create_returns( + bidi_session, subscribe_events, type_hint +): + events = [] + + async def on_event(method, data): + events.append(data) + + remove_listener = bidi_session.add_event_listener(CONTEXT_CREATED_EVENT, on_event) + + await subscribe_events([CONTEXT_CREATED_EVENT]) + context = await bidi_session.browsing_context.create(type_hint=type_hint) + + # If the browsingContext.contextCreated event was emitted after the + # browsingContext.create command resolved, the array would most likely be + # empty at this point. + assert len(events) == 1 + + assert_browsing_context( + events[0], + context["context"], + children=None, + url="about:blank", + parent=None, + user_context="default", + ) + + remove_listener() + + async def test_navigate_creates_iframes(bidi_session, subscribe_events, top_context, test_page_multiple_frames): events = [] @@ -263,3 +294,22 @@ async def test_new_user_context( ) remove_listener() + + +@pytest.mark.parametrize("type_hint", ["tab", "window"]) +async def test_existing_context(bidi_session, wait_for_event, wait_for_future_safe, subscribe_events, type_hint): + # See https://w3c.github.io/webdriver-bidi/#ref-for-remote-end-subscribe-steps%E2%91%A1. + top_level_context = await bidi_session.browsing_context.create(type_hint=type_hint) + + on_entry = wait_for_event(CONTEXT_CREATED_EVENT) + await subscribe_events([CONTEXT_CREATED_EVENT], contexts=[top_level_context["context"]]) + context_info = await wait_for_future_safe(on_entry) + + assert_browsing_context( + context_info, + top_level_context["context"], + children=None, + url="about:blank", + parent=None, + user_context="default" + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/create/type.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/create/type.py index 55ce7b4428..cc6d7e51ab 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/create/type.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/create/type.py @@ -1,19 +1,27 @@ import pytest -from .. import assert_browsing_context from webdriver.bidi.modules.script import ContextTarget +from .. import assert_browsing_context, assert_document_status + pytestmark = pytest.mark.asyncio -@pytest.mark.parametrize("value", ["tab", "window"]) -async def test_type(bidi_session, value): +@pytest.mark.parametrize("type_hint", ["tab", "window"]) +async def test_type(bidi_session, top_context, type_hint): + is_window = type_hint == "window" + contexts = await bidi_session.browsing_context.get_tree(max_depth=0) assert len(contexts) == 1 - new_context = await bidi_session.browsing_context.create(type_hint=value) + await assert_document_status(bidi_session, top_context, visible=True, focused=True) + + new_context = await bidi_session.browsing_context.create(type_hint=type_hint) assert contexts[0]["context"] != new_context["context"] + await assert_document_status(bidi_session, new_context, visible=True, focused=True) + await assert_document_status(bidi_session, top_context, visible=is_window, focused=False) + # Check there is an additional browsing context contexts = await bidi_session.browsing_context.get_tree(max_depth=0) assert len(contexts) == 2 diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/fragment_navigated/fragment_navigated.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/fragment_navigated/fragment_navigated.py index a4bd012588..fb690807f2 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/fragment_navigated/fragment_navigated.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/fragment_navigated/fragment_navigated.py @@ -57,7 +57,7 @@ async def test_subscribe(bidi_session, subscribe_events, url, new_tab, wait_for_ assert_navigation_info(event, {"context": new_tab["context"], "url": target_url}) -async def test_timestamp(bidi_session, current_time, subscribe_events, url, new_tab, wait_for_event): +async def test_timestamp(bidi_session, current_time, subscribe_events, url, new_tab, wait_for_event, wait_for_future_safe): await bidi_session.browsing_context.navigate( context=new_tab["context"], url=url(EMPTY_PAGE), wait="complete" ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/invalid.py index ff00de91ed..ecd3173e87 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/invalid.py @@ -93,41 +93,6 @@ async def test_params_max_node_count_invalid_value(bidi_session, inline, top_con ) -@pytest.mark.parametrize("value", [False, 42, {}, []]) -async def test_params_ownership_invalid_type(bidi_session, inline, top_context, value): - await navigate_to_page(bidi_session, inline, top_context) - - with pytest.raises(error.InvalidArgumentException): - await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div" }, - ownership=value - ) - - -async def test_params_ownership_invalid_value(bidi_session, inline, top_context): - await navigate_to_page(bidi_session, inline, top_context) - - with pytest.raises(error.InvalidArgumentException): - await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div" }, - ownership="foo" - ) - - -@pytest.mark.parametrize("value", [False, 42, {}, []]) -async def test_params_sandbox_invalid_type(bidi_session, inline, top_context, value): - await navigate_to_page(bidi_session, inline, top_context) - - with pytest.raises(error.InvalidArgumentException): - await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div" }, - sandbox=value - ) - - @pytest.mark.parametrize("value", [False, 42, "foo", []]) async def test_params_serialization_options_invalid_type(bidi_session, inline, top_context, value): await navigate_to_page(bidi_session, inline, top_context) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/ownership.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/ownership.py deleted file mode 100644 index b1830c740a..0000000000 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/ownership.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest - -from ... import assert_handle - - -@pytest.mark.parametrize("ownership,has_handle", [ - ("root", True), - ("none", False) -]) -@pytest.mark.asyncio -async def test_root_ownership_of_located_nodes(bidi_session, inline, top_context, ownership, has_handle): - url = inline("""
foobarBARbaz
foobarBARbaz
""") - await bidi_session.browsing_context.navigate( - context=top_context["context"], url=url, wait="complete" - ) - - result = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" }, - ownership=ownership - ) - - assert len(result["nodes"]) == 1 - result_node = result["nodes"][0] - - assert_handle(result_node, has_handle) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/sandbox.py b/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/sandbox.py deleted file mode 100644 index efa431bf19..0000000000 --- a/testing/web-platform/tests/webdriver/tests/bidi/browsing_context/locate_nodes/sandbox.py +++ /dev/null @@ -1,111 +0,0 @@ -import pytest - -from webdriver.bidi.modules.script import ContextTarget,OwnershipModel - - -@pytest.mark.asyncio -async def test_locate_nodes_in_sandbox(bidi_session, inline, top_context): - url = inline("""
foobarBARbaz
foobarBARbaz
""") - await bidi_session.browsing_context.navigate( - context=top_context["context"], url=url, wait="complete" - ) - - result = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" }, - sandbox="sandbox" - ) - - assert len(result["nodes"]) == 1 - node_id = result["nodes"][0]["sharedId"] - - # Since the node was found in the sandbox, it should be available - # to scripts running in the sandbox. - result_in_sandbox = await bidi_session.script.call_function( - function_declaration="function(){ return arguments[0]; }", - target=ContextTarget(top_context["context"], "sandbox"), - await_promise=True, - arguments=[ - { - "sharedId": node_id - } - ] - ) - assert result_in_sandbox["type"] == "node" - assert result_in_sandbox["sharedId"] == node_id - - -@pytest.mark.asyncio -async def test_locate_same_node_in_different_sandboxes_returns_same_id(bidi_session, inline, top_context): - url = inline("""
foobarBARbaz
foobarBARbaz
""") - await bidi_session.browsing_context.navigate( - context=top_context["context"], url=url, wait="complete" - ) - - first_result = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" }, - sandbox="first_sandbox" - ) - - assert len(first_result["nodes"]) == 1 - - second_result = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" }, - sandbox="second_sandbox" - ) - assert len(second_result["nodes"]) == 1 - assert first_result["nodes"][0]["sharedId"] == second_result["nodes"][0]["sharedId"] - - -@pytest.mark.asyncio -async def test_locate_same_node_in_default_sandbox_returns_same_id_as_sandbox(bidi_session, inline, top_context): - url = inline("""
foobarBARbaz
foobarBARbaz
""") - await bidi_session.browsing_context.navigate( - context=top_context["context"], url=url, wait="complete" - ) - - result = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" } - ) - - assert len(result["nodes"]) == 1 - node_id = result["nodes"][0]["sharedId"] - - result_in_sandbox = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" }, - sandbox="sandbox" - ) - assert len(result_in_sandbox["nodes"]) == 1 - assert result_in_sandbox["nodes"][0]["sharedId"] == node_id - - -@pytest.mark.asyncio -async def test_locate_same_node_in_different_sandboxes_with_root_ownership_returns_different_handles(bidi_session, inline, top_context): - url = inline("""
foobarBARbaz
foobarBARbaz
""") - await bidi_session.browsing_context.navigate( - context=top_context["context"], url=url, wait="complete" - ) - - first_result = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" }, - ownership=OwnershipModel.ROOT.value, - sandbox="first_sandbox" - ) - - assert len(first_result["nodes"]) == 1 - - second_result = await bidi_session.browsing_context.locate_nodes( - context=top_context["context"], - locator={ "type": "css", "value": "div[data-class='one']" }, - ownership=OwnershipModel.ROOT.value, - sandbox="second_sandbox" - ) - - assert len(second_result["nodes"]) == 1 - assert first_result["nodes"][0]["sharedId"] == second_result["nodes"][0]["sharedId"] - assert first_result["nodes"][0]["handle"] != second_result["nodes"][0]["handle"] 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 0ef8c57f41..0ace04e8bc 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 @@ -34,7 +34,7 @@ async def test_params_state_invalid_type(bidi_session, state): ) -@pytest.mark.parametrize("state", ["UNKOWN", "Granted"]) +@pytest.mark.parametrize("state", ["UNKNOWN", "Granted"]) async def test_params_state_invalid_value(bidi_session, state): with pytest.raises(error.InvalidArgumentException): await bidi_session.permissions.set_permission( 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 dc6ca14a8d..92ebed1e63 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 @@ -96,7 +96,22 @@ async def test_set_permission_new_context(bidi_session, new_tab, url): @pytest.mark.parametrize("origin", ['UNKNOWN', '']) -async def test_set_permission_origin_unknown(bidi_session, new_tab, origin): +async def test_set_permission_origin_unknown(bidi_session, new_tab, origin, url): + test_url = url("/common/blank.html", protocol="https") + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=test_url, + wait="complete", + ) + + # Ensure permission for the tab is prompt. + tab_origin = await get_context_origin(bidi_session, new_tab) + await bidi_session.permissions.set_permission( + descriptor={"name": "geolocation"}, + state="prompt", + origin=tab_origin, + ) + await bidi_session.permissions.set_permission( descriptor={"name": "geolocation"}, state="granted", diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/invalid.py index 4ae3039f47..1c5983159c 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/invalid.py @@ -531,7 +531,7 @@ async def test_params_pointer_action_up_down_button_invalid_value( @pytest.mark.parametrize("pointer_action", - ["pointerDown", "pointerMove", "pointerUp"]) + ["pointerDown", "pointerMove"]) @pytest.mark.parametrize("dimension", ["width", "height"]) @pytest.mark.parametrize("value", [None, "foo", True, 0.1, [], {}]) async def test_params_pointer_action_common_properties_dimensions_invalid_type( @@ -554,7 +554,7 @@ async def test_params_pointer_action_common_properties_dimensions_invalid_type( @pytest.mark.parametrize("dimension", ["width", "height"]) @pytest.mark.parametrize("pointer_action", - ["pointerDown", "pointerMove", "pointerUp"]) + ["pointerDown", "pointerMove"]) @pytest.mark.parametrize("value", [-1, MAX_INT + 1]) async def test_params_pointer_action_common_properties_dimensions_invalid_value( perform_actions, dimension, pointer_action, value): @@ -575,7 +575,7 @@ async def test_params_pointer_action_common_properties_dimensions_invalid_value( @pytest.mark.parametrize("pointer_action", - ["pointerDown", "pointerMove", "pointerUp"]) + ["pointerDown", "pointerMove"]) @pytest.mark.parametrize("pressure", ["pressure", "tangentialPressure"]) @pytest.mark.parametrize("value", [None, "foo", True, [], {}]) async def test_params_pointer_action_common_properties_pressure_invalid_type( @@ -599,7 +599,7 @@ async def test_params_pointer_action_common_properties_pressure_invalid_type( @pytest.mark.parametrize("pointer_action", - ["pointerDown", "pointerMove", "pointerUp"]) + ["pointerDown", "pointerMove"]) @pytest.mark.parametrize("value", [None, "foo", True, 0.1, [], {}]) async def test_params_pointer_action_common_properties_twist_invalid_type( perform_actions, pointer_action, value): @@ -614,7 +614,7 @@ async def test_params_pointer_action_common_properties_twist_invalid_type( @pytest.mark.parametrize("pointer_action", - ["pointerDown", "pointerMove", "pointerUp"]) + ["pointerDown", "pointerMove"]) @pytest.mark.parametrize("value", [-1, 360]) async def test_params_pointer_action_common_properties_twist_invalid_value( perform_actions, pointer_action, value): @@ -629,7 +629,7 @@ async def test_params_pointer_action_common_properties_twist_invalid_value( @pytest.mark.parametrize("pointer_action", - ["pointerDown", "pointerMove", "pointerUp"]) + ["pointerDown", "pointerMove"]) @pytest.mark.parametrize("angle", ["altitudeAngle", "azimuthAngle"]) @pytest.mark.parametrize("value", [None, "foo", True, [], {}]) async def test_params_pointer_action_common_properties_angle_invalid_type( diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/conftest.py b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/conftest.py new file mode 100644 index 0000000000..f114ca701e --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/conftest.py @@ -0,0 +1,33 @@ +import os +import pytest + + +@pytest.fixture +def create_files(tmpdir_factory): + def create_files(paths): + """Create files in a temporary folder. + + Note: the fixture doesn't work with absolute paths, since all the files + should be created inside the temporary folder. + + :param paths: list of file names which should be used for creating files + :return: list of final paths for created files + """ + + filelist = [] + tmpdir = tmpdir_factory.mktemp("wdspec-") + + for path in paths: + # Make path separators system compatible. + path = os.path.join(*path.split("/")) + dir_path = os.path.join(tmpdir, os.path.dirname(path)) + if not os.path.exists(dir_path): + os.makedirs(dir_path) + + full_path = os.path.join(tmpdir, path) + open(full_path, 'w').close() + filelist.append(full_path) + + return filelist + + return create_files diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/context.py b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/context.py new file mode 100644 index 0000000000..f9a39f2bfb --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/context.py @@ -0,0 +1,80 @@ +import pytest + +from .. import get_events + +pytestmark = pytest.mark.asyncio + + +async def test_set_files_сontext( + bidi_session, top_context, new_tab, load_static_test_page, get_element, create_files +): + await load_static_test_page(page="files.html") + await load_static_test_page(page="files.html", context=new_tab) + + element = await get_element("#input", context=new_tab) + + await bidi_session.input.set_files( + context=new_tab["context"], + element=element, + files=create_files(["noop.txt"]), + ) + + events_in_new_tab = await get_events(bidi_session, new_tab["context"]) + assert events_in_new_tab == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + ] + + # Make sure that events are not sent in the other context. + events_in_top_context = await get_events(bidi_session, top_context["context"]) + assert events_in_top_context == [] + + +@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"]) +async def test_set_files_in_iframe( + bidi_session, new_tab, get_element, inline, url, create_files, domain +): + iframe_url = url("/webdriver/tests/support/html/files.html") + page_url = inline(f"", domain=domain) + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=page_url, + wait="complete", + ) + + contexts = await bidi_session.browsing_context.get_tree(root=new_tab["context"]) + iframe_context = contexts[0]["children"][0] + + element = await get_element("#input", context=iframe_context) + + await bidi_session.input.set_files( + context=iframe_context["context"], + element=element, + files=create_files(["noop.txt"]), + ) + + events_in_new_tab = await get_events(bidi_session, iframe_context["context"]) + assert events_in_new_tab == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + ] diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/files.py b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/files.py new file mode 100644 index 0000000000..7a31f3e14a --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/files.py @@ -0,0 +1,352 @@ +import pytest + +from .. import get_events + +pytestmark = pytest.mark.asyncio + + +async def test_set_files( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + ] + + +async def test_set_files_empty( + bidi_session, + top_context, + load_static_test_page, + get_element, +): + await load_static_test_page(page="files.html") + + element = await get_element("#input") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=[], + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [], + "type": "cancel", + }, + ] + + +async def test_set_files_multiple( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input-multiple") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt", "path/to/noop-2.txt"]), + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [ + "noop.txt", + "noop-2.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + "noop-2.txt", + ], + "type": "change", + }, + ] + + +async def test_set_files_something_then_empty( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=[], + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + { + "files": [], + "type": "input", + }, + { + "files": [], + "type": "change", + }, + ] + + +async def test_set_files_twice( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop-2.txt"]), + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + { + "files": [ + "noop-2.txt", + ], + "type": "input", + }, + { + "files": [ + "noop-2.txt", + ], + "type": "change", + }, + ] + + +async def test_set_files_twice_intersected( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input-multiple") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["noop.txt"]), + ) + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["noop.txt", "noop-2.txt"]), + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + { + "files": [ + "noop.txt", + "noop-2.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + "noop-2.txt", + ], + "type": "change", + }, + ] + + +async def test_set_files_twice_same( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + { + "files": [ + "noop.txt", + ], + "type": "cancel", + }, + ] + + +async def test_set_files_twice_same_in_different_folders( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input") + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["different/to/noop.txt"]), + ) + + events = await get_events(bidi_session, top_context["context"]) + assert events == [ + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + { + "files": [ + "noop.txt", + ], + "type": "input", + }, + { + "files": [ + "noop.txt", + ], + "type": "change", + }, + ] diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/invalid.py new file mode 100644 index 0000000000..6527f462c9 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/input/set_files/invalid.py @@ -0,0 +1,232 @@ +import pytest + +from webdriver.bidi.error import ( + InvalidArgumentException, + NoSuchElementException, + NoSuchFrameException, + NoSuchNodeException, + UnableToSetFileInputException, +) +from webdriver.bidi.modules.script import ContextTarget + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize("value", [None, True, 42, {}, []]) +async def test_params_context_invalid_type( + bidi_session, load_static_test_page, get_element, value +): + await load_static_test_page(page="files.html") + element = await get_element("#input") + with pytest.raises(InvalidArgumentException): + await bidi_session.input.set_files( + context=value, + element=element, + files=[], + ) + + +async def test_params_context_invalid_value( + bidi_session, load_static_test_page, get_element +): + await load_static_test_page(page="files.html") + element = await get_element("#input") + with pytest.raises(NoSuchFrameException): + await bidi_session.input.set_files( + context="foo", + element=element, + files=[], + ) + + +@pytest.mark.parametrize("value", [None, True, 42, []]) +async def test_params_element_invalid_type(bidi_session, top_context, value): + with pytest.raises(InvalidArgumentException): + await bidi_session.input.set_files( + context=top_context["context"], + element=value, + files=[], + ) + + +@pytest.mark.parametrize("value", [None, True, 42, {}]) +async def test_params_files_invalid_type( + top_context, bidi_session, load_static_test_page, get_element, value +): + await load_static_test_page(page="files.html") + element = await get_element("#input") + with pytest.raises(InvalidArgumentException): + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=value, + ) + + +@pytest.mark.parametrize("value", [None, True, 42, {}, []]) +async def test_params_files_file_invalid_type( + top_context, bidi_session, load_static_test_page, get_element, value +): + await load_static_test_page(page="files.html") + element = await get_element("#input") + with pytest.raises(InvalidArgumentException): + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=[value], + ) + + +async def test_params_element_invalid_shared_reference_value( + bidi_session, + top_context, + load_static_test_page, + create_files, +): + await load_static_test_page(page="files.html") + + with pytest.raises(NoSuchNodeException): + await bidi_session.input.set_files( + context=top_context["context"], + element={"sharedId": "invalid"}, + files=create_files(["path/to/noop.txt"]), + ) + + +@pytest.mark.parametrize( + "expression", + [ + "document.querySelector('input#button').attributes[0]", + "document.querySelector('#with-text-node').childNodes[0]", + """document.createProcessingInstruction("xml-stylesheet", "href='foo.css'")""", + "document.querySelector('#with-comment').childNodes[0]", + "document", + "document.doctype", + "document.createDocumentFragment()", + "document.querySelector('#custom-element').shadowRoot", + ], + ids=[ + "attribute", + "text node", + "processing instruction", + "comment", + "document", + "doctype", + "document fragment", + "shadow root", + ] +) +async def test_params_element_invalid_element( + bidi_session, + top_context, + get_test_page, + create_files, + expression +): + await bidi_session.browsing_context.navigate( + context=top_context["context"], + url=get_test_page(), + wait="complete", + ) + + node = await bidi_session.script.evaluate( + expression=expression, + target=ContextTarget(top_context["context"]), + await_promise=False, + ) + + with pytest.raises(NoSuchElementException): + await bidi_session.input.set_files( + context=top_context["context"], + element=node, + files=create_files(["path/to/noop.txt"]), + ) + + +async def test_params_element_disabled( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input-disabled") + + with pytest.raises(UnableToSetFileInputException): + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + +@pytest.mark.parametrize( + "html", + [ + "
foo
", + "foo", + "foo", + ], +) +async def test_params_element_non_input( + bidi_session, + top_context, + inline, + get_element, + create_files, + html, +): + await bidi_session.browsing_context.navigate( + context=top_context["context"], + url=inline(html), + wait="complete", + ) + + element = await get_element("#test") + + with pytest.raises(UnableToSetFileInputException): + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + +async def test_params_element_non_file_input( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files, +): + await load_static_test_page(page="files.html") + + element = await get_element("#text-input") + + with pytest.raises(UnableToSetFileInputException): + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt"]), + ) + + +async def test_params_element_not_multiple( + bidi_session, + top_context, + load_static_test_page, + get_element, + create_files +): + await load_static_test_page(page="files.html") + + element = await get_element("#input") + + with pytest.raises(UnableToSetFileInputException): + await bidi_session.input.set_files( + context=top_context["context"], + element=element, + files=create_files(["path/to/noop.txt", "path/to/noop-2.txt"]), + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/integration/navigation.py b/testing/web-platform/tests/webdriver/tests/bidi/integration/navigation.py new file mode 100644 index 0000000000..23615040c7 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/integration/navigation.py @@ -0,0 +1,67 @@ +import pytest + +from webdriver.error import TimeoutException +from webdriver.bidi.error import UnknownErrorException +from webdriver.bidi.modules.script import ContextTarget + + +pytestmark = pytest.mark.asyncio + +NAVIGATION_STARTED_EVENT = "browsingContext.navigationStarted" +FRAGMENT_NAVIGATED_EVENT = "browsingContext.fragmentNavigated" +BEFORE_REQUEST_SENT_EVENT = "network.beforeRequestSent" + +async def test_navigate_history_replacestate_beforeunload( + bidi_session, inline, new_tab, subscribe_events +): + url = inline(""" + """) + + result = await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=url, wait="complete" + ) + + events = [] + + async def on_event(method, data): + events.append(method) + + remove_navigation_started_listener = bidi_session.add_event_listener( + NAVIGATION_STARTED_EVENT, on_event + ) + + remove_fragment_navigated_listener = bidi_session.add_event_listener( + FRAGMENT_NAVIGATED_EVENT, on_event + ) + + remove_before_request_sent_listener = bidi_session.add_event_listener( + BEFORE_REQUEST_SENT_EVENT, on_event + ) + + await subscribe_events([NAVIGATION_STARTED_EVENT, FRAGMENT_NAVIGATED_EVENT, BEFORE_REQUEST_SENT_EVENT]) + + result = await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=url, wait="interactive" + ) + + # Navigation caused by browsing_context.navigate call should happen first: + # https://html.spec.whatwg.org/#beginning-navigation + # network.beforeRequestSent should arrive before the page becomes + # interactive. + assert events == [ + NAVIGATION_STARTED_EVENT, + FRAGMENT_NAVIGATED_EVENT, + BEFORE_REQUEST_SENT_EVENT + ] + + remove_navigation_started_listener() + remove_fragment_navigated_listener() + remove_before_request_sent_listener() diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/add_intercept.py b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/add_intercept.py index 7648eb1934..c073e1cc32 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/add_intercept.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/add_intercept.py @@ -15,49 +15,6 @@ from .. import ( ) -@pytest.mark.asyncio -@pytest.mark.parametrize("phase", ["beforeRequestSent", "responseStarted"]) -async def test_other_context( - bidi_session, - url, - top_context, - add_intercept, - fetch, - setup_network_test, - phase, -): - # Subscribe to network events only in top_context - await setup_network_test( - events=[ - BEFORE_REQUEST_SENT_EVENT, - RESPONSE_STARTED_EVENT, - RESPONSE_COMPLETED_EVENT, - ], - contexts=[top_context["context"]], - ) - - # Create another tab, where network events are not monitored. - other_context = await bidi_session.browsing_context.create(type_hint="tab") - await bidi_session.browsing_context.navigate( - context=other_context["context"], url=url(PAGE_EMPTY_HTML), wait="complete" - ) - - # Add an intercept. - text_url = url(PAGE_EMPTY_TEXT) - await add_intercept( - phases=[phase], - 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) - - @pytest.mark.asyncio @pytest.mark.parametrize("phase", ["beforeRequestSent", "responseStarted"]) async def test_other_url( 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 new file mode 100644 index 0000000000..83dfa5560f --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/contexts.py @@ -0,0 +1,210 @@ +import asyncio + +import pytest +from webdriver.bidi.modules.script import ScriptEvaluateResultException + +from .. import ( + assert_before_request_sent_event, + PAGE_EMPTY_HTML, + PAGE_EMPTY_TEXT, + BEFORE_REQUEST_SENT_EVENT, + RESPONSE_COMPLETED_EVENT, + RESPONSE_STARTED_EVENT, +) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("phase", ["beforeRequestSent", "responseStarted"]) +async def test_other_context( + bidi_session, + url, + top_context, + add_intercept, + fetch, + setup_network_test, + phase, +): + # Subscribe to network events only in top_context + await setup_network_test( + events=[ + BEFORE_REQUEST_SENT_EVENT, + RESPONSE_STARTED_EVENT, + RESPONSE_COMPLETED_EVENT, + ], + contexts=[top_context["context"]], + ) + + # Create another tab, where network events are not monitored. + other_context = await bidi_session.browsing_context.create(type_hint="tab") + await bidi_session.browsing_context.navigate( + context=other_context["context"], url=url(PAGE_EMPTY_HTML), wait="complete" + ) + + # Add an intercept. + text_url = url(PAGE_EMPTY_TEXT) + await add_intercept( + phases=[phase], + 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) + + +@pytest.mark.asyncio +async def test_other_context_with_event_subscription( + bidi_session, + url, + top_context, + add_intercept, + fetch, + setup_network_test, + wait_for_event, + wait_for_future_safe +): + # Create another tab that will listen to network events without interception. + other_context = await bidi_session.browsing_context.create(type_hint="tab") + await bidi_session.browsing_context.navigate( + context=other_context["context"], url=url(PAGE_EMPTY_HTML), wait="complete" + ) + + # Subscribe to network events in both contexts. + await setup_network_test( + events=[ + BEFORE_REQUEST_SENT_EVENT, + RESPONSE_STARTED_EVENT, + RESPONSE_COMPLETED_EVENT, + ], + contexts=[top_context["context"], other_context["context"]], + ) + + # Add an intercept to top_context only. + text_url = url(PAGE_EMPTY_TEXT) + await add_intercept( + phases=["beforeRequestSent"], + url_patterns=[{"type": "string", "pattern": text_url}], + contexts=[top_context["context"]] + ) + + # Request to the top_context should be blocked. + on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + asyncio.ensure_future(fetch(text_url, context=top_context)) + event = await wait_for_future_safe(on_network_event) + assert_before_request_sent_event( + event, is_blocked=True + ) + + # Request to other_context should not be blocked. + on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + asyncio.ensure_future(fetch(text_url, context=other_context)) + event = await wait_for_future_safe(on_network_event) + assert_before_request_sent_event( + event, is_blocked=False + ) + + +@pytest.mark.asyncio +async def test_two_contexts_same_intercept( + bidi_session, + url, + top_context, + add_intercept, + fetch, + setup_network_test, + wait_for_event, + wait_for_future_safe +): + other_context = await bidi_session.browsing_context.create(type_hint="tab") + await bidi_session.browsing_context.navigate( + context=other_context["context"], url=url(PAGE_EMPTY_HTML), wait="complete" + ) + + # Subscribe to network events in both contexts. + await setup_network_test( + events=[ + BEFORE_REQUEST_SENT_EVENT, + ], + contexts=[top_context["context"], other_context["context"]], + ) + + # Add an intercept to both contexts + text_url = url(PAGE_EMPTY_TEXT) + intercept = await add_intercept( + phases=["beforeRequestSent"], + url_patterns=[{"type": "string", "pattern": text_url}], + contexts=[top_context["context"], other_context["context"]], + ) + + # Request on the top_context should be blocked. + on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + asyncio.ensure_future(fetch(text_url, context=top_context)) + event = await wait_for_future_safe(on_network_event) + assert_before_request_sent_event( + event, is_blocked=True, intercepts=[intercept] + ) + + # Request on the other_context should be blocked. + on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + asyncio.ensure_future(fetch(text_url, context=other_context)) + event = await wait_for_future_safe(on_network_event) + assert_before_request_sent_event( + event, is_blocked=True, intercepts=[intercept] + ) + + +@pytest.mark.asyncio +async def test_two_contexts_global_intercept( + bidi_session, + url, + top_context, + add_intercept, + fetch, + setup_network_test, + wait_for_event, + wait_for_future_safe +): + other_context = await bidi_session.browsing_context.create(type_hint="tab") + await bidi_session.browsing_context.navigate( + context=other_context["context"], url=url(PAGE_EMPTY_HTML), wait="complete" + ) + + # Subscribe to network events in both contexts. + await setup_network_test( + events=[ + BEFORE_REQUEST_SENT_EVENT, + ], + contexts=[top_context["context"], other_context["context"]], + ) + + # Add an intercept for top_context and a global intercept. + text_url = url(PAGE_EMPTY_TEXT) + context_intercept = await add_intercept( + phases=["beforeRequestSent"], + url_patterns=[{"type": "string", "pattern": text_url}], + contexts=[top_context["context"]], + ) + global_intercept = await add_intercept( + phases=["beforeRequestSent"], + url_patterns=[{"type": "string", "pattern": text_url}], + ) + + # Request on the top_context should be blocked and list both intercepts. + on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + asyncio.ensure_future(fetch(text_url, context=top_context)) + event = await wait_for_future_safe(on_network_event) + assert_before_request_sent_event( + event, is_blocked=True, intercepts=[context_intercept, global_intercept] + ) + + # Request on the other_context should be blocked by the global intercept. + on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + asyncio.ensure_future(fetch(text_url, context=other_context)) + event = await wait_for_future_safe(on_network_event) + assert_before_request_sent_event( + event, is_blocked=True, intercepts=[global_intercept] + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/invalid.py index ac7b273854..0821ba7782 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/invalid.py @@ -147,7 +147,8 @@ async def test_params_url_patterns_pattern_protocol_file_invalid_value(bidi_sess with pytest.raises(error.InvalidArgumentException): await bidi_session.network.add_intercept( phases=["beforeRequestSent"], - url_patterns=[{"type": "pattern", "protocol": value, "hostname": "example.com"}], + url_patterns=[ + {"type": "pattern", "protocol": value, "hostname": "example.com"}], ) @@ -185,3 +186,36 @@ async def test_params_url_patterns_pattern_search_invalid_value(bidi_session, va phases=["beforeRequestSent"], url_patterns=[{"type": "pattern", "search": value}], ) + + +@pytest.mark.parametrize("value", [False, 42, {}, ""]) +async def test_params_contexts_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.network.add_intercept(phases=["beforeRequestSent"], contexts=value) + + +async def test_params_contexts_empty_list(bidi_session): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.network.add_intercept(phases=["beforeRequestSent"], contexts=[]) + + +async def test_params_contexts_context_invalid_value(bidi_session): + with pytest.raises(error.NoSuchFrameException): + await bidi_session.network.add_intercept(phases=["beforeRequestSent"], contexts=["does not exist"]) + + +async def test_params_contexts_context_non_top_level(bidi_session, new_tab, test_page_same_origin_frame): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=test_page_same_origin_frame, + wait="complete", + ) + + contexts = await bidi_session.browsing_context.get_tree(root=new_tab["context"]) + + assert len(contexts) == 1 + assert len(contexts[0]["children"]) == 1 + child_info = contexts[0]["children"][0] + + with pytest.raises(error.InvalidArgumentException): + await bidi_session.network.add_intercept(phases=["beforeRequestSent"], contexts=[child_info['context']]) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/phase_auth_required.py b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/phase_auth_required.py index dd322a2340..0df3e9e86a 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/phase_auth_required.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/phase_auth_required.py @@ -1,9 +1,6 @@ import pytest -from .. import ( - assert_before_request_sent_event, - assert_response_event, -) +import asyncio from .. import ( assert_before_request_sent_event, @@ -26,7 +23,14 @@ async def test_basic_authentication( url, setup_network_test, add_intercept, + fetch, ): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=url(PAGE_EMPTY_TEXT), + wait="complete", + ) + network_events = await setup_network_test( events=[ BEFORE_REQUEST_SENT_EVENT, @@ -49,11 +53,8 @@ async def test_basic_authentication( assert isinstance(intercept, str) on_auth_required = wait_for_event(AUTH_REQUIRED_EVENT) - await bidi_session.browsing_context.navigate( - context=new_tab["context"], - url=auth_url, - wait="none", - ) + # The fetch should fails as there is no authentication + asyncio.ensure_future(fetch(url=auth_url, context=new_tab)) await wait_for_future_safe(on_auth_required) expected_request = {"method": "GET", "url": auth_url} diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/url_patterns.py b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/url_patterns.py index 517a94ffc4..cee5f5d822 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/url_patterns.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/add_intercept/url_patterns.py @@ -59,7 +59,7 @@ def substitute_host(server_config): async def test_pattern_patterns_matching( wait_for_event, subscribe_events, - top_context, + new_tab, add_intercept, fetch, substitute_host, @@ -67,7 +67,7 @@ async def test_pattern_patterns_matching( patterns, url_template, ): - await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[top_context["context"]]) + await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[new_tab["context"]]) for pattern in patterns: for key in pattern: @@ -78,7 +78,7 @@ async def test_pattern_patterns_matching( intercept = await add_intercept(phases=["beforeRequestSent"], url_patterns=patterns) on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) - asyncio.ensure_future(fetch(substitute_host(url_template))) + asyncio.ensure_future(fetch(substitute_host(url_template), context=new_tab)) event = await wait_for_future_safe(on_network_event) assert_before_request_sent_event(event, is_blocked=True, intercepts=[intercept]) @@ -106,7 +106,7 @@ async def test_pattern_patterns_matching( async def test_pattern_patterns_not_matching( wait_for_event, subscribe_events, - top_context, + new_tab, add_intercept, fetch, substitute_host, @@ -114,7 +114,7 @@ async def test_pattern_patterns_not_matching( pattern, url_template, ): - await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[top_context["context"]]) + await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[new_tab["context"]]) for key in pattern: pattern[key] = substitute_host(pattern[key]) @@ -124,7 +124,7 @@ async def test_pattern_patterns_not_matching( await add_intercept(phases=["beforeRequestSent"], url_patterns=[pattern]) on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) - asyncio.ensure_future(fetch(substitute_host(url_template))) + asyncio.ensure_future(fetch(substitute_host(url_template), context=new_tab)) event = await wait_for_future_safe(on_network_event) assert_before_request_sent_event(event, is_blocked=False) @@ -156,7 +156,7 @@ async def test_pattern_patterns_not_matching( async def test_string_patterns_matching( wait_for_event, subscribe_events, - top_context, + new_tab, add_intercept, fetch, substitute_host, @@ -164,7 +164,7 @@ async def test_string_patterns_matching( pattern, url_template, ): - await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[top_context["context"]]) + await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[new_tab["context"]]) intercept = await add_intercept( phases=["beforeRequestSent"], @@ -172,7 +172,7 @@ async def test_string_patterns_matching( ) on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) - asyncio.ensure_future(fetch(substitute_host(url_template))) + asyncio.ensure_future(fetch(substitute_host(url_template), context=new_tab)) event = await wait_for_future_safe(on_network_event) assert_before_request_sent_event(event, is_blocked=True, intercepts=[intercept]) @@ -198,7 +198,7 @@ async def test_string_patterns_matching( async def test_string_patterns_not_matching( wait_for_event, subscribe_events, - top_context, + new_tab, add_intercept, fetch, substitute_host, @@ -206,7 +206,7 @@ async def test_string_patterns_not_matching( pattern, url_template, ): - await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[top_context["context"]]) + await subscribe_events(events=[BEFORE_REQUEST_SENT_EVENT], contexts=[new_tab["context"]]) await add_intercept( phases=["beforeRequestSent"], @@ -214,7 +214,7 @@ async def test_string_patterns_not_matching( ) on_network_event = wait_for_event(BEFORE_REQUEST_SENT_EVENT) - asyncio.ensure_future(fetch(substitute_host(url_template))) + asyncio.ensure_future(fetch(substitute_host(url_template), context=new_tab)) event = await wait_for_future_safe(on_network_event) assert_before_request_sent_event(event, is_blocked=False) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/auth_required.py b/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/auth_required.py index 9a24946cde..4f5c836280 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/auth_required.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/auth_required.py @@ -1,12 +1,20 @@ import pytest +import asyncio + from .. import assert_response_event, AUTH_REQUIRED_EVENT, PAGE_EMPTY_HTML @pytest.mark.asyncio async def test_subscribe_status( - bidi_session, new_tab, subscribe_events, wait_for_event, wait_for_future_safe, url + bidi_session, new_tab, subscribe_events, wait_for_event, wait_for_future_safe, url, fetch ): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=url(PAGE_EMPTY_HTML), + wait="complete", + ) + await subscribe_events(events=[AUTH_REQUIRED_EVENT]) # Track all received network.authRequired events in the events array. @@ -15,7 +23,8 @@ async def test_subscribe_status( async def on_event(method, data): events.append(data) - remove_listener = bidi_session.add_event_listener(AUTH_REQUIRED_EVENT, on_event) + remove_listener = bidi_session.add_event_listener( + AUTH_REQUIRED_EVENT, on_event) auth_url = url( "/webdriver/tests/support/http_handlers/authentication.py?realm=testrealm" @@ -23,13 +32,7 @@ async def test_subscribe_status( on_auth_required = wait_for_event(AUTH_REQUIRED_EVENT) - # navigate using wait="none" as other wait conditions would hang because of - # the authentication prompt. - await bidi_session.browsing_context.navigate( - context=new_tab["context"], - url=auth_url, - wait="none", - ) + asyncio.ensure_future(fetch(url=auth_url, context=new_tab)) await wait_for_future_safe(on_auth_required) @@ -63,7 +66,8 @@ async def test_no_authentication( async def on_event(method, data): events.append(data) - remove_listener = bidi_session.add_event_listener(AUTH_REQUIRED_EVENT, on_event) + remove_listener = bidi_session.add_event_listener( + AUTH_REQUIRED_EVENT, on_event) # Navigate to a page which should not trigger any authentication. await bidi_session.browsing_context.navigate( diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/unsubscribe.py b/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/unsubscribe.py index cf818fee6f..0bbf8df266 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/unsubscribe.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/auth_required/unsubscribe.py @@ -1,15 +1,22 @@ -import asyncio - import pytest -pytestmark = pytest.mark.asyncio +import asyncio + +from webdriver.bidi.modules.script import ScriptEvaluateResultException from .. import AUTH_REQUIRED_EVENT, PAGE_EMPTY_HTML +pytestmark = pytest.mark.asyncio # This test can be moved back to `auth_required.py` when all implementations # support handing of HTTP auth prompt. -async def test_unsubscribe(bidi_session, new_tab, url): +async def test_unsubscribe(bidi_session, new_tab, url, fetch): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=url(PAGE_EMPTY_HTML), + wait="complete", + ) + await bidi_session.session.subscribe(events=[AUTH_REQUIRED_EVENT]) await bidi_session.session.unsubscribe(events=[AUTH_REQUIRED_EVENT]) @@ -19,17 +26,13 @@ async def test_unsubscribe(bidi_session, new_tab, url): async def on_event(method, data): events.append(data) - remove_listener = bidi_session.add_event_listener(AUTH_REQUIRED_EVENT, on_event) + remove_listener = bidi_session.add_event_listener( + AUTH_REQUIRED_EVENT, on_event) + + asyncio.ensure_future(fetch(url=url( + "/webdriver/tests/support/http_handlers/authentication.py?realm=testrealm" + ), context=new_tab)) - # Navigate to authentication.py again and check no event is received. - await bidi_session.browsing_context.navigate( - context=new_tab["context"], - url=url( - "/webdriver/tests/support/http_handlers/authentication.py?realm=testrealm" - ), - wait="none", - ) - await asyncio.sleep(0.5) assert len(events) == 0 remove_listener() diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent_cached.py b/testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent_cached.py new file mode 100644 index 0000000000..2de71362ae --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/before_request_sent/before_request_sent_cached.py @@ -0,0 +1,123 @@ +import pytest +import random + +from tests.support.sync import AsyncPoll + +from .. import ( + assert_before_request_sent_event, + PAGE_EMPTY_TEXT, + BEFORE_REQUEST_SENT_EVENT, +) + +# Note: The cached status cannot be checked in the beforeRequestSent event, but +# the goal is to verify that the events are still emitted for cached requests. + + +@pytest.mark.asyncio +async def test_cached_document( + wait_for_event, + wait_for_future_safe, + url, + fetch, + setup_network_test, +): + network_events = await setup_network_test( + events=[ + BEFORE_REQUEST_SENT_EVENT, + ] + ) + events = network_events[BEFORE_REQUEST_SENT_EVENT] + + # `nocache` is not used in cached.py, it is here to avoid the browser cache. + cached_url = url( + f"/webdriver/tests/support/http_handlers/cached.py?status=200&nocache={random.random()}" + ) + on_before_request_sent = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + await fetch(cached_url) + await wait_for_future_safe(on_before_request_sent) + + assert len(events) == 1 + expected_request = {"method": "GET", "url": cached_url} + + assert_before_request_sent_event( + events[0], + expected_request=expected_request, + ) + + on_before_request_sent = wait_for_event(BEFORE_REQUEST_SENT_EVENT) + await fetch(cached_url) + await wait_for_future_safe(on_before_request_sent) + + assert len(events) == 2 + + assert_before_request_sent_event( + events[1], + expected_request=expected_request, + ) + + +@pytest.mark.asyncio +async def test_page_with_cached_resource( + bidi_session, + url, + inline, + setup_network_test, + top_context, +): + network_events = await setup_network_test( + events=[ + BEFORE_REQUEST_SENT_EVENT, + ] + ) + events = network_events[BEFORE_REQUEST_SENT_EVENT] + + # Build a page with a stylesheet resource which will be read from http cache + # on the next reload. + # `nocache` is not used in cached.py, it is here to avoid the browser cache. + cached_css_url = url( + f"/webdriver/tests/support/http_handlers/cached.py?status=200&contenttype=text/css&nocache={random.random()}" + ) + page_with_cached_css = inline( + f""" + + test page with cached stylesheet + """, + ) + + await bidi_session.browsing_context.navigate( + context=top_context["context"], + url=page_with_cached_css, + wait="complete", + ) + + # Expect two events, one for the document, one for the stylesheet. + wait = AsyncPoll(bidi_session, timeout=2) + await wait.until(lambda _: len(events) >= 2) + assert len(events) == 2 + + assert_before_request_sent_event( + events[0], + expected_request={"method": "GET", "url": page_with_cached_css}, + ) + assert_before_request_sent_event( + events[1], + expected_request={"method": "GET", "url": cached_css_url}, + ) + + # Reload the page. + await bidi_session.browsing_context.reload(context=top_context["context"]) + + # Expect two events after reload, for the document and the stylesheet. + wait = AsyncPoll(bidi_session, timeout=2) + await wait.until(lambda _: len(events) >= 4) + assert len(events) == 4 + + assert_before_request_sent_event( + events[2], + expected_request={"method": "GET", "url": page_with_cached_css}, + ) + + assert_before_request_sent_event( + events[3], + expected_request={"method": "GET", "url": cached_css_url}, + ) 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 934b649c91..7813530c4c 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/conftest.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/conftest.py @@ -17,11 +17,12 @@ async def add_intercept(bidi_session): intercepts = [] - async def add_intercept(phases, url_patterns): + async def add_intercept(phases, url_patterns, contexts = None): nonlocal intercepts intercept = await bidi_session.network.add_intercept( phases=phases, url_patterns=url_patterns, + contexts=contexts, ) intercepts.append(intercept) @@ -143,6 +144,7 @@ async def setup_blocked_request( add_intercept, fetch, wait_for_event, + wait_for_future_safe, top_context, ): """Creates an intercept for the provided phase, sends a fetch request that @@ -189,16 +191,17 @@ async def setup_blocked_request( ], ) + network_event = wait_for_event(f"network.{phase}") if navigate: asyncio.ensure_future( bidi_session.browsing_context.navigate( - context=top_context["context"], url=blocked_url, wait="complete" + context=context["context"], url=blocked_url, wait="complete" ) ) else: - asyncio.ensure_future(fetch(blocked_url)) + asyncio.ensure_future(fetch(blocked_url, context=context)) - event = await wait_for_event(f"network.{phase}") + event = await wait_for_future_safe(network_event) request = event["request"]["request"] return request diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/credentials.py b/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/credentials.py index 3e595722cc..499c8a28c1 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/credentials.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/credentials.py @@ -11,7 +11,7 @@ pytestmark = pytest.mark.asyncio @pytest.mark.parametrize("navigate", [False, True], ids=["fetch", "navigate"]) async def test_wrong_credentials( - 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 ): username = f"test_missing_credentials_{navigate}" password = f"test_missing_credentials_password_{navigate}" @@ -27,12 +27,12 @@ async def test_wrong_credentials( await bidi_session.network.continue_response( request=request, credentials=wrong_credentials ) - await on_auth_required + await wait_for_future_safe(on_auth_required) @pytest.mark.parametrize("navigate", [False, True], ids=["fetch", "navigate"]) async def test_correct_credentials( - 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 ): # Setup unique username / password because browsers cache credentials. username = f"test_wrong_credentials_{navigate}" @@ -64,15 +64,17 @@ async def test_correct_credentials( await bidi_session.network.continue_response( request=request, credentials=correct_credentials ) - await on_response_completed + await wait_for_future_safe(on_response_completed) if navigate: - await on_load - - # Wait until 2 responseCompleted events have been emitted: - # - one for the initial request - # - one for the continue with correct credentials - wait = AsyncPoll(bidi_session, timeout=2) - await wait.until(lambda _: len(response_completed_events) >= 2) - assert len(response_completed_events) == 2 + await wait_for_future_safe(on_load) + + # TODO: At the moment, the specification does not expect to receive a + # responseCompleted event for each authentication attempt, so only assert + # the last event. See https://github.com/w3c/webdriver-bidi/issues/627 + + # Wait until a a responseCompleted event with status 200 OK is received. + wait = AsyncPoll( + bidi_session, message="Didn't receive response completed events") + await wait.until(lambda _: len(response_completed_events) > 0 and response_completed_events[-1]["response"]["status"] == 200) remove_listener() diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/request.py b/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/request.py index 579f1da288..ae9c94d955 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/request.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/continue_response/request.py @@ -1,17 +1,13 @@ import pytest -from webdriver.bidi.modules.network import AuthCredentials - -from tests.support.sync import AsyncPoll - -from .. import AUTH_REQUIRED_EVENT, RESPONSE_COMPLETED_EVENT, RESPONSE_STARTED_EVENT +from .. import AUTH_REQUIRED_EVENT, RESPONSE_COMPLETED_EVENT pytestmark = pytest.mark.asyncio @pytest.mark.parametrize("navigate", [False, True], ids=["fetch", "navigate"]) async def test_continue_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 ): # Setup unique username / password because browsers cache credentials. username = f"test_continue_auth_required_{navigate}" @@ -30,12 +26,12 @@ async def test_continue_auth_required( # network.authRequired should be emitted. on_auth_required = wait_for_event(AUTH_REQUIRED_EVENT) await bidi_session.network.continue_response(request=request) - await on_auth_required + await wait_for_future_safe(on_auth_required) @pytest.mark.parametrize("navigate", [False, True], ids=["fetch", "navigate"]) async def test_continue_response_started( - 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("responseStarted", navigate=navigate) @@ -52,6 +48,6 @@ async def test_continue_response_started( await bidi_session.network.continue_response(request=request) - await on_response_completed + await wait_for_future_safe(on_response_completed) if navigate: - await on_load + await wait_for_future_safe(on_load) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/continue_with_auth/action.py b/testing/web-platform/tests/webdriver/tests/bidi/network/continue_with_auth/action.py index a122ce0e49..e4cf6da08f 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/continue_with_auth/action.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/continue_with_auth/action.py @@ -7,7 +7,6 @@ from tests.support.sync import AsyncPoll from .. import ( assert_response_event, AUTH_REQUIRED_EVENT, - PAGE_EMPTY_TEXT, RESPONSE_COMPLETED_EVENT, ) @@ -15,7 +14,7 @@ pytestmark = pytest.mark.asyncio async def test_cancel( - setup_blocked_request, subscribe_events, wait_for_event, bidi_session, url + setup_blocked_request, subscribe_events, wait_for_event, bidi_session, wait_for_future_safe ): request = await setup_blocked_request("authRequired") await subscribe_events(events=[RESPONSE_COMPLETED_EVENT]) @@ -24,7 +23,7 @@ async def test_cancel( await bidi_session.network.continue_with_auth(request=request, action="cancel") await on_response_completed - response_event = await on_response_completed + response_event = await wait_for_future_safe(on_response_completed) assert_response_event( response_event, expected_response={ @@ -35,7 +34,7 @@ async def test_cancel( async def test_default( - setup_blocked_request, subscribe_events, wait_for_event, bidi_session, url + setup_blocked_request, subscribe_events, bidi_session ): request = await setup_blocked_request("authRequired") @@ -64,7 +63,7 @@ async def test_default( async def test_provideCredentials( - setup_blocked_request, subscribe_events, bidi_session, url + setup_blocked_request, subscribe_events, bidi_session ): # Setup unique username / password because browsers cache credentials. username = "test_provideCredentials" @@ -101,7 +100,7 @@ async def test_provideCredentials( async def test_provideCredentials_wrong_credentials( - setup_blocked_request, subscribe_events, bidi_session, wait_for_event, url + setup_blocked_request, subscribe_events, bidi_session, wait_for_event, wait_for_future_safe ): # Setup unique username / password because browsers cache credentials. username = "test_provideCredentials_wrong_credentials" @@ -129,7 +128,7 @@ async def test_provideCredentials_wrong_credentials( ) # We expect to get another authRequired event after providing wrong credentials - await on_auth_required + await wait_for_future_safe(on_auth_required) # Continue with the correct credentials correct_credentials = AuthCredentials(username=username, password=password) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed_cached.py b/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed_cached.py index 6457e7d412..25503c971d 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed_cached.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/response_completed/response_completed_cached.py @@ -148,6 +148,7 @@ async def test_cached_revalidate( ) events = network_events[RESPONSE_COMPLETED_EVENT] + # `nocache` is not used in cached.py, it is here to avoid the browser cache. revalidate_url = url( f"/webdriver/tests/support/http_handlers/must-revalidate.py?nocache={random.random()}" ) @@ -189,3 +190,74 @@ async def test_cached_revalidate( expected_request=expected_request, expected_response=expected_response, ) + + +@pytest.mark.asyncio +async def test_page_with_cached_resource( + bidi_session, + url, + inline, + setup_network_test, + top_context, +): + network_events = await setup_network_test( + events=[ + RESPONSE_COMPLETED_EVENT, + ] + ) + events = network_events[RESPONSE_COMPLETED_EVENT] + + # Build a page with a stylesheet resource which will be read from http cache + # on the next reload. + # `nocache` is not used in cached.py, it is here to avoid the browser cache. + cached_css_url = url( + f"/webdriver/tests/support/http_handlers/cached.py?status=200&contenttype=text/css&nocache={random.random()}" + ) + page_with_cached_css = inline( + f""" + + test page with cached stylesheet + """, + ) + + await bidi_session.browsing_context.navigate( + context=top_context["context"], + url=page_with_cached_css, + wait="complete", + ) + + # Expect two events, one for the page, one for the stylesheet. + wait = AsyncPoll(bidi_session, timeout=2) + await wait.until(lambda _: len(events) >= 2) + assert len(events) == 2 + + assert_response_event( + events[0], + expected_request={"method": "GET", "url": page_with_cached_css}, + expected_response={"url": page_with_cached_css, "fromCache": False}, + ) + assert_response_event( + events[1], + expected_request={"method": "GET", "url": cached_css_url}, + expected_response={"url": cached_css_url, "fromCache": False}, + ) + + # Reload the page. + await bidi_session.browsing_context.reload(context=top_context["context"]) + + # Expect two additional events after reload, for the page and the stylesheet. + wait = AsyncPoll(bidi_session, timeout=2) + await wait.until(lambda _: len(events) >= 4) + assert len(events) == 4 + + assert_response_event( + events[2], + expected_request={"method": "GET", "url": page_with_cached_css}, + expected_response={"url": page_with_cached_css, "fromCache": False}, + ) + + assert_response_event( + events[3], + expected_request={"method": "GET", "url": cached_css_url}, + expected_response={"url": cached_css_url, "fromCache": True}, + ) 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 dec743e175..fb99073fb3 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 @@ -245,6 +245,11 @@ async def test_response_mime_type_file( async def test_www_authenticate( bidi_session, url, fetch, new_tab, wait_for_event, wait_for_future_safe, setup_network_test ): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=url(PAGE_EMPTY_HTML), + wait="complete", + ) auth_url = url( "/webdriver/tests/support/http_handlers/authentication.py?realm=testrealm" ) @@ -253,11 +258,8 @@ async def test_www_authenticate( events = network_events[RESPONSE_STARTED_EVENT] on_response_started = wait_for_event(RESPONSE_STARTED_EVENT) - await bidi_session.browsing_context.navigate( - context=new_tab["context"], - url=auth_url, - wait="none", - ) + + asyncio.ensure_future(fetch(url=auth_url, context=new_tab)) await wait_for_future_safe(on_response_started) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started_cached.py b/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started_cached.py index 2776950b0e..2c747f135a 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started_cached.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/network/response_started/response_started_cached.py @@ -21,6 +21,7 @@ async def test_cached( ) events = network_events[RESPONSE_STARTED_EVENT] + # `nocache` is not used in cached.py, it is here to avoid the browser cache. cached_url = url( f"/webdriver/tests/support/http_handlers/cached.py?status=200&nocache={random.random()}" ) @@ -78,6 +79,7 @@ async def test_cached_redirect( events = network_events[RESPONSE_STARTED_EVENT] text_url = url(PAGE_EMPTY_TEXT) + # `nocache` is not used in cached.py, it is here to avoid the browser cache. cached_url = url( f"/webdriver/tests/support/http_handlers/cached.py?status=301&location={text_url}&nocache={random.random()}" ) @@ -156,6 +158,7 @@ async def test_cached_revalidate( ) events = network_events[RESPONSE_STARTED_EVENT] + # `nocache` is not used in cached.py, it is here to avoid the browser cache. revalidate_url = url( f"/webdriver/tests/support/http_handlers/must-revalidate.py?nocache={random.random()}" ) @@ -197,3 +200,74 @@ async def test_cached_revalidate( expected_request=expected_request, expected_response=expected_response, ) + + +@pytest.mark.asyncio +async def test_page_with_cached_resource( + bidi_session, + url, + inline, + setup_network_test, + top_context, +): + network_events = await setup_network_test( + events=[ + RESPONSE_STARTED_EVENT, + ] + ) + events = network_events[RESPONSE_STARTED_EVENT] + + # Build a page with a stylesheet resource which will be read from http cache + # on the next reload. + # `nocache` is not used in cached.py, it is here to avoid the browser cache. + cached_css_url = url( + f"/webdriver/tests/support/http_handlers/cached.py?status=200&contenttype=text/css&nocache={random.random()}" + ) + page_with_cached_css = inline( + f""" + + test page with cached stylesheet + """, + ) + + await bidi_session.browsing_context.navigate( + context=top_context["context"], + url=page_with_cached_css, + wait="complete", + ) + + # Expect two events, one for the page, one for the stylesheet. + wait = AsyncPoll(bidi_session, timeout=2) + await wait.until(lambda _: len(events) >= 2) + assert len(events) == 2 + + assert_response_event( + events[0], + expected_request={"method": "GET", "url": page_with_cached_css}, + expected_response={"url": page_with_cached_css, "fromCache": False}, + ) + assert_response_event( + events[1], + expected_request={"method": "GET", "url": cached_css_url}, + expected_response={"url": cached_css_url, "fromCache": False}, + ) + + # Reload the page. + await bidi_session.browsing_context.reload(context=top_context["context"]) + + # Expect two additional events after reload, for the page and the stylesheet. + wait = AsyncPoll(bidi_session, timeout=2) + await wait.until(lambda _: len(events) >= 4) + assert len(events) == 4 + + assert_response_event( + events[2], + expected_request={"method": "GET", "url": page_with_cached_css}, + expected_response={"url": page_with_cached_css, "fromCache": False}, + ) + + assert_response_event( + events[3], + expected_request={"method": "GET", "url": cached_css_url}, + expected_response={"url": cached_css_url, "fromCache": True}, + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/script/call_function/serialization_options.py b/testing/web-platform/tests/webdriver/tests/bidi/script/call_function/serialization_options.py index 4084ec4820..68c8cf9c1c 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/script/call_function/serialization_options.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/script/call_function/serialization_options.py @@ -1,5 +1,6 @@ import pytest from webdriver.bidi.modules.script import ContextTarget, SerializationOptions +from webdriver.bidi.undefined import UNDEFINED from ... import any_string, recursive_compare @@ -10,7 +11,7 @@ pytestmark = pytest.mark.asyncio "include_shadow_tree, shadow_root_mode, contains_children, expected", [ ( - None, + UNDEFINED, "open", False, { @@ -20,7 +21,7 @@ pytestmark = pytest.mark.asyncio }, ), ( - None, + UNDEFINED, "closed", False, { @@ -189,7 +190,7 @@ async def test_include_shadow_tree_for_custom_element( "include_shadow_tree, contains_children, expected", [ ( - None, + UNDEFINED, False, { "type": "node", @@ -438,7 +439,8 @@ async def test_max_dom_depth( function_declaration="""() => document.querySelector("div#with-children")""", target=ContextTarget(top_context["context"]), await_promise=True, - serialization_options=SerializationOptions(max_dom_depth=max_dom_depth), + serialization_options=SerializationOptions( + max_dom_depth=max_dom_depth), ) recursive_compare(expected, result) @@ -446,21 +448,17 @@ async def test_max_dom_depth( async def test_max_dom_depth_null( bidi_session, - send_blocking_command, top_context, get_test_page, ): await bidi_session.browsing_context.navigate( context=top_context["context"], url=get_test_page(), wait="complete" ) - result = await send_blocking_command( - "script.callFunction", - { - "functionDeclaration": """() => document.querySelector("div#with-children")""", - "target": ContextTarget(top_context["context"]), - "awaitPromise": True, - "serializationOptions": {"maxDomDepth": None}, - }, + result = await bidi_session.script.call_function( + function_declaration="""() => document.querySelector("div#with-children")""", + target=ContextTarget(top_context["context"]), + await_promise=True, + serialization_options=SerializationOptions(max_dom_depth=None), ) recursive_compare( @@ -518,7 +516,7 @@ async def test_max_dom_depth_null( "shadowRoot": None, }, }, - result["result"], + result, ) @@ -526,7 +524,7 @@ async def test_max_dom_depth_null( "max_object_depth, expected", [ ( - None, + UNDEFINED, { "type": "array", "value": [ diff --git a/testing/web-platform/tests/webdriver/tests/bidi/session/new/connect.py b/testing/web-platform/tests/webdriver/tests/bidi/session/new/connect.py index d5872cd3ba..523899c336 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/session/new/connect.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/session/new/connect.py @@ -16,17 +16,16 @@ async def test_websocket_url_connect(session): # test bidi_session send @pytest.mark.asyncio -async def test_bidi_session_send(bidi_session, send_blocking_command): - await send_blocking_command("session.status", {}) +async def test_bidi_session_send(bidi_session): + await bidi_session.session.status() # bidi session following a bidi session with a different capabilities # to test session recreation @pytest.mark.asyncio @pytest.mark.capabilities({"acceptInsecureCerts": True}) -async def test_bidi_session_with_different_capability(bidi_session, - send_blocking_command): - await send_blocking_command("session.status", {}) +async def test_bidi_session_with_different_capability(bidi_session): + await bidi_session.session.status() # classic session following a bidi session to test session diff --git a/testing/web-platform/tests/webdriver/tests/bidi/session/status/status.py b/testing/web-platform/tests/webdriver/tests/bidi/session/status/status.py index 13d131bfec..f62ad4c562 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/session/status/status.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/session/status/status.py @@ -4,7 +4,7 @@ import pytest # Check that session.status can be used. The actual values for the "ready" and # "message" properties are implementation specific. @pytest.mark.asyncio -async def test_bidi_session_status(send_blocking_command): - response = await send_blocking_command("session.status", {}) +async def test_bidi_session_status(bidi_session): + response = await bidi_session.session.status() assert isinstance(response["ready"], bool) assert isinstance(response["message"], str) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/session/subscribe/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/session/subscribe/invalid.py index 81c38316f9..b1b4d28016 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/session/subscribe/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/session/subscribe/invalid.py @@ -14,39 +14,38 @@ async def test_params_empty(send_blocking_command): @pytest.mark.asyncio @pytest.mark.parametrize("value", [None, True, "foo", 42, {}]) -async def test_params_events_invalid_type(send_blocking_command, value): +async def test_params_events_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command("session.subscribe", {"events": value}) + await bidi_session.session.subscribe(events=value) @pytest.mark.asyncio async def test_params_events_empty(bidi_session): - response = await bidi_session.session.subscribe(events=[]) - assert response == {} + with pytest.raises(InvalidArgumentException): + await bidi_session.session.subscribe(events=[]) @pytest.mark.asyncio @pytest.mark.parametrize("value", [None, True, 42, [], {}]) -async def test_params_events_value_invalid_type(send_blocking_command, value): +async def test_params_events_value_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command("session.subscribe", {"events": [value]}) + await bidi_session.session.subscribe(events=[value]) @pytest.mark.asyncio @pytest.mark.parametrize("value", ["", "foo", "foo.bar", "log.invalidEvent"]) -async def test_params_events_value_invalid_event_name(send_blocking_command, value): +async def test_params_events_value_invalid_event_name(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command("session.subscribe", {"events": [value]}) + await bidi_session.session.subscribe(events=[value]) @pytest.mark.asyncio async def test_params_events_value_valid_and_invalid_event_names( - bidi_session, send_blocking_command, top_context + bidi_session, top_context ): with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.subscribe", {"events": ["log.entryAdded", "some.invalidEvent"]} - ) + await bidi_session.session.subscribe(events=[ + "log.entryAdded", "some.invalidEvent"]) # Make sure that we didn't subscribe to log.entryAdded because of the error @@ -56,7 +55,8 @@ async def test_params_events_value_valid_and_invalid_event_names( async def on_event(method, data): events.append(data) - remove_listener = bidi_session.add_event_listener("log.entryAdded", on_event) + remove_listener = bidi_session.add_event_listener( + "log.entryAdded", on_event) await create_console_api_message(bidi_session, top_context, "text1") @@ -69,57 +69,37 @@ async def test_params_events_value_valid_and_invalid_event_names( @pytest.mark.asyncio @pytest.mark.parametrize("value", [True, "foo", 42, {}]) -async def test_params_contexts_invalid_type(send_blocking_command, value): +async def test_params_contexts_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.subscribe", - { - "events": [], - "contexts": value, - } - ) + await bidi_session.session.subscribe(events=["log.entryAdded"], contexts=value) @pytest.mark.asyncio async def test_params_contexts_empty(bidi_session): - response = await bidi_session.session.subscribe(events=[], contexts=[]) - assert response == {} + with pytest.raises(InvalidArgumentException): + await bidi_session.session.subscribe(events=["log.entryAdded"], contexts=[]) @pytest.mark.asyncio @pytest.mark.parametrize("value", [None, True, 42, [], {}]) -async def test_params_contexts_value_invalid_type(send_blocking_command, value): +async def test_params_contexts_value_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.subscribe", - { - "events": [], - "contexts": [value], - } - ) + await bidi_session.session.subscribe(events=["log.entryAdded"], contexts=[value]) @pytest.mark.asyncio -async def test_params_contexts_value_invalid_value(send_blocking_command): +async def test_params_contexts_value_invalid_value(bidi_session): with pytest.raises(NoSuchFrameException): - await send_blocking_command( - "session.subscribe", - { - "events": [], - "contexts": ["foo"], - } - ) + await bidi_session.session.subscribe(events=["log.entryAdded"], contexts=["foo"]) @pytest.mark.asyncio async def test_params_contexts_valid_and_invalid_value( - bidi_session, send_blocking_command, top_context + bidi_session, top_context ): with pytest.raises(NoSuchFrameException): - await send_blocking_command( - "session.subscribe", - {"events": ["log.entryAdded"], "contexts": [top_context["context"], "foo"]}, - ) + await bidi_session.session.subscribe(events=["log.entryAdded"], contexts=[ + top_context["context"], "foo"]) # Make sure that we didn't subscribe to log.entryAdded because of error @@ -129,7 +109,8 @@ async def test_params_contexts_valid_and_invalid_value( async def on_event(method, data): events.append(data) - remove_listener = bidi_session.add_event_listener("log.entryAdded", on_event) + remove_listener = bidi_session.add_event_listener( + "log.entryAdded", on_event) await create_console_api_message(bidi_session, top_context, "text1") @@ -141,16 +122,10 @@ async def test_params_contexts_valid_and_invalid_value( @pytest.mark.asyncio -async def test_subscribe_to_closed_tab(bidi_session, send_blocking_command): +async def test_subscribe_to_closed_tab(bidi_session): new_tab = await bidi_session.browsing_context.create(type_hint="tab") await bidi_session.browsing_context.close(context=new_tab["context"]) # Try to subscribe to the closed context with pytest.raises(NoSuchFrameException): - await send_blocking_command( - "session.subscribe", - { - "events": ["log.entryAdded"], - "contexts": [new_tab["context"]] - }, - ) + await bidi_session.session.subscribe(events=["log.entryAdded"], contexts=[new_tab["context"]]) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/session/unsubscribe/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/session/unsubscribe/invalid.py index 5b55556413..78470afa65 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/session/unsubscribe/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/session/unsubscribe/invalid.py @@ -5,50 +5,49 @@ from ... import create_console_api_message @pytest.mark.asyncio -async def test_params_empty(bidi_session, send_blocking_command): +async def test_params_empty(send_blocking_command): with pytest.raises(InvalidArgumentException): await send_blocking_command("session.unsubscribe", {}) @pytest.mark.asyncio @pytest.mark.parametrize("value", [None, True, "foo", 42, {}]) -async def test_params_events_invalid_type(bidi_session, send_blocking_command, value): +async def test_params_events_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command("session.unsubscribe", {"events": value}) + await bidi_session.session.unsubscribe(events=value) @pytest.mark.asyncio async def test_params_events_empty(bidi_session): - response = await bidi_session.session.unsubscribe(events=[]) - assert response == {} + with pytest.raises(InvalidArgumentException): + await bidi_session.session.unsubscribe(events=[]) @pytest.mark.asyncio @pytest.mark.parametrize("value", [None, True, 42, [], {}]) -async def test_params_events_value_invalid_type(send_blocking_command, value): +async def test_params_events_value_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command("session.unsubscribe", {"events": [value]}) + await bidi_session.session.unsubscribe(events=[value]) @pytest.mark.asyncio @pytest.mark.parametrize("value", ["", "foo", "foo.bar"]) -async def test_params_events_value_invalid_event_name(send_blocking_command, value): +async def test_params_events_value_invalid_event_name(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command("session.unsubscribe", {"events": [value]}) + await bidi_session.session.unsubscribe(events=[value]) @pytest.mark.asyncio async def test_params_events_value_valid_and_invalid_event_name( - bidi_session, subscribe_events, send_blocking_command, wait_for_event, wait_for_future_safe, top_context + bidi_session, subscribe_events, wait_for_event, wait_for_future_safe, top_context ): # Subscribe to a valid event await subscribe_events(events=["log.entryAdded"]) # Try to unsubscribe from the valid and an invalid event with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", {"events": ["log.entryAdded", "some.invalidEvent"]} - ) + await bidi_session.session.unsubscribe(events=[ + "log.entryAdded", "some.invalidEvent"]) # Make sure that we didn't unsubscribe from log.entryAdded because of the error # and events are still coming @@ -59,7 +58,8 @@ async def test_params_events_value_valid_and_invalid_event_name( async def on_event(method, data): events.append(data) - remove_listener = bidi_session.add_event_listener("log.entryAdded", on_event) + remove_listener = bidi_session.add_event_listener( + "log.entryAdded", on_event) on_entry_added = wait_for_event("log.entryAdded") await create_console_api_message(bidi_session, top_context, "text1") @@ -72,7 +72,7 @@ async def test_params_events_value_valid_and_invalid_event_name( @pytest.mark.asyncio async def test_unsubscribe_from_one_event_and_then_from_module( - bidi_session, subscribe_events, send_blocking_command + bidi_session, subscribe_events ): await subscribe_events(events=["browsingContext"]) @@ -81,9 +81,7 @@ async def test_unsubscribe_from_one_event_and_then_from_module( # Try to unsubscribe from all events with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", {"events": ["browsingContext"]} - ) + await bidi_session.session.unsubscribe(events=["browsingContext"]) # Unsubscribe from the rest of the events await bidi_session.session.unsubscribe(events=["browsingContext.contextCreated"]) @@ -92,61 +90,40 @@ async def test_unsubscribe_from_one_event_and_then_from_module( @pytest.mark.asyncio @pytest.mark.parametrize("value", [True, "foo", 42, {}]) -async def test_params_contexts_invalid_type(bidi_session, send_blocking_command, value): +async def test_params_contexts_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", - { - "events": [], - "contexts": value, - } - ) + await bidi_session.session.unsubscribe(events=["browsingContext.load"], contexts=value) @pytest.mark.asyncio async def test_params_contexts_empty(bidi_session): - response = await bidi_session.session.unsubscribe(events=[], contexts=[]) - assert response == {} + with pytest.raises(InvalidArgumentException): + await bidi_session.session.unsubscribe(events=["browsingContext.load"], contexts=[]) @pytest.mark.asyncio @pytest.mark.parametrize("value", [None, True, 42, [], {}]) -async def test_params_contexts_value_invalid_type(send_blocking_command, value): +async def test_params_contexts_value_invalid_type(bidi_session, value): with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", - { - "events": [], - "contexts": [value], - } - ) + await bidi_session.session.unsubscribe(events=["browsingContext.load"], contexts=[value]) @pytest.mark.asyncio -async def test_params_contexts_value_invalid_value(send_blocking_command): +async def test_params_contexts_value_invalid_value(bidi_session): with pytest.raises(NoSuchFrameException): - await send_blocking_command( - "session.unsubscribe", - { - "events": [], - "contexts": ["foo"], - }, - ) + await bidi_session.session.unsubscribe(events=["browsingContext.load"], contexts=["foo"]) @pytest.mark.asyncio async def test_params_contexts_value_valid_and_invalid_value( - bidi_session, subscribe_events, send_blocking_command, wait_for_event, wait_for_future_safe, top_context + bidi_session, subscribe_events, wait_for_event, wait_for_future_safe, top_context ): # Subscribe to a valid context await subscribe_events(events=["log.entryAdded"], contexts=[top_context["context"]]) # Try to unsubscribe from the valid and an invalid context with pytest.raises(NoSuchFrameException): - await send_blocking_command( - "session.unsubscribe", - {"events": ["log.entryAdded"], "contexts": [top_context["context"], "foo"]}, - ) + await bidi_session.session.unsubscribe(events=["log.entryAdded"], contexts=[top_context["context"], "foo"]) # Make sure that we didn't unsubscribe from the valid context because of the error # and events are still coming @@ -157,7 +134,8 @@ async def test_params_contexts_value_valid_and_invalid_value( async def on_event(method, data): events.append(data) - remove_listener = bidi_session.add_event_listener("log.entryAdded", on_event) + remove_listener = bidi_session.add_event_listener( + "log.entryAdded", on_event) on_entry_added = wait_for_event("log.entryAdded") await create_console_api_message(bidi_session, top_context, "text1") @@ -170,7 +148,7 @@ async def test_params_contexts_value_valid_and_invalid_value( @pytest.mark.asyncio async def test_unsubscribe_from_closed_tab( - bidi_session, subscribe_events, send_blocking_command + bidi_session, subscribe_events ): new_tab = await bidi_session.browsing_context.create(type_hint="tab") # Subscribe to a new context @@ -180,55 +158,42 @@ async def test_unsubscribe_from_closed_tab( # Try to unsubscribe from the closed context with pytest.raises(NoSuchFrameException): - await send_blocking_command( - "session.unsubscribe", - {"events": ["log.entryAdded"], "contexts": [new_tab["context"]]}, - ) + await bidi_session.session.unsubscribe(events=["log.entryAdded"], contexts=[new_tab["context"]]) @pytest.mark.asyncio -async def test_params_unsubscribe_globally_without_subscription(send_blocking_command): +async def test_params_unsubscribe_globally_without_subscription(bidi_session): with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", {"events": ["log.entryAdded"]} - ) + await bidi_session.session.unsubscribe(events=["log.entryAdded"]) @pytest.mark.asyncio async def test_params_unsubscribe_globally_with_individual_subscription( - subscribe_events, send_blocking_command, top_context + subscribe_events, bidi_session, top_context ): # Subscribe to one context await subscribe_events(events=["log.entryAdded"], contexts=[top_context["context"]]) # Try to unsubscribe globally with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", {"events": ["log.entryAdded"]} - ) + await bidi_session.session.unsubscribe(events=["log.entryAdded"]) @pytest.mark.asyncio async def test_params_unsubscribe_from_one_context_without_subscription( - send_blocking_command, top_context + bidi_session, top_context ): with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", - {"events": ["log.entryAdded"], "contexts": [top_context["context"]]}, - ) + await bidi_session.session.unsubscribe(events=["log.entryAdded"], contexts=[top_context["context"]]) @pytest.mark.asyncio async def test_params_unsubscribe_from_one_context_with_global_subscription( - subscribe_events, send_blocking_command, top_context + subscribe_events, bidi_session, top_context ): # Subscribe to all contexts await subscribe_events(events=["log.entryAdded"]) # Try to unsubscribe from one context with pytest.raises(InvalidArgumentException): - await send_blocking_command( - "session.unsubscribe", - {"events": ["log.entryAdded"], "contexts": [top_context["context"]]}, - ) + await bidi_session.session.unsubscribe(events=["log.entryAdded"], contexts=[top_context["context"]]) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/__init__.py index 0d7cea96bc..4ca0f7bdd7 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/__init__.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/__init__.py @@ -1,7 +1,7 @@ from datetime import datetime, timedelta, timezone from typing import Optional from webdriver.bidi.modules.network import NetworkBytesValue, NetworkStringValue -from webdriver.bidi.modules.storage import PartialCookie, PartitionDescriptor +from webdriver.bidi.modules.storage import PartialCookie, PartitionDescriptor, BrowsingContextPartitionDescriptor from .. import any_int, recursive_compare COOKIE_NAME = 'SOME_COOKIE_NAME' @@ -88,3 +88,11 @@ def format_expiry_string(date): # same formatting as Date.toUTCString() in javascript utc_string_format = "%a, %d %b %Y %H:%M:%S GMT" return date.strftime(utc_string_format) + + +async def get_default_partition_key(bidi_session, context=None): + if context is None: + result = await bidi_session.storage.get_cookies() + else: + result = await bidi_session.storage.get_cookies(partition=BrowsingContextPartitionDescriptor(context)) + return result['partitionKey'] diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/__init__.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/__init__.py new file mode 100644 index 0000000000..4b73b0bced --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/__init__.py @@ -0,0 +1,3 @@ +async def assert_cookies_are_not_present(bidi_session, filter=None, partition=None): + result = await bidi_session.storage.get_cookies(filter=filter, partition=partition) + assert result["cookies"] == [] diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/filter.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/filter.py new file mode 100644 index 0000000000..7bfb743cfc --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/filter.py @@ -0,0 +1,514 @@ +import pytest +from webdriver.bidi.modules.network import NetworkBase64Value, NetworkStringValue +from webdriver.bidi.modules.storage import CookieFilter + +from . import assert_cookies_are_not_present +from .. import ( + assert_cookie_is_set, + create_cookie, + format_expiry_string, + get_default_partition_key, + generate_expiry_date, +) + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize( + "filter", + [ + ({"size": 6}), + ({"value": NetworkStringValue("bar")}), + ({"value": NetworkBase64Value("YmFy")}), + ], +) +async def test_filter( + bidi_session, + new_tab, + test_page, + domain_value, + add_cookie, + filter, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + # This value is going to be used to match specified filter options: + # 1. size == 6, both matching cookies have name length 3, the value has length 3; + # 2. value == "bar"; + # 3. value == base64 value "YmFy", it will be decoded to a string "bar". + cookie_value_matching_filter = "bar" + + cookie1_name = "baz" + await add_cookie(new_tab["context"], cookie1_name, cookie_value_matching_filter) + + cookie2_name = "foo" + await add_cookie(new_tab["context"], cookie2_name, cookie_value_matching_filter) + + cookie3_name = "foo_3" + cookie3_value = "not_bar" + await add_cookie(new_tab["context"], cookie3_name, cookie3_value) + + result = await bidi_session.storage.delete_cookies( + filter=filter, + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present. + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=cookie3_name, + value={"type": "string", "value": cookie3_value}, + path="/webdriver/tests/support", + secure=False, + ) + + +async def test_filter_domain( + bidi_session, + top_context, + new_tab, + test_page, + test_page_cross_origin, + domain_value, + add_cookie, +): + await bidi_session.browsing_context.navigate( + context=top_context["context"], url=test_page, wait="complete" + ) + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page_cross_origin, wait="complete" + ) + + cookie1_name = "bar" + cookie1_value = "foo" + await add_cookie(top_context["context"], cookie1_name, cookie1_value) + + cookie2_name = "foo" + cookie2_value = "bar" + await add_cookie(top_context["context"], cookie2_name, cookie2_value) + + cookie3_name = "foo_2" + cookie3_value = "bar_2" + cookie3_domain = domain_value(domain="alt") + await add_cookie(new_tab["context"], cookie3_name, cookie3_value) + + filter = CookieFilter(domain=domain_value()) + result = await bidi_session.storage.delete_cookies( + filter=filter, + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present. + await assert_cookie_is_set( + bidi_session, + domain=cookie3_domain, + name=cookie3_name, + value={"type": "string", "value": cookie3_value}, + path="/webdriver/tests/support", + secure=False, + ) + + +@pytest.mark.parametrize( + "expiry_diff_to_delete, expiry_diff_to_remain", + [ + (1, 2), + (1, None), + ], +) +async def test_filter_expiry( + bidi_session, + new_tab, + test_page, + domain_value, + add_cookie, + expiry_diff_to_delete, + expiry_diff_to_remain, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + expiry_date_to_delete = generate_expiry_date(expiry_diff_to_delete) + expiry_to_delete = int(expiry_date_to_delete.timestamp()) + date_string_to_delete = format_expiry_string(expiry_date_to_delete) + + cookie1_name = "bar" + cookie1_value = "foo" + await add_cookie( + context=new_tab["context"], + name=cookie1_name, + value=cookie1_value, + expiry=date_string_to_delete, + ) + + cookie2_name = "foo" + cookie2_value = "bar" + await add_cookie( + context=new_tab["context"], + name=cookie2_name, + value=cookie2_value, + expiry=date_string_to_delete, + ) + + cookie3_name = "foo_3" + cookie3_value = "bar_3" + if expiry_diff_to_remain is None: + date_string_to_remain = None + else: + expiry_date_to_remain = generate_expiry_date(expiry_diff_to_remain) + date_string_to_remain = format_expiry_string(expiry_date_to_remain) + + await add_cookie( + new_tab["context"], cookie3_name, cookie3_value, expiry=date_string_to_remain + ) + + filter = CookieFilter(expiry=expiry_to_delete) + result = await bidi_session.storage.delete_cookies( + filter=CookieFilter(expiry=expiry_to_delete), + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present. + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=cookie3_name, + value={"type": "string", "value": cookie3_value}, + path="/webdriver/tests/support", + secure=False, + ) + + +async def test_filter_name(bidi_session, new_tab, test_page, add_cookie, domain_value): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + name_to_delete = "foo" + + cookie1_value = "bar" + cookie1_path = "/" + await add_cookie( + new_tab["context"], name_to_delete, cookie1_value, path=cookie1_path + ) + + cookie2_value = "baz" + cookie2_path = "/webdriver/" + await add_cookie( + new_tab["context"], name_to_delete, cookie2_value, path=cookie2_path + ) + + name_to_remain = "foo_2" + cookie3_value = "bar_2" + cookie3_path = "/" + await add_cookie(new_tab["context"], name_to_remain, cookie3_value, path=cookie3_path) + + filter = CookieFilter(name=name_to_delete) + result = await bidi_session.storage.delete_cookies( + filter=filter, + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present. + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=name_to_remain, + value={"type": "string", "value": cookie3_value}, + path=cookie3_path, + secure=False, + ) + + +@pytest.mark.parametrize( + "same_site_to_delete, same_site_to_remain", + [ + ("none", "strict"), + ("lax", "none"), + ("strict", "none"), + ("lax", "strict"), + ("strict", "lax"), + ], +) +async def test_filter_same_site( + bidi_session, + new_tab, + test_page, + domain_value, + same_site_to_delete, + same_site_to_remain, + add_cookie, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + cookie1_name = "bar" + cookie1_value = "foo" + await add_cookie( + new_tab["context"], + cookie1_name, + cookie1_value, + same_site=same_site_to_delete, + ) + + cookie2_name = "foo" + cookie2_value = "bar" + await add_cookie( + new_tab["context"], + cookie2_name, + cookie2_value, + same_site=same_site_to_delete, + ) + + cookie3_name = "foo_3" + cookie3_value = "bar_3" + await add_cookie( + new_tab["context"], cookie3_name, cookie3_value, same_site=same_site_to_remain + ) + + filter = CookieFilter(same_site=same_site_to_delete) + result = await bidi_session.storage.delete_cookies( + filter=filter, + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=cookie3_name, + value={"type": "string", "value": cookie3_value}, + path="/webdriver/tests/support", + same_site=same_site_to_remain, + secure=False, + ) + + +@pytest.mark.parametrize( + "secure_to_delete, secure_to_remain", + [(True, False), (False, True)], +) +async def test_filter_secure( + bidi_session, + new_tab, + test_page, + domain_value, + add_cookie, + secure_to_delete, + secure_to_remain, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + cookie1_name = "bar" + cookie1_value = "foo" + await add_cookie( + new_tab["context"], + cookie1_name, + cookie1_value, + secure=secure_to_delete, + ) + + cookie2_name = "foo" + cookie2_value = "bar" + await add_cookie( + new_tab["context"], + cookie2_name, + cookie2_value, + secure=secure_to_delete, + ) + + cookie3_name = "foo_3" + cookie3_value = "bar_3" + await add_cookie( + new_tab["context"], cookie3_name, cookie3_value, secure=secure_to_remain + ) + + filter = CookieFilter(secure=secure_to_delete) + result = await bidi_session.storage.delete_cookies( + filter=filter, + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present. + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=cookie3_name, + value={"type": "string", "value": cookie3_value}, + path="/webdriver/tests/support", + secure=secure_to_remain, + ) + + +@pytest.mark.parametrize( + "path_to_delete, path_to_remain", + [ + ("/webdriver/tests/support", "/"), + ("/", None), + ("/webdriver", "/webdriver/tests"), + ], +) +async def test_filter_path( + bidi_session, + new_tab, + test_page, + domain_value, + add_cookie, + path_to_delete, + path_to_remain, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + cookie1_name = "bar" + cookie1_value = "foo" + await add_cookie( + new_tab["context"], + cookie1_name, + cookie1_value, + path=path_to_delete, + ) + + cookie2_name = "foo" + cookie2_value = "bar" + await add_cookie( + new_tab["context"], + cookie2_name, + cookie2_value, + path=path_to_delete, + ) + + cookie3_name = "foo_3" + cookie3_value = "bar_3" + await add_cookie( + new_tab["context"], cookie3_name, cookie3_value, path=path_to_remain + ) + + filter = CookieFilter(path=path_to_delete) + result = await bidi_session.storage.delete_cookies( + filter=filter, + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present. + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=cookie3_name, + value={"type": "string", "value": cookie3_value}, + path="/webdriver/tests/support" if path_to_remain is None else path_to_remain, + secure=False, + ) + + +@pytest.mark.parametrize( + "http_only_to_delete, http_only_to_remain", + [(True, False), (False, True)], +) +async def test_filter_http_only( + bidi_session, + new_tab, + test_page, + domain_value, + set_cookie, + http_only_to_delete, + http_only_to_remain, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + cookie1_name = "bar" + cookie1_value = "foo" + await set_cookie( + cookie=create_cookie( + domain=domain_value(), + name=cookie1_name, + value=NetworkStringValue(cookie1_value), + http_only=http_only_to_delete, + ) + ) + + cookie2_name = "foo" + cookie2_value = "bar" + await set_cookie( + cookie=create_cookie( + domain=domain_value(), + name=cookie2_name, + value=NetworkStringValue(cookie2_value), + http_only=http_only_to_delete, + ) + ) + + cookie3_name = "foo_2" + cookie3_value = "bar_2" + await set_cookie( + cookie=create_cookie( + domain=domain_value(), + name=cookie3_name, + value=NetworkStringValue(cookie3_value), + http_only=http_only_to_remain, + ) + ) + + filter = CookieFilter(http_only=http_only_to_delete) + result = await bidi_session.storage.delete_cookies( + filter=filter, + ) + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, filter) + + # Make sure that non-deleted cookies are present + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=cookie3_name, + value={"type": "string", "value": cookie3_value}, + http_only=http_only_to_remain, + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/invalid.py new file mode 100644 index 0000000000..ba9c5a5da0 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/invalid.py @@ -0,0 +1,163 @@ +import pytest +import webdriver.bidi.error as error + +from webdriver.bidi.modules.network import NetworkBase64Value, NetworkStringValue +from webdriver.bidi.modules.storage import ( + BrowsingContextPartitionDescriptor, + CookieFilter, + StorageKeyPartitionDescriptor, +) + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize("value", [False, 42, "foo", []]) +async def test_params_filter_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=value) + + +@pytest.mark.parametrize("value", [False, 42, {}, []]) +async def test_params_filter_domain_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(domain=value)) + + +@pytest.mark.parametrize("value", [False, "foo", {}, [], -1, 0.5]) +async def test_params_filter_expiry_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(expiry=value)) + + +@pytest.mark.parametrize("value", ["foo", {}, [], 42]) +async def test_params_filter_http_only_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(http_only=value)) + + +@pytest.mark.parametrize("value", [False, 42, {}, []]) +async def test_params_filter_name_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(name=value)) + + +@pytest.mark.parametrize("value", [False, 42, {}, []]) +async def test_params_filter_path_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(path=value)) + + +@pytest.mark.parametrize("value", [False, 42, {}, []]) +async def test_params_filter_same_site_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(same_site=value)) + + +@pytest.mark.parametrize("value", ["", "INVALID_SAME_SITE_STATE"]) +async def test_params_filter_same_site_invalid_value(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(same_site=value)) + + +@pytest.mark.parametrize("value", ["foo", {}, [], 42]) +async def test_params_filter_secure_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(secure=value)) + + +@pytest.mark.parametrize("value", [False, "foo", {}, [], -1, 0.5]) +async def test_params_filter_size_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(size=value)) + + +@pytest.mark.parametrize("value", [False, 42, "foo", []]) +async def test_params_filter_value_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(filter=CookieFilter(value=value)) + + +@pytest.mark.parametrize("value", [None, False, 42, {}, []]) +async def test_params_filter_value_type_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies( + filter=CookieFilter(value={"type": value}) + ) + + +async def test_params_filter_value_type_invalid_value(bidi_session): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies( + filter=CookieFilter(value={"type": "foo"}) + ) + + +@pytest.mark.parametrize("value", [None, False, 42, {}, []]) +async def test_params_filter_value_base64_type_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies( + filter=CookieFilter(value=NetworkBase64Value(value)) + ) + + +@pytest.mark.parametrize("value", [None, False, 42, {}, []]) +async def test_params_filter_value_string_type_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies( + filter=CookieFilter(value=NetworkStringValue(value)) + ) + + +@pytest.mark.parametrize("value", [False, 42, "foo", []]) +async def test_params_partition_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(partition=value) + + +@pytest.mark.parametrize("value", [None, False, 42, {}, []]) +async def test_params_partition_type_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(partition={"type": value}) + + +async def test_params_partition_type_invalid_value(bidi_session): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies(partition={"type": "foo"}) + + +@pytest.mark.parametrize("value", [None, False, 42, {}, []]) +async def test_params_partition_context_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies( + partition=BrowsingContextPartitionDescriptor(context=value) + ) + + +async def test_partition_invalid_context(bidi_session): + with pytest.raises(error.NoSuchFrameException): + await bidi_session.storage.delete_cookies( + partition=BrowsingContextPartitionDescriptor("foo") + ) + + +@pytest.mark.parametrize("value", [False, 42, {}, []]) +async def test_params_partition_source_origin_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies( + partition=StorageKeyPartitionDescriptor(source_origin=value) + ) + + +@pytest.mark.parametrize("value", [False, 42, {}, []]) +async def test_params_partition_user_context_invalid_type(bidi_session, value): + with pytest.raises(error.InvalidArgumentException): + await bidi_session.storage.delete_cookies( + partition=StorageKeyPartitionDescriptor(user_context=value) + ) + + +async def test_params_partition_user_context_invalid_value(bidi_session): + with pytest.raises(error.NoSuchUserContextException): + await bidi_session.storage.delete_cookies( + partition=StorageKeyPartitionDescriptor(user_context="foo") + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/partition.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/partition.py new file mode 100644 index 0000000000..bf23abb720 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/delete_cookies/partition.py @@ -0,0 +1,308 @@ +import pytest + +from webdriver.bidi.modules.network import NetworkStringValue +from webdriver.bidi.modules.storage import ( + BrowsingContextPartitionDescriptor, + PartialCookie, + StorageKeyPartitionDescriptor, +) + +from . import assert_cookies_are_not_present +from .. import assert_cookie_is_set, create_cookie, get_default_partition_key +from ... import recursive_compare + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize( + "with_document_cookie", + [True, False], + ids=["with document cookie", "with set cookie"], +) +async def test_default_partition( + bidi_session, + top_context, + new_tab, + test_page, + test_page_cross_origin, + domain_value, + add_cookie, + set_cookie, + with_document_cookie, +): + await bidi_session.browsing_context.navigate( + context=top_context["context"], url=test_page_cross_origin, wait="complete" + ) + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + cookie1_name = "foo" + cookie1_value = "bar" + + cookie2_name = "foo_2" + cookie2_value = "bar_2" + + if with_document_cookie: + await add_cookie(new_tab["context"], cookie1_name, cookie1_value) + await add_cookie(top_context["context"], cookie2_name, cookie2_value) + else: + await set_cookie( + cookie=create_cookie( + domain=domain_value("alt"), + name=cookie1_name, + value=NetworkStringValue(cookie1_value), + ) + ) + await set_cookie( + cookie=create_cookie( + domain=domain_value(), + name=cookie2_name, + value=NetworkStringValue(cookie2_value), + ) + ) + + result = await bidi_session.storage.delete_cookies() + assert result == { + "partitionKey": (await get_default_partition_key(bidi_session)) + } + + await assert_cookies_are_not_present(bidi_session) + + +@pytest.mark.parametrize( + "with_document_cookie", + [True, False], + ids=["with document cookie", "with set cookie"], +) +async def test_partition_context( + bidi_session, + new_tab, + test_page, + domain_value, + add_cookie, + set_cookie, + with_document_cookie, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + cookie_name = "foo" + cookie_value = "bar" + partition = BrowsingContextPartitionDescriptor(new_tab["context"]) + if with_document_cookie: + await add_cookie(new_tab["context"], cookie_name, cookie_value) + else: + await set_cookie( + cookie=create_cookie( + domain=domain_value(), + name=cookie_name, + value=NetworkStringValue(cookie_value), + ), + partition=partition, + ) + + result = await bidi_session.storage.delete_cookies(partition=partition) + assert result == {"partitionKey": (await get_default_partition_key(bidi_session, new_tab["context"]))} + + await assert_cookies_are_not_present(bidi_session, partition) + + +@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"]) +async def test_partition_context_iframe( + bidi_session, new_tab, inline, domain_value, domain, set_cookie +): + iframe_url = inline("
foo
", domain=domain) + page_url = inline(f"") + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=page_url, wait="complete" + ) + + contexts = await bidi_session.browsing_context.get_tree(root=new_tab["context"]) + iframe_context = contexts[0]["children"][0] + + cookie_name = "foo" + cookie_value = "bar" + frame_partition = BrowsingContextPartitionDescriptor(iframe_context["context"]) + await set_cookie( + cookie=create_cookie( + domain=domain_value(domain), + name=cookie_name, + value=NetworkStringValue(cookie_value), + ), + partition=frame_partition, + ) + + result = await bidi_session.storage.delete_cookies(partition=frame_partition) + assert result == {"partitionKey": (await get_default_partition_key(bidi_session, new_tab["context"]))} + + await assert_cookies_are_not_present(bidi_session, frame_partition) + + +@pytest.mark.parametrize( + "protocol", + [ + "http", + "https", + ], +) +async def test_partition_source_origin( + bidi_session, + new_tab, + top_context, + test_page, + inline, + domain_value, + origin, + set_cookie, + protocol, +): + url = inline("
bar
", protocol=protocol, domain="alt") + await bidi_session.browsing_context.navigate( + context=top_context["context"], url=url, wait="complete" + ) + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + cookie1_domain = domain_value(domain="alt") + cookie1_name = "foo" + cookie1_value = "bar" + cookie1_source_origin = origin(domain="alt", protocol=protocol) + cookie1_partition = StorageKeyPartitionDescriptor( + source_origin=cookie1_source_origin + ) + await set_cookie( + cookie=create_cookie( + domain=cookie1_domain, + name=cookie1_name, + value=NetworkStringValue(cookie1_value), + ), + partition=cookie1_partition, + ) + + cookie2_domain = domain_value() + cookie2_name = "bar" + cookie2_value = "foo" + cookie2_source_origin = origin() + cookie2_partition = StorageKeyPartitionDescriptor( + source_origin=cookie2_source_origin + ) + await set_cookie( + cookie=create_cookie( + domain=cookie2_domain, + name=cookie2_name, + value=NetworkStringValue(cookie2_value), + ), + partition=cookie2_partition, + ) + + result = await bidi_session.storage.delete_cookies(partition=cookie1_partition) + assert result == { + "partitionKey": { + **(await get_default_partition_key(bidi_session)), + "sourceOrigin": cookie1_source_origin + } + } + + await assert_cookies_are_not_present(bidi_session, partition=cookie1_partition) + + # Check that the second cookie is still present on another origin. + await assert_cookie_is_set( + bidi_session=bidi_session, + domain=domain_value(), + name=cookie2_name, + value={"type": "string", "value": cookie2_value}, + partition=cookie2_partition, + ) + + +@pytest.mark.parametrize( + "with_document_cookie", + [True, False], + ids=["with document cookie", "with set cookie"], +) +async def test_partition_user_context( + bidi_session, + test_page, + create_user_context, + test_page_cross_origin, + domain_value, + add_cookie, + set_cookie, + with_document_cookie, +): + user_context_1 = await create_user_context() + new_context_1 = await bidi_session.browsing_context.create( + user_context=user_context_1, type_hint="tab" + ) + await bidi_session.browsing_context.navigate( + context=new_context_1["context"], url=test_page, wait="complete" + ) + + user_context_2 = await create_user_context() + new_context_2 = await bidi_session.browsing_context.create( + user_context=user_context_2, type_hint="tab" + ) + await bidi_session.browsing_context.navigate( + context=new_context_2["context"], url=test_page_cross_origin, wait="complete" + ) + + cookie1_domain = domain_value() + cookie1_name = "foo_1" + cookie1_value = "bar_1" + cookie1_partition = StorageKeyPartitionDescriptor(user_context=user_context_1) + + cookie2_domain = domain_value(domain="alt") + cookie2_name = "foo_2" + cookie2_value = "bar_2" + cookie2_partition = StorageKeyPartitionDescriptor(user_context=user_context_2) + + if with_document_cookie: + await add_cookie( + new_context_1["context"], cookie1_name, cookie1_value, path="/" + ) + await add_cookie( + new_context_2["context"], cookie2_name, cookie2_value, path="/" + ) + else: + await set_cookie( + cookie=PartialCookie( + domain=cookie1_domain, + name=cookie1_name, + value=NetworkStringValue(cookie1_value), + ), + partition=cookie1_partition, + ) + await set_cookie( + cookie=PartialCookie( + domain=cookie2_domain, + name=cookie2_name, + value=NetworkStringValue(cookie2_value), + ), + partition=cookie2_partition, + ) + + result = await bidi_session.storage.delete_cookies( + partition=StorageKeyPartitionDescriptor(user_context=user_context_1) + ) + assert result == { + "partitionKey": { + **(await get_default_partition_key(bidi_session)), + "userContext": user_context_1 + } + } + + # Make sure that deleted cookies are not present. + await assert_cookies_are_not_present(bidi_session, partition=cookie1_partition) + + # Check that the second cookie is still present on another origin. + await assert_cookie_is_set( + bidi_session=bidi_session, + domain=cookie2_domain, + name=cookie2_name, + value={"type": "string", "value": cookie2_value}, + partition=cookie2_partition, + secure=False + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/filter.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/filter.py index b244ef86ac..efa22f7dc9 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/filter.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/filter.py @@ -2,7 +2,7 @@ import pytest from webdriver.bidi.modules.network import NetworkBase64Value, NetworkStringValue from webdriver.bidi.modules.storage import CookieFilter -from .. import create_cookie, format_expiry_string, generate_expiry_date +from .. import create_cookie, format_expiry_string, get_default_partition_key, generate_expiry_date from ... import recursive_compare pytestmark = pytest.mark.asyncio @@ -37,7 +37,9 @@ async def test_filter( filter=filter, ) - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 # Provide consistent cookies order. (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["name"]) @@ -102,7 +104,9 @@ async def test_filter_domain( filter=CookieFilter(domain=domain), ) - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 # Provide consistent cookies order. (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["name"]) @@ -191,7 +195,9 @@ async def test_filter_expiry( filter=CookieFilter(expiry=cookie1_expiry), ) - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 # Provide consistent cookies order. (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["name"]) @@ -303,7 +309,9 @@ async def test_filter_same_site( filter=CookieFilter(same_site=same_site_1), ) - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 # Provide consistent cookies order. (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["name"]) @@ -371,7 +379,9 @@ async def test_filter_secure( filter=CookieFilter(secure=secure_1), ) - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 # Provide consistent cookies order. (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["name"]) @@ -449,7 +459,9 @@ async def test_filter_path( filter=CookieFilter(path=path_1), ) - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["name"]) recursive_compare( @@ -528,7 +540,9 @@ async def test_filter_http_only( filter=CookieFilter(http_only=http_only_1), ) - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["name"]) recursive_compare( diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/invalid.py index fbd5647f30..93d0da2ac4 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/get_cookies/invalid.py @@ -153,3 +153,10 @@ async def test_params_partition_user_context_invalid_type(bidi_session, value): await bidi_session.storage.get_cookies( partition=StorageKeyPartitionDescriptor(user_context=value) ) + + +async def test_params_partition_user_context_invalid_value(bidi_session): + with pytest.raises(error.NoSuchUserContextException): + await bidi_session.storage.get_cookies( + partition=StorageKeyPartitionDescriptor(user_context="foo") + ) 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 a1c2650352..632e7ffa26 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 @@ -6,7 +6,7 @@ from webdriver.bidi.modules.storage import ( StorageKeyPartitionDescriptor, ) -from .. import create_cookie +from .. import create_cookie, get_default_partition_key from ... import recursive_compare pytestmark = pytest.mark.asyncio @@ -38,7 +38,9 @@ async def test_default_partition( cookies = await bidi_session.storage.get_cookies() - assert cookies["partitionKey"] == {} + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session)), + } assert len(cookies["cookies"]) == 2 # Provide consistent cookies order. (cookie_1, cookie_2) = sorted(cookies["cookies"], key=lambda c: c["domain"]) @@ -101,10 +103,10 @@ async def test_partition_context( partition=BrowsingContextPartitionDescriptor(new_tab["context"]) ) - # `partitionKey` here might contain `sourceOrigin` for certain browser implementation, - # so use `recursive_compare` to allow additional fields to be present. - recursive_compare({"partitionKey": {}}, cookies) - + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session, new_tab["context"])), + "userContext": "default" + } assert len(cookies["cookies"]) == 1 recursive_compare( { @@ -125,12 +127,52 @@ async def test_partition_context( partition=BrowsingContextPartitionDescriptor(new_context["context"]) ) - # `partitionKey` here might contain `sourceOrigin` for certain browser implementation, - # so use `recursive_compare` to allow additional fields to be present. - recursive_compare({"partitionKey": {}}, cookies) + assert cookies["partitionKey"] == { + **(await get_default_partition_key(bidi_session, new_context["context"])), + "userContext": user_context + } assert len(cookies["cookies"]) == 0 +async def test_partition_context_with_different_domain( + bidi_session, set_cookie, new_tab, test_page, domain_value +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + + # Set cookie on a different domain. + cookie_domain = domain_value(domain="alt") + cookie_name = "foo" + cookie_value = "bar" + partition = BrowsingContextPartitionDescriptor(new_tab["context"]) + await set_cookie( + cookie=create_cookie( + domain=cookie_domain, + name=cookie_name, + value=NetworkStringValue(cookie_value), + ), + partition=partition, + ) + + result = await bidi_session.storage.get_cookies( + partition=BrowsingContextPartitionDescriptor(new_tab["context"]) + ) + + assert result["cookies"] == [ + { + "domain": cookie_domain, + "httpOnly": False, + "name": cookie_name, + "path": "/", + "sameSite": "none", + "secure": True, + "size": 6, + "value": {"type": "string", "value": cookie_value}, + } + ] + + @pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"]) async def test_partition_context_iframe( bidi_session, new_tab, inline, domain_value, domain, set_cookie @@ -174,7 +216,7 @@ async def test_partition_context_iframe( "value": {"type": "string", "value": cookie_value}, } ], - "partitionKey": {}, + "partitionKey": {"userContext": "default"}, }, cookies, ) @@ -256,3 +298,109 @@ async def test_partition_source_origin( }, cookies, ) + + +async def test_partition_default_user_context( + bidi_session, + test_page, + domain_value, + add_cookie, +): + new_context = await bidi_session.browsing_context.create(type_hint="tab") + await bidi_session.browsing_context.navigate( + context=new_context["context"], url=test_page, wait="complete" + ) + + cookie_name = "foo" + cookie_value = "bar" + await add_cookie(new_context["context"], cookie_name, cookie_value) + + # Check that added cookies are present on the right user context. + result = await bidi_session.storage.get_cookies( + partition=StorageKeyPartitionDescriptor(user_context="default") + ) + expected_cookies = [ + { + "domain": domain_value(), + "httpOnly": False, + "name": cookie_name, + "path": "/webdriver/tests/support", + "sameSite": "none", + "secure": False, + "size": 6, + "value": {"type": "string", "value": cookie_value}, + } + ] + recursive_compare( + { + "cookies": expected_cookies, + "partitionKey": {"userContext": "default"}, + }, + result, + ) + + +async def test_partition_user_context( + bidi_session, + test_page, + domain_value, + create_user_context, + test_page_cross_origin, + add_cookie, +): + user_context_1 = await create_user_context() + new_context_1 = await bidi_session.browsing_context.create( + user_context=user_context_1, type_hint="tab" + ) + await bidi_session.browsing_context.navigate( + context=new_context_1["context"], url=test_page, wait="complete" + ) + + user_context_2 = await create_user_context() + new_context_2 = await bidi_session.browsing_context.create( + user_context=user_context_2, type_hint="tab" + ) + await bidi_session.browsing_context.navigate( + context=new_context_2["context"], url=test_page_cross_origin, wait="complete" + ) + + cookie_name = "foo_1" + cookie_value = "bar_1" + await add_cookie(new_context_1["context"], cookie_name, cookie_value) + + # Check that added cookies are present on the right user context. + result = await bidi_session.storage.get_cookies( + partition=StorageKeyPartitionDescriptor(user_context=user_context_1) + ) + expected_cookies = [ + { + "domain": domain_value(), + "httpOnly": False, + "name": cookie_name, + "path": "/webdriver/tests/support", + "sameSite": "none", + "secure": False, + "size": 10, + "value": {"type": "string", "value": cookie_value}, + } + ] + recursive_compare( + { + "cookies": expected_cookies, + "partitionKey": {"userContext": user_context_1}, + }, + result, + ) + + # Check that added cookies are not present on the other user context. + result = await bidi_session.storage.get_cookies( + partition=StorageKeyPartitionDescriptor(user_context=user_context_2) + ) + + recursive_compare( + { + "cookies": [], + "partitionKey": {"userContext": user_context_2}, + }, + result, + ) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_expiry.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_expiry.py index 4e49479a87..7aac38da69 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_expiry.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_expiry.py @@ -1,5 +1,5 @@ import pytest -from .. import assert_cookie_is_not_set, assert_cookie_is_set, create_cookie +from .. import assert_cookie_is_not_set, assert_cookie_is_set, create_cookie, get_default_partition_key from datetime import datetime, timedelta import time @@ -13,7 +13,7 @@ async def test_cookie_expiry_unset(bidi_session, set_cookie, test_page, domain_v expiry=None)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } await assert_cookie_is_set(bidi_session, expiry=None, domain=domain_value()) @@ -29,7 +29,7 @@ async def test_cookie_expiry_future(bidi_session, set_cookie, test_page, domain_ expiry=tomorrow_timestamp)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } await assert_cookie_is_set(bidi_session, expiry=tomorrow_timestamp, domain=domain_value()) @@ -45,7 +45,7 @@ async def test_cookie_expiry_past(bidi_session, set_cookie, test_page, domain_va expiry=yesterday_timestamp)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } await assert_cookie_is_not_set(bidi_session) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_http_only.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_http_only.py index 4473fbf576..b2155d1ac2 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_http_only.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_http_only.py @@ -1,5 +1,5 @@ import pytest -from .. import assert_cookie_is_set, create_cookie +from .. import assert_cookie_is_set, create_cookie, get_default_partition_key pytestmark = pytest.mark.asyncio @@ -16,7 +16,7 @@ async def test_cookie_http_only(bidi_session, set_cookie, test_page, domain_valu cookie=create_cookie(domain=domain_value(), http_only=http_only)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } # `httpOnly` defaults to `false`. diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_path.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_path.py index 727d24348a..70084dee6e 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_path.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_path.py @@ -1,5 +1,5 @@ import pytest -from .. import assert_cookie_is_set, create_cookie +from .. import assert_cookie_is_set, create_cookie, get_default_partition_key pytestmark = pytest.mark.asyncio @@ -17,7 +17,7 @@ async def test_cookie_path(bidi_session, test_page, set_cookie, domain_value, pa set_cookie_result = await set_cookie(cookie=create_cookie(domain=domain_value(), path=path)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } # `path` defaults to "/". diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_same_site.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_same_site.py index dfc94c5727..27640bb9a6 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_same_site.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_same_site.py @@ -1,5 +1,5 @@ import pytest -from .. import assert_cookie_is_set, create_cookie +from .. import assert_cookie_is_set, create_cookie, get_default_partition_key pytestmark = pytest.mark.asyncio @@ -18,7 +18,7 @@ async def test_cookie_secure(bidi_session, set_cookie, test_page, domain_value, cookie=create_cookie(domain=domain_value(), same_site=same_site)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } # `same_site` defaults to "none". diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_secure.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_secure.py index ef1060cb46..81e462c87c 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_secure.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/cookie_secure.py @@ -1,5 +1,5 @@ import pytest -from .. import assert_cookie_is_set, create_cookie +from .. import assert_cookie_is_set, create_cookie, get_default_partition_key pytestmark = pytest.mark.asyncio @@ -17,7 +17,7 @@ async def test_cookie_secure(bidi_session, set_cookie, test_page, domain_value, cookie=create_cookie(domain=domain_value(), secure=secure)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } # `secure` defaults to `false`. diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/invalid.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/invalid.py index 53d2573575..9962d303a1 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/invalid.py @@ -122,5 +122,9 @@ async def test_partition_storage_key_user_context_invalid_type(set_cookie, test_ with pytest.raises(error.InvalidArgumentException): await set_cookie(cookie=create_cookie(domain=domain_value()), partition=partition) -# TODO: test `test_partition_storage_key_user_context_unknown`. -# TODO: test `test_partition_storage_key_user_context_invalid_type`. + +async def test_partition_storage_key_user_context_invalid_value(set_cookie, domain_value): + partition = StorageKeyPartitionDescriptor(user_context="foo") + + with pytest.raises(error.NoSuchUserContextException): + await set_cookie(cookie=create_cookie(domain=domain_value()), partition=partition) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/page_protocols.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/page_protocols.py index 4cb712b372..295b09c10e 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/page_protocols.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/page_protocols.py @@ -1,6 +1,6 @@ import pytest from urllib.parse import urlparse -from .. import assert_cookie_is_set, create_cookie +from .. import assert_cookie_is_set, create_cookie, get_default_partition_key pytestmark = pytest.mark.asyncio @@ -18,7 +18,7 @@ async def test_page_protocols(bidi_session, set_cookie, get_test_page, protocol) set_cookie_result = await set_cookie(cookie=create_cookie(domain=domain)) assert set_cookie_result == { - 'partitionKey': {}, + 'partitionKey': (await get_default_partition_key(bidi_session)), } # Assert the cookie is actually set. diff --git a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/partition.py b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/partition.py index cb0ace1f40..bb171c6141 100644 --- a/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/partition.py +++ b/testing/web-platform/tests/webdriver/tests/bidi/storage/set_cookie/partition.py @@ -1,5 +1,10 @@ import pytest -from webdriver.bidi.modules.storage import BrowsingContextPartitionDescriptor, StorageKeyPartitionDescriptor +from webdriver.bidi.modules.network import NetworkStringValue +from webdriver.bidi.modules.script import ContextTarget +from webdriver.bidi.modules.storage import ( + BrowsingContextPartitionDescriptor, + StorageKeyPartitionDescriptor, +) from .. import assert_cookie_is_set, create_cookie from ... import recursive_compare @@ -14,7 +19,7 @@ def assert_set_cookie_result(set_cookie_result, partition): # Browsing context does not require a `sourceOrigin` partition key, but it can be present depending on the # browser implementation. # `recursive_compare` allows the actual result to be any extension of the expected one. - recursive_compare({'partitionKey': {}, }, set_cookie_result) + recursive_compare({'partitionKey': {"userContext": "default"}, }, set_cookie_result) return if isinstance(partition, StorageKeyPartitionDescriptor): expected_partition_key = {} @@ -31,13 +36,33 @@ def assert_set_cookie_result(set_cookie_result, partition): async def test_partition_context(bidi_session, set_cookie, top_context, test_page, domain_value): await bidi_session.browsing_context.navigate(context=top_context["context"], url=test_page, wait="complete") + cookie_name = "foo" + cookie_value = "bar" partition = BrowsingContextPartitionDescriptor(top_context["context"]) set_cookie_result = await set_cookie( - cookie=create_cookie(domain=domain_value()), - partition=partition) + cookie=create_cookie( + domain=domain_value(), + name=cookie_name, + value=NetworkStringValue(cookie_value), + ), + partition=partition, + ) assert_set_cookie_result(set_cookie_result, partition) - await assert_cookie_is_set(bidi_session, domain=domain_value()) + await assert_cookie_is_set( + bidi_session, + domain=domain_value(), + name=cookie_name, + value=NetworkStringValue(cookie_value) + ) + + result = await bidi_session.script.evaluate( + expression="document.cookie", + target=ContextTarget(top_context["context"]), + await_promise=True, + ) + + assert result == {"type": "string", "value": f"{cookie_name}={cookie_value}"} async def test_partition_context_frame(bidi_session, set_cookie, top_context, test_page, domain_value, inline): @@ -75,4 +100,19 @@ async def test_partition_storage_key_source_origin(bidi_session, set_cookie, tes await assert_cookie_is_set(bidi_session, domain=domain_value(), partition=partition) -# TODO: test `test_partition_storage_key_user_context`. + +async def test_partition_user_context( + bidi_session, + domain_value, + create_user_context, + set_cookie +): + user_context_1 = await create_user_context() + + partition = StorageKeyPartitionDescriptor(user_context=user_context_1) + set_cookie_result = await set_cookie( + cookie=create_cookie(domain=domain_value()), + partition=partition) + assert_set_cookie_result(set_cookie_result, partition) + + await assert_cookie_is_set(bidi_session, domain=domain_value(), partition=partition) diff --git a/testing/web-platform/tests/webdriver/tests/classic/new_session/response.py b/testing/web-platform/tests/webdriver/tests/classic/new_session/response.py index 43a8d57931..fa8d56c449 100644 --- a/testing/web-platform/tests/webdriver/tests/classic/new_session/response.py +++ b/testing/web-platform/tests/webdriver/tests/classic/new_session/response.py @@ -42,3 +42,10 @@ def test_capability_default_value(session, capability, default_value): assert isinstance(session.capabilities, dict) assert capability in session.capabilities assert session.capabilities[capability] == default_value + + +def test_capability_user_agent(session): + assert isinstance(session.capabilities, dict) + assert "userAgent" in session.capabilities + assert type(session.capabilities["userAgent"]) == str + assert len(session.capabilities["userAgent"]) > 0 diff --git a/testing/web-platform/tests/webdriver/tests/classic/new_window/new_tab.py b/testing/web-platform/tests/webdriver/tests/classic/new_window/new_tab.py index f6cacf3c35..53810e7fb6 100644 --- a/testing/web-platform/tests/webdriver/tests/classic/new_window/new_tab.py +++ b/testing/web-platform/tests/webdriver/tests/classic/new_window/new_tab.py @@ -1,4 +1,5 @@ from tests.support.asserts import assert_success +from tests.support.sync import Poll from . import opener, window_name @@ -63,7 +64,7 @@ def test_sets_no_opener(session): assert opener(session) is None -def test_focus_content(session, inline): +def test_initial_selection_for_contenteditable(session, inline): response = new_window(session, type_hint="tab") value = assert_success(response) assert value["type"] == "tab" @@ -71,19 +72,26 @@ def test_focus_content(session, inline): session.window_handle = value["handle"] session.url = inline(""" - abc +
abc
""") - elem = session.find.css("span", all=False) - assert elem.attribute("_focused") == "true" + elem = session.find.css("div", all=False) + + wait = Poll( + session, + timeout=5, + message="Initial selection for contenteditable not set") + wait.until(lambda _: elem.attribute("_focused") == "true") diff --git a/testing/web-platform/tests/webdriver/tests/classic/new_window/new_window.py b/testing/web-platform/tests/webdriver/tests/classic/new_window/new_window.py index d47dacdc08..cc10d2fb86 100644 --- a/testing/web-platform/tests/webdriver/tests/classic/new_window/new_window.py +++ b/testing/web-platform/tests/webdriver/tests/classic/new_window/new_window.py @@ -1,4 +1,5 @@ from tests.support.asserts import assert_success +from tests.support.sync import Poll from . import opener, window_name @@ -65,26 +66,33 @@ def test_sets_no_opener(session): assert opener(session) is None -def test_focus_content(session, inline): +def test_initial_selection_for_contenteditable(session, inline): response = new_window(session, type_hint="window") value = assert_success(response) session.window_handle = value["handle"] session.url = inline(""" - abc +
abc
""") - elem = session.find.css("span", all=False) - assert elem.attribute("_focused") == "true" + elem = session.find.css("div", all=False) + + wait = Poll( + session, + timeout=5, + message="Initial selection for contenteditable not set") + wait.until(lambda _: elem.attribute("_focused") == "true") 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 9566e6ebd1..7f3e4f9a9a 100644 --- a/testing/web-platform/tests/webdriver/tests/support/fixtures_bidi.py +++ b/testing/web-platform/tests/webdriver/tests/support/fixtures_bidi.py @@ -198,7 +198,7 @@ def add_and_remove_iframe(bidi_session): document.documentElement.lastElementChild.append(iframe); return new Promise(resolve => iframe.onload = () => resolve(id)); }""", - target={"context": context["context"]}, + target=ContextTarget(context["context"]), await_promise=True) iframe_dom_id = resp["value"] @@ -210,7 +210,7 @@ def add_and_remove_iframe(bidi_session): await bidi_session.script.evaluate( expression=f"document.getElementById('{iframe_dom_id}').remove()", - target={"context": context["context"]}, + target=ContextTarget(context["context"]), await_promise=False) return frame_id diff --git a/testing/web-platform/tests/webdriver/tests/support/html/files.html b/testing/web-platform/tests/webdriver/tests/support/html/files.html new file mode 100644 index 0000000000..be24791844 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/support/html/files.html @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/webdriver/tests/support/http_handlers/cached.py b/testing/web-platform/tests/webdriver/tests/support/http_handlers/cached.py index a43410f885..ce1dadefa1 100644 --- a/testing/web-platform/tests/webdriver/tests/support/http_handlers/cached.py +++ b/testing/web-platform/tests/webdriver/tests/support/http_handlers/cached.py @@ -8,7 +8,14 @@ def main(request, response): response.headers.set(b"Location", request.GET.first(b"location")) response.status = status - response.headers.set(b"Content-Type", "text/plain") + + + if b"contenttype" in request.GET: + content_type = request.GET.first(b"contenttype") + response.headers.set(b"Content-Type", content_type) + else: + response.headers.set(b"Content-Type", "text/plain") + response.headers.set(b"Expires", "Thu, 01 Dec 2100 20:00:00 GMT") response.headers.set(b"Cache-Control", "max-age=3600") return "Cached HTTP Response" -- cgit v1.2.3