diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/mozilla/tests/webdriver/bidi | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/mozilla/tests/webdriver/bidi')
38 files changed, 1319 insertions, 0 deletions
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browser/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browser/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browser/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browser/close/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browser/close/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browser/close/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browser/close/close.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browser/close/close.py new file mode 100644 index 0000000000..a7197a7d0d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browser/close/close.py @@ -0,0 +1,36 @@ +import pytest + +pytestmark = pytest.mark.asyncio + + +async def test_close_browser(new_session, add_browser_capabilities): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + + await bidi_session.browser.close() + + # Wait for the browser to actually close. + bidi_session.current_browser.wait() + + assert bidi_session.current_browser.is_running is False + + +async def test_start_session_again(new_session, add_browser_capabilities): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + first_session_id = bidi_session.session_id + + await bidi_session.browser.close() + + # Wait for the browser to actually close. + bidi_session.current_browser.wait() + + # Try to create a session again. + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + + assert isinstance(bidi_session.session_id, str) + assert first_session_id != bidi_session.session_id diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/__init__.py new file mode 100644 index 0000000000..910b202075 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/__init__.py @@ -0,0 +1,20 @@ +import contextlib + + +def set_context(session, context): + session.send_session_command("POST", "moz/context", {"context": context}) + + +@contextlib.contextmanager +def using_context(session, context): + orig_context = session.send_session_command("GET", "moz/context") + needs_change = context != orig_context + + if needs_change: + set_context(session, context) + + try: + yield + finally: + if needs_change: + set_context(session, orig_context) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/reference_context.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/reference_context.py new file mode 100644 index 0000000000..1a5906339b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/reference_context.py @@ -0,0 +1,72 @@ +import pytest + +from . import using_context + +pytestmark = pytest.mark.asyncio + + +# Helper to assert the order of top level browsing contexts. +# The window used for the assertion is inferred from the first context id of +# expected_context_ids. +def assert_tab_order(session, expected_context_ids): + with using_context(session, "chrome"): + context_ids = session.execute_script( + """ + const contextId = arguments[0]; + const { TabManager } = + ChromeUtils.importESModule("chrome://remote/content/shared/TabManager.sys.mjs"); + const browsingContext = TabManager.getBrowsingContextById(contextId); + const chromeWindow = browsingContext.embedderElement.ownerGlobal; + const tabBrowser = TabManager.getTabBrowser(chromeWindow); + return tabBrowser.browsers.map(browser => TabManager.getIdForBrowser(browser)); + """, + args=(expected_context_ids[0],), + ) + + assert context_ids == expected_context_ids + + +async def test_reference_context(bidi_session, current_session): + # Create a new window with a tab tab1 + result = await bidi_session.browsing_context.create(type_hint="window") + tab1_context_id = result["context"] + + # Create a second window with a tab tab2 + result = await bidi_session.browsing_context.create(type_hint="window") + tab2_context_id = result["context"] + + # Create a new tab tab3 next to tab1 + result = await bidi_session.browsing_context.create( + type_hint="tab", reference_context=tab1_context_id + ) + tab3_context_id = result["context"] + + # Create a new tab tab4 next to tab2 + result = await bidi_session.browsing_context.create( + type_hint="tab", reference_context=tab2_context_id + ) + tab4_context_id = result["context"] + + # Create a new tab tab5 also next to tab2 (should consequently be between + # tab2 and tab4) + result = await bidi_session.browsing_context.create( + type_hint="tab", reference_context=tab2_context_id + ) + tab5_context_id = result["context"] + + # Create a new window, but pass a reference_context from an existing window. + # The reference context is expected to be ignored here. + result = await bidi_session.browsing_context.create( + type_hint="window", reference_context=tab2_context_id + ) + tab6_context_id = result["context"] + + # We expect 3 windows in total, with a specific tab order: + # - the first window should contain tab1, tab3 + assert_tab_order(current_session, [tab1_context_id, tab3_context_id]) + # - the second window should contain tab2, tab5, tab4 + assert_tab_order( + current_session, [tab2_context_id, tab5_context_id, tab4_context_id] + ) + # - the third window should contain tab6 + assert_tab_order(current_session, [tab6_context_id]) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/type_hint.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/type_hint.py new file mode 100644 index 0000000000..337a03b3dd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/type_hint.py @@ -0,0 +1,31 @@ +import pytest +from tests.support.asserts import assert_success + +from . import using_context + +pytestmark = pytest.mark.asyncio + + +def count_window_handles(session): + with using_context(session, "chrome"): + response = session.transport.send( + "GET", "session/{session_id}/window/handles".format(**vars(session)) + ) + chrome_handles = assert_success(response) + return len(chrome_handles) + + +@pytest.mark.parametrize("type_hint", ["tab", "window"]) +async def test_type_hint(bidi_session, current_session, type_hint): + assert len(await bidi_session.browsing_context.get_tree()) == 1 + assert count_window_handles(current_session) == 1 + + await bidi_session.browsing_context.create(type_hint=type_hint) + + if type_hint == "window": + expected_window_count = 2 + else: + expected_window_count = 1 + + assert len(await bidi_session.browsing_context.get_tree()) == 2 + assert count_window_handles(current_session) == expected_window_count diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/error.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/error.py new file mode 100644 index 0000000000..374359d1ae --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/error.py @@ -0,0 +1,48 @@ +import os +from copy import deepcopy + +import pytest +from tests.bidi.browsing_context.navigate import navigate_and_assert + +pytestmark = pytest.mark.asyncio + + +async def test_insecure_certificate(configuration, url, custom_profile, geckodriver): + try: + # Create a new profile and remove the certificate storage so that + # loading a HTTPS page will cause an insecure certificate error + os.remove(os.path.join(custom_profile.profile, "cert9.db")) + except Exception: + pass + + config = deepcopy(configuration) + config["capabilities"]["moz:firefoxOptions"]["args"] = [ + "--profile", + custom_profile.profile, + ] + # Capability matching not implemented yet for WebDriver BiDi (bug 1713784) + config["capabilities"]["acceptInsecureCerts"] = False + config["capabilities"]["webSocketUrl"] = True + + driver = geckodriver(config=config) + driver.new_session() + + bidi_session = driver.session.bidi_session + await bidi_session.start() + + contexts = await bidi_session.browsing_context.get_tree(max_depth=0) + await navigate_and_assert( + bidi_session, + contexts[0], + url("/common/blank.html", protocol="https"), + expected_error=True, + ) + + +async def test_invalid_content_encoding(bidi_session, new_tab, inline): + await navigate_and_assert( + bidi_session, + new_tab, + f"{inline('<div>foo')}&pipe=header(Content-Encoding,gzip)", + expected_error=True, + ) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/invalid.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/invalid.py new file mode 100644 index 0000000000..b837b86416 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/invalid.py @@ -0,0 +1,19 @@ +import pytest +from webdriver.bidi import error + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize( + "viewport", + [ + {"width": 10000001, "height": 100}, + {"width": 100, "height": 10000001}, + ], + ids=["width exceeded", "height exceeded"], +) +async def test_params_viewport_invalid_value(bidi_session, new_tab, viewport): + with pytest.raises(error.UnsupportedOperationException): + await bidi_session.browsing_context.set_viewport( + context=new_tab["context"], viewport=viewport + ) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/viewport.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/viewport.py new file mode 100644 index 0000000000..ef48ad2926 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/viewport.py @@ -0,0 +1,18 @@ +import pytest + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize( + "viewport", + [ + {"width": 10000000, "height": 100}, + {"width": 100, "height": 10000000}, + {"width": 10000000, "height": 10000000}, + ], + ids=["maximal width", "maximal height", "maximal width and height"], +) +async def test_params_viewport_max_value(bidi_session, new_tab, viewport): + await bidi_session.browsing_context.set_viewport( + context=new_tab["context"], viewport=viewport + ) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/conftest.py b/testing/web-platform/mozilla/tests/webdriver/bidi/conftest.py new file mode 100644 index 0000000000..4bd63c8df7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/conftest.py @@ -0,0 +1,93 @@ +import pytest +import pytest_asyncio +from webdriver.bidi.client import BidiSession + + +@pytest.fixture +def match_capabilities(add_browser_capabilities): + def match_capabilities(match_type, capability_key, capability_value): + capability = {} + capability[capability_key] = capability_value + capabilities = add_browser_capabilities(capability) + if match_type == "firstMatch": + capabilities = [capabilities] + + capabilities_params = {} + capabilities_params[match_type] = capabilities + + return capabilities_params + + return match_capabilities + + +@pytest_asyncio.fixture +async def bidi_client(browser): + bidi_session = None + current_browser = browser(use_bidi=True) + + async def bidi_client(capabilities={}): + nonlocal current_browser + + # Launch the browser again if it's not running. + if current_browser.is_running is False: + current_browser = browser(use_bidi=True) + + server_host = current_browser.remote_agent_host + server_port = current_browser.remote_agent_port + + nonlocal bidi_session + + bidi_session = BidiSession.bidi_only( + f"ws://{server_host}:{server_port}", requested_capabilities=capabilities + ) + bidi_session.current_browser = current_browser + + await bidi_session.start_transport() + + return bidi_session + + yield bidi_client + + if bidi_session is not None: + await bidi_session.end() + + +@pytest_asyncio.fixture +async def new_session(bidi_client): + """Start bidi client and create a new session. + At the moment, it throws an error if the session was already started, + since multiple sessions are not supported. + """ + bidi_session = None + + async def new_session(capabilities): + nonlocal bidi_session + + bidi_session = await bidi_client(capabilities) + await bidi_session.start() + + return bidi_session + + yield new_session + + # Check if the browser, the session or websocket connection was not closed already. + if ( + bidi_session is not None + and bidi_session.current_browser.is_running is True + and bidi_session.session_id is not None + and bidi_session.transport.connection.closed is False + ): + await bidi_session.session.end() + + +@pytest.fixture(name="add_browser_capabilities") +def fixture_add_browser_capabilities(configuration): + def add_browser_capabilities(capabilities): + # Make sure there aren't keys in common. + assert not set(configuration["capabilities"]).intersection(set(capabilities)) + result = dict(configuration["capabilities"]) + result.update(capabilities) + + return result + + return add_browser_capabilities diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/errors/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/errors/errors.py b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/errors.py new file mode 100644 index 0000000000..69b1f2fb7a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/errors.py @@ -0,0 +1,8 @@ +import pytest +from webdriver.bidi.error import UnknownCommandException + + +@pytest.mark.asyncio +async def test_internal_method(bidi_session, send_blocking_command): + with pytest.raises(UnknownCommandException): + await send_blocking_command("log._applySessionData", {}) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/interface/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/interface/interface.py b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/interface.py new file mode 100644 index 0000000000..c7924ca851 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/interface.py @@ -0,0 +1,26 @@ +import pytest +from webdriver.bidi.client import BidiSession +from webdriver.bidi.modules.script import ContextTarget + +pytestmark = pytest.mark.asyncio + + +async def test_navigator_webdriver_enabled(inline, browser): + # Request a new browser with only WebDriver BiDi and not Marionette/CDP enabled. + current_browser = browser(use_bidi=True, extra_prefs={"remote.active-protocols": 1}) + server_host = current_browser.remote_agent_host + server_port = current_browser.remote_agent_port + + async with BidiSession.bidi_only( + f"ws://{server_host}:{server_port}", requested_capabilities={"alwaysMatch": {}} + ) as bidi_session: + contexts = await bidi_session.browsing_context.get_tree(max_depth=0) + assert len(contexts) > 0 + + result = await bidi_session.script.evaluate( + expression="navigator.webdriver", + target=ContextTarget(contexts[0]["context"]), + await_promise=False, + ) + + assert result == {"type": "boolean", "value": True} diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/script/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/script/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/script/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/script/exception_details.py b/testing/web-platform/mozilla/tests/webdriver/bidi/script/exception_details.py new file mode 100644 index 0000000000..2af2d5d24f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/script/exception_details.py @@ -0,0 +1,61 @@ +import pytest +from webdriver.bidi.modules.script import ContextTarget, ScriptEvaluateResultException + + +@pytest.mark.asyncio +@pytest.mark.parametrize("await_promise", [True, False]) +@pytest.mark.parametrize( + "expression", + [ + "null", + "{ toString: 'not a function' }", + "{ toString: () => {{ throw 'toString not allowed'; }} }", + "{ toString: () => true }", + ], +) +@pytest.mark.asyncio +async def test_call_function_without_to_string_interface( + bidi_session, top_context, await_promise, expression +): + function_declaration = "()=>{throw { toString: 'not a function' } }" + if await_promise: + function_declaration = "async" + function_declaration + + with pytest.raises(ScriptEvaluateResultException) as exception: + await bidi_session.script.call_function( + function_declaration=function_declaration, + await_promise=await_promise, + target=ContextTarget(top_context["context"]), + ) + + assert isinstance(exception.value.text, str) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("await_promise", [True, False]) +@pytest.mark.parametrize( + "expression", + [ + "null", + "{ toString: 'not a function' }", + "{ toString: () => {{ throw 'toString not allowed'; }} }", + "{ toString: () => true }", + ], +) +@pytest.mark.asyncio +async def test_evaluate_without_to_string_interface( + bidi_session, top_context, await_promise, expression +): + if await_promise: + expression = f"Promise.reject({expression})" + else: + expression = f"throw {expression}" + + with pytest.raises(ScriptEvaluateResultException) as exception: + await bidi_session.script.evaluate( + expression=expression, + await_promise=await_promise, + target=ContextTarget(top_context["context"]), + ) + + assert isinstance(exception.value.text, str) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/end.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/end.py new file mode 100644 index 0000000000..f1f9c84263 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/end.py @@ -0,0 +1,53 @@ +import pytest +from webdriver.bidi.error import InvalidSessionIDError + +pytestmark = pytest.mark.asyncio + + +async def test_session_end(new_session, add_browser_capabilities, bidi_client): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + + await bidi_session.session.end() + + # Connect the client again. + not_active_bidi_session = await bidi_client() + response = await not_active_bidi_session.session.status() + + # Make sure that session can be created. + assert response["ready"] is True + + +async def test_start_session_again(new_session, add_browser_capabilities): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + first_session_id = bidi_session.session_id + + await bidi_session.session.end() + + # Try to create a session again + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + + assert isinstance(bidi_session.session_id, str) + assert first_session_id != bidi_session.session_id + + +async def test_send_the_command_after_session_end( + new_session, add_browser_capabilities, bidi_client +): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + + await bidi_session.session.end() + + # Connect the client again. + not_active_bidi_session = await bidi_client() + + # Make sure that command will fail, since the session was closed. + with pytest.raises(InvalidSessionIDError): + await not_active_bidi_session.browsing_context.create(type_hint="tab") diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/invalid.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/invalid.py new file mode 100644 index 0000000000..1ffe57c615 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/end/invalid.py @@ -0,0 +1,15 @@ +import pytest +from webdriver.bidi.error import InvalidSessionIDError + +pytestmark = pytest.mark.asyncio + + +async def test_without_session(bidi_client): + # Connect the client. + bidi_session = await bidi_client() + response = await bidi_session.session.status() + + assert response["ready"] is True + + with pytest.raises(InvalidSessionIDError): + await bidi_session.session.end() diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/always_match.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/always_match.py new file mode 100644 index 0000000000..50f1314a47 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/always_match.py @@ -0,0 +1,18 @@ +# META: timeout=long + +import pytest + +from bidi.session.new.support.test_data import flat_valid_data + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize("key,value", flat_valid_data) +async def test_valid(new_session, add_browser_capabilities, key, value): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({key: value})} + ) + + assert bidi_session.capabilities is not None + if value is not None: + assert key in bidi_session.capabilities diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/capabilities.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/capabilities.py new file mode 100644 index 0000000000..f709198eca --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/capabilities.py @@ -0,0 +1,51 @@ +import pytest +from tests.support import platform_name +from webdriver.bidi.modules.script import ContextTarget + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.skipif( + platform_name is None, reason="Unsupported platform {}".format(platform_name) +) +@pytest.mark.parametrize("match_type", ["alwaysMatch", "firstMatch"]) +async def test_platform_name(new_session, match_capabilities, match_type): + capabilities = match_capabilities(match_type, "platformName", platform_name) + + bidi_session = await new_session(capabilities=capabilities) + + assert bidi_session.capabilities["platformName"] == platform_name + + +@pytest.mark.parametrize("match_type", ["alwaysMatch", "firstMatch"]) +async def test_proxy( + new_session, match_capabilities, server_config, inline, match_type +): + domain = server_config["domains"][""][""] + port = server_config["ports"]["http"][0] + proxy_url = f"{domain}:{port}" + proxy_capability = {"proxyType": "manual", "httpProxy": proxy_url} + capabilities = match_capabilities(match_type, "proxy", proxy_capability) + + bidi_session = await new_session(capabilities=capabilities) + + assert bidi_session.capabilities["proxy"] == proxy_capability + + page_content = "proxy" + page_url = inline(f"<div>{page_content}</div>") + test_url = page_url.replace(proxy_url, "example.com") + + contexts = await bidi_session.browsing_context.get_tree() + + await bidi_session.browsing_context.navigate( + context=contexts[0]["context"], url=test_url, wait="complete" + ) + + # Check that content is expected + response = await bidi_session.script.evaluate( + expression="""document.querySelector('div').textContent""", + target=ContextTarget(contexts[0]["context"]), + await_promise=False, + ) + + assert response == {"type": "string", "value": page_content} diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/first_match.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/first_match.py new file mode 100644 index 0000000000..2e7fd00607 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/first_match.py @@ -0,0 +1,18 @@ +# META: timeout=long + +import pytest + +from bidi.session.new.support.test_data import flat_valid_data + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize("key,value", flat_valid_data) +async def test_valid(new_session, add_browser_capabilities, key, value): + bidi_session = await new_session( + capabilities={"firstMatch": [add_browser_capabilities({key: value})]} + ) + + assert bidi_session.capabilities is not None + if value is not None: + assert key in bidi_session.capabilities diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/invalid.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/invalid.py new file mode 100644 index 0000000000..8736933631 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/invalid.py @@ -0,0 +1,66 @@ +import pytest +from webdriver.bidi.error import InvalidArgumentException + +from bidi.session.new.support.test_data import flat_invalid_data, invalid_extensions + +pytestmark = pytest.mark.asyncio + + +@pytest.mark.parametrize("value", [None, True, 1, "{}", []]) +async def test_params_capabilities_invalid_type(new_session, value): + with pytest.raises(InvalidArgumentException): + await new_session(capabilities=value) + + +@pytest.mark.parametrize("value", [True, 1, "{}", []]) +async def test_params_always_match_invalid_type(new_session, value): + with pytest.raises(InvalidArgumentException): + await new_session(capabilities={"alwaysMatch": value}) + + +@pytest.mark.parametrize("value", [True, 1, "{}", {}, []]) +async def test_params_first_match_invalid_type(new_session, value): + with pytest.raises(InvalidArgumentException): + await new_session(capabilities={"firstMatch": value}) + + +@pytest.mark.parametrize("value", [True, 1, "{}", None, []]) +async def test_params_first_match_item_invalid_type(new_session, value): + with pytest.raises(InvalidArgumentException): + await new_session(capabilities={"firstMatch": [value]}) + + +@pytest.mark.parametrize("match_type", ["alwaysMatch", "firstMatch"]) +@pytest.mark.parametrize("key,value", flat_invalid_data) +async def test_invalid_value(new_session, match_capabilities, match_type, key, value): + capabilities = match_capabilities(match_type, key, value) + + with pytest.raises(InvalidArgumentException): + await new_session(capabilities=capabilities) + + +@pytest.mark.parametrize("match_type", ["alwaysMatch", "firstMatch"]) +@pytest.mark.parametrize("key", invalid_extensions) +async def test_invalid_extension(new_session, match_capabilities, match_type, key): + capabilities = match_capabilities(match_type, key, {}) + + with pytest.raises(InvalidArgumentException): + await new_session(capabilities=capabilities) + + +@pytest.mark.parametrize("match_type", ["alwaysMatch", "firstMatch"]) +async def test_invalid_moz_extension(new_session, match_capabilities, match_type): + capabilities = match_capabilities(match_type, "moz:someRandomString", {}) + + with pytest.raises(InvalidArgumentException): + await new_session(capabilities=capabilities) + + +async def test_params_with_shadowed_value(new_session): + with pytest.raises(InvalidArgumentException): + await new_session( + capabilities={ + "firstMatch": [{"acceptInsecureCerts": True}], + "alwaysMatch": {"acceptInsecureCerts": True}, + } + ) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/response.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/response.py new file mode 100644 index 0000000000..c635b7c93f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/response.py @@ -0,0 +1,84 @@ +# META: timeout=long + +import uuid + +import pytest + +pytestmark = pytest.mark.asyncio + + +async def test_session_id(new_session, add_browser_capabilities): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + assert isinstance(bidi_session.session_id, str) + uuid.UUID(hex=bidi_session.session_id) + + +async def test_capability_type(new_session, add_browser_capabilities): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + + default_capability_types = [ + ("acceptInsecureCerts", bool), + ("browserName", str), + ("browserVersion", str), + ("platformName", str), + ("proxy", dict), + ("setWindowRect", bool), + ] + + assert isinstance(bidi_session.capabilities, dict) + + for capability, type in default_capability_types: + assert isinstance(bidi_session.capabilities[capability], type) + + +async def test_capability_default_value(new_session, add_browser_capabilities): + bidi_session = await new_session( + capabilities={"alwaysMatch": add_browser_capabilities({})} + ) + assert isinstance(bidi_session.capabilities, dict) + + default_capability_values = [ + ("acceptInsecureCerts", False), + ("proxy", {}), + ] + + for capability, value in default_capability_values: + assert bidi_session.capabilities[capability] == value + + +async def test_ignore_non_spec_fields_in_capabilities( + new_session, add_browser_capabilities +): + bidi_session = await new_session( + capabilities={ + "alwaysMatch": add_browser_capabilities({}), + "nonSpecCapabilities": {"acceptInsecureCerts": True}, + } + ) + + assert bidi_session.capabilities["acceptInsecureCerts"] is False + + +@pytest.mark.parametrize("match_type", ["alwaysMatch", "firstMatch"]) +@pytest.mark.parametrize( + "key, value", + [ + ("pageLoadStrategy", "none"), + ("strictFileInteractability", True), + ("timeouts", {"script": 500}), + ("unhandledPromptBehavior", "accept"), + ], +) +async def test_with_webdriver_classic_capabilities( + new_session, match_capabilities, match_type, key, value +): + capabilities = match_capabilities(match_type, key, value) + + bidi_session = await new_session(capabilities=capabilities) + + assert isinstance(bidi_session.capabilities, dict) + assert key not in bidi_session.capabilities diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/support/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/support/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/support/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/support/test_data.py b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/support/test_data.py new file mode 100644 index 0000000000..7a2b41a06e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/session/new/support/test_data.py @@ -0,0 +1,143 @@ +def product(a, b): + return [(a, item) for item in b] + + +def flatten(l): + return [item for x in l for item in x] + + +# Note that we can only test things here all implementations must support +valid_data = [ + ( + "acceptInsecureCerts", + [ + False, + None, + ], + ), + ( + "browserName", + [ + None, + ], + ), + ( + "browserVersion", + [ + None, + ], + ), + ( + "platformName", + [ + None, + ], + ), + ( + "proxy", + [ + None, + ], + ), + ( + "test:extension", + [ + None, + False, + "abc", + 123, + [], + {"key": "value"}, + ], + ), +] + +flat_valid_data = flatten(product(*item) for item in valid_data) + +invalid_data = [ + ( + "acceptInsecureCerts", + [ + 1, + [], + {}, + "false", + ], + ), + ( + "browserName", + [ + 1, + [], + {}, + False, + ], + ), + ( + "browserVersion", + [ + 1, + [], + {}, + False, + ], + ), + ( + "platformName", + [ + 1, + [], + {}, + False, + ], + ), + ( + "proxy", + [ + 1, + [], + "{}", + {"proxyType": "SYSTEM"}, + {"proxyType": "systemSomething"}, + {"proxy type": "pac"}, + {"proxy-Type": "system"}, + {"proxy_type": "system"}, + {"proxytype": "system"}, + {"PROXYTYPE": "system"}, + {"proxyType": None}, + {"proxyType": 1}, + {"proxyType": []}, + {"proxyType": {"value": "system"}}, + {" proxyType": "system"}, + {"proxyType ": "system"}, + {"proxyType ": " system"}, + {"proxyType": "system "}, + ], + ), +] + +flat_invalid_data = flatten(product(*item) for item in invalid_data) + +invalid_extensions = [ + "automaticInspection", + "automaticProfiling", + "browser", + "chromeOptions", + "ensureCleanSession", + "firefox", + "firefox_binary", + "firefoxOptions", + "initialBrowserUrl", + "javascriptEnabled", + "logFile", + "logLevel", + "nativeEvents", + "platform", + "platformVersion", + "profile", + "requireWindowFocus", + "safari.options", + "seleniumProtocol", + "trustAllSSLCertificates", + "version", +] diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/storage/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/storage/get_cookies/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/get_cookies/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/get_cookies/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/storage/get_cookies/partition.py b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/get_cookies/partition.py new file mode 100644 index 0000000000..b037c30038 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/get_cookies/partition.py @@ -0,0 +1,131 @@ +import pytest +from tests.bidi import recursive_compare +from tests.support.helpers import get_origin_from_url +from webdriver.bidi.modules.storage import BrowsingContextPartitionDescriptor + +pytestmark = pytest.mark.asyncio + + +async def test_partition_context( + bidi_session, + new_tab, + test_page, + domain_value, + add_cookie, + top_context, + test_page_cross_origin, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + source_origin_1 = get_origin_from_url(test_page) + + await bidi_session.browsing_context.navigate( + context=top_context["context"], url=test_page_cross_origin, wait="complete" + ) + source_origin_2 = get_origin_from_url(test_page_cross_origin) + + cookie_name = "foo" + cookie_value = "bar" + await add_cookie(new_tab["context"], cookie_name, cookie_value) + + # Check that added cookies are present on the right context. + cookies = await bidi_session.storage.get_cookies( + partition=BrowsingContextPartitionDescriptor(new_tab["context"]) + ) + + recursive_compare( + { + "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}, + } + ], + "partitionKey": {"sourceOrigin": source_origin_1}, + }, + cookies, + ) + + # Check that added cookies are not present on the other context. + cookies = await bidi_session.storage.get_cookies( + partition=BrowsingContextPartitionDescriptor(top_context["context"]) + ) + + recursive_compare( + {"cookies": [], "partitionKey": {"sourceOrigin": source_origin_2}}, cookies + ) + + +@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"]) +async def test_partition_context_iframe( + bidi_session, new_tab, inline, domain_value, domain, add_cookie +): + iframe_url = inline("<div id='in-iframe'>foo</div>", domain=domain) + source_origin_for_iframe = get_origin_from_url(iframe_url) + page_url = inline(f"<iframe src='{iframe_url}'></iframe>") + source_origin_for_page = get_origin_from_url(page_url) + 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" + await add_cookie(iframe_context["context"], cookie_name, cookie_value) + + # Check that added cookies are present on the right context + cookies = await bidi_session.storage.get_cookies( + partition=BrowsingContextPartitionDescriptor(iframe_context["context"]) + ) + + expected_cookies = [ + { + "domain": domain_value(domain=domain), + "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": {"sourceOrigin": source_origin_for_iframe}, + }, + cookies, + ) + + cookies = await bidi_session.storage.get_cookies( + partition=BrowsingContextPartitionDescriptor(new_tab["context"]) + ) + # When the iframe is on the different domain we can verify that top context has no iframe cookie. + if domain == "alt": + recursive_compare( + { + "cookies": [], + "partitionKey": {"sourceOrigin": source_origin_for_page}, + }, + cookies, + ) + else: + # When the iframe is on the same domain, since the browsing context partition is defined by user context and origin, + # which will be the same for the page, we get the same cookies as for the iframe + recursive_compare( + { + "cookies": expected_cookies, + "partitionKey": {"sourceOrigin": source_origin_for_page}, + }, + cookies, + ) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/storage/set_cookie/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/set_cookie/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/set_cookie/__init__.py diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/storage/set_cookie/partition.py b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/set_cookie/partition.py new file mode 100644 index 0000000000..f8e2823dbc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/storage/set_cookie/partition.py @@ -0,0 +1,150 @@ +import pytest +from tests.bidi import recursive_compare +from tests.support.helpers import get_origin_from_url +from webdriver.bidi.modules.network import NetworkStringValue +from webdriver.bidi.modules.storage import ( + BrowsingContextPartitionDescriptor, + PartialCookie, +) + +pytestmark = pytest.mark.asyncio + + +async def test_partition_context( + bidi_session, + set_cookie, + top_context, + new_tab, + test_page, + test_page_cross_origin, + domain_value, +): + await bidi_session.browsing_context.navigate( + context=new_tab["context"], url=test_page, wait="complete" + ) + source_origin_1 = get_origin_from_url(test_page) + await bidi_session.browsing_context.navigate( + context=top_context["context"], url=test_page_cross_origin, wait="complete" + ) + source_origin_2 = get_origin_from_url(test_page_cross_origin) + + cookie_name = "foo" + cookie_value = "bar" + cookie_domain = domain_value() + new_tab_partition = BrowsingContextPartitionDescriptor(new_tab["context"]) + + set_cookie_result = await set_cookie( + cookie=PartialCookie( + domain=cookie_domain, + name=cookie_name, + value=NetworkStringValue(cookie_value), + ), + partition=new_tab_partition, + ) + + assert set_cookie_result == {"partitionKey": {"sourceOrigin": source_origin_1}} + + # Check that added cookies are present on the right context. + cookies = await bidi_session.storage.get_cookies(partition=new_tab_partition) + + recursive_compare( + { + "cookies": [ + { + "domain": cookie_domain, + "httpOnly": False, + "name": cookie_name, + "path": "/", + "sameSite": "none", + "secure": False, + "size": 6, + "value": {"type": "string", "value": cookie_value}, + } + ], + "partitionKey": {"sourceOrigin": source_origin_1}, + }, + cookies, + ) + + # Check that added cookies are not present on the other context. + cookies = await bidi_session.storage.get_cookies( + partition=BrowsingContextPartitionDescriptor(top_context["context"]) + ) + + recursive_compare( + {"cookies": [], "partitionKey": {"sourceOrigin": source_origin_2}}, cookies + ) + + +@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("<div id='in-iframe'>foo</div>", domain=domain) + source_origin_for_iframe = get_origin_from_url(iframe_url) + page_url = inline(f"<iframe src='{iframe_url}'></iframe>") + source_origin_for_page = get_origin_from_url(page_url) + 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] + iframe_partition = BrowsingContextPartitionDescriptor(iframe_context["context"]) + + cookie_name = "foo" + cookie_value = "bar" + await set_cookie( + cookie=PartialCookie( + domain=domain_value(domain), + name=cookie_name, + value=NetworkStringValue(cookie_value), + ), + partition=iframe_partition, + ) + + # Check that added cookies are present on the right context + cookies = await bidi_session.storage.get_cookies(partition=iframe_partition) + + expected_cookies = [ + { + "domain": domain_value(domain=domain), + "httpOnly": False, + "name": cookie_name, + "path": "/", + "sameSite": "none", + "secure": False, + "size": 6, + "value": {"type": "string", "value": cookie_value}, + } + ] + recursive_compare( + { + "cookies": expected_cookies, + "partitionKey": {"sourceOrigin": source_origin_for_iframe}, + }, + cookies, + ) + + cookies = await bidi_session.storage.get_cookies( + partition=BrowsingContextPartitionDescriptor(new_tab["context"]) + ) + # When the iframe is on the different domain we can verify that top context has no iframe cookie. + if domain == "alt": + recursive_compare( + { + "cookies": [], + "partitionKey": {"sourceOrigin": source_origin_for_page}, + }, + cookies, + ) + else: + # When the iframe is on the same domain, since the browsing context partition is defined by user context and origin, + # which will be the same for the page, we get the same cookies as for the iframe + recursive_compare( + { + "cookies": expected_cookies, + "partitionKey": {"sourceOrigin": source_origin_for_page}, + }, + cookies, + ) diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/websocket_upgrade.py b/testing/web-platform/mozilla/tests/webdriver/bidi/websocket_upgrade.py new file mode 100644 index 0000000000..69f48aa9d2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/websocket_upgrade.py @@ -0,0 +1,158 @@ +# META: timeout=long + +import pytest +from support.network import get_host, websocket_request + + +@pytest.mark.parametrize( + "hostname, port_type, status", + [ + # Valid hosts + ("localhost", "server_port", 101), + ("localhost", "default_port", 101), + ("127.0.0.1", "server_port", 101), + ("127.0.0.1", "default_port", 101), + ("[::1]", "server_port", 101), + ("[::1]", "default_port", 101), + ("192.168.8.1", "server_port", 101), + ("192.168.8.1", "default_port", 101), + ("[fdf8:f535:82e4::53]", "server_port", 101), + ("[fdf8:f535:82e4::53]", "default_port", 101), + # Invalid hosts + ("mozilla.org", "server_port", 400), + ("mozilla.org", "wrong_port", 400), + ("mozilla.org", "default_port", 400), + ("localhost", "wrong_port", 400), + ("127.0.0.1", "wrong_port", 400), + ("[::1]", "wrong_port", 400), + ("192.168.8.1", "wrong_port", 400), + ("[fdf8:f535:82e4::53]", "wrong_port", 400), + ], + ids=[ + # Valid hosts + "localhost with same port as RemoteAgent", + "localhost with default port", + "127.0.0.1 (loopback) with same port as RemoteAgent", + "127.0.0.1 (loopback) with default port", + "[::1] (ipv6 loopback) with same port as RemoteAgent", + "[::1] (ipv6 loopback) with default port", + "ipv4 address with same port as RemoteAgent", + "ipv4 address with default port", + "ipv6 address with same port as RemoteAgent", + "ipv6 address with default port", + # Invalid hosts + "random hostname with the same port as RemoteAgent", + "random hostname with a different port than RemoteAgent", + "random hostname with default port", + "localhost with a different port than RemoteAgent", + "127.0.0.1 (loopback) with a different port than RemoteAgent", + "[::1] (ipv6 loopback) with a different port than RemoteAgent", + "ipv4 address with a different port than RemoteAgent", + "ipv6 address with a different port than RemoteAgent", + ], +) +def test_host_header(browser, hostname, port_type, status): + # Request a default browser + current_browser = browser(use_bidi=True) + server_host = current_browser.remote_agent_host + server_port = current_browser.remote_agent_port + test_host = get_host(port_type, hostname, server_port) + + response = websocket_request(server_host, server_port, host=test_host) + assert response.status == status + + +@pytest.mark.parametrize( + "hostname, port_type, status", + [ + # Allowed hosts + ("testhost", "server_port", 101), + ("testhost", "default_port", 101), + ("testhost", "wrong_port", 400), + # IP addresses + ("192.168.8.1", "server_port", 101), + ("192.168.8.1", "default_port", 101), + ("[fdf8:f535:82e4::53]", "server_port", 101), + ("[fdf8:f535:82e4::53]", "default_port", 101), + ("127.0.0.1", "server_port", 101), + ("127.0.0.1", "default_port", 101), + ("[::1]", "server_port", 101), + ("[::1]", "default_port", 101), + # Localhost + ("localhost", "server_port", 400), + ("localhost", "default_port", 400), + ], + ids=[ + # Allowed hosts + "allowed host with same port as RemoteAgent", + "allowed host with default port", + "allowed host with wrong port", + # IP addresses + "ipv4 address with same port as RemoteAgent", + "ipv4 address with default port", + "ipv6 address with same port as RemoteAgent", + "ipv6 address with default port", + "127.0.0.1 (loopback) with same port as RemoteAgent", + "127.0.0.1 (loopback) with default port", + "[::1] (ipv6 loopback) with same port as RemoteAgent", + "[::1] (ipv6 loopback) with default port", + # Localhost + "localhost with same port as RemoteAgent", + "localhost with default port", + ], +) +def test_allowed_hosts(browser, hostname, port_type, status): + # Request a browser with custom allowed hosts. + current_browser = browser( + use_bidi=True, + extra_args=["--remote-allow-hosts", "testhost"], + ) + server_host = current_browser.remote_agent_host + server_port = current_browser.remote_agent_port + test_host = get_host(port_type, hostname, server_port) + + response = websocket_request(server_host, server_port, host=test_host) + assert response.status == status + + +@pytest.mark.parametrize( + "origin, status", + [ + (None, 101), + ("", 400), + ("sometext", 400), + ("http://localhost:1234", 400), + ], +) +def test_origin_header(browser, origin, status): + # Request a default browser. + current_browser = browser(use_bidi=True) + server_host = current_browser.remote_agent_host + server_port = current_browser.remote_agent_port + response = websocket_request(server_host, server_port, origin=origin) + assert response.status == status + + +@pytest.mark.parametrize( + "origin, status", + [ + (None, 101), + ("", 400), + ("sometext", 400), + ("http://localhost:1234", 101), + ("https://localhost:1234", 400), + ], +) +def test_allowed_origins(browser, origin, status): + # Request a browser with custom allowed origins. + current_browser = browser( + use_bidi=True, + extra_args=["--remote-allow-origins", "http://localhost:1234"], + ) + server_port = current_browser.remote_agent_port + + # Both `localhost` and `127.0.0.1` have to accept connections. + for target_host in ["127.0.0.1", "localhost"]: + print(f"Connecting to the WebSocket via host {target_host}") + response = websocket_request(target_host, server_port, origin=origin) + assert response.status == status |