blob: 6dbd3b1a81a75e5b24df058f3e164b8046c66323 [file] [log] [blame]
import asyncio
import json
import pytest
from webdriver.bidi.modules.script import ContextTarget
from tests.support.sync import AsyncPoll
from .. import assert_before_request_sent_event
PAGE_EMPTY_HTML = "/webdriver/tests/bidi/network/support/empty.html"
PAGE_EMPTY_TEXT = "/webdriver/tests/bidi/network/support/empty.txt"
PAGE_REDIRECT_HTTP_EQUIV = "/webdriver/tests/bidi/network/support/redirect_http_equiv.html"
PAGE_REDIRECTED_HTML = "/webdriver/tests/bidi/network/support/redirected.html"
# The following tests are marked as tentative until
# https://github.com/w3c/webdriver-bidi/pull/204 is merged.
@pytest.fixture
def fetch(bidi_session, top_context):
"""Perform a fetch from the page of the top level context."""
async def fetch(url, method="GET", headers=None):
method_arg = f"method: '{method}',"
headers_arg = ""
if headers != None:
headers_arg = f"headers: {json.dumps(headers)},"
# Wait for fetch() to resolve a response and for response.text() to
# resolve as well to make sure the request/response is completed when
# the helper returns.
await bidi_session.script.evaluate(
expression=f"""
fetch("{url}", {{
{method_arg}
{headers_arg}
}}).then(response => response.text());""",
target=ContextTarget(top_context["context"]),
await_promise=True,
)
return fetch
@pytest.fixture
async def setup_network_test(bidi_session, subscribe_events, top_context, url):
"""Navigate the current top level context to the provided url and subscribe
to network.beforeRequestSent.
Returns an `events` list in which the captured network events will be added.
"""
remove_listener = None
async def _setup_network_test(test_url=url(PAGE_EMPTY_HTML)):
nonlocal remove_listener
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=test_url,
wait="complete",
)
events = []
await subscribe_events(["network.beforeRequestSent"])
async def on_event(method, data):
events.append(data)
remove_listener = bidi_session.add_event_listener(
"network.beforeRequestSent", on_event
)
return events
yield _setup_network_test
# cleanup
remove_listener()
@pytest.mark.asyncio
async def test_subscribe_status(bidi_session, top_context, wait_for_event, url, fetch):
await bidi_session.session.subscribe(events=["network.beforeRequestSent"])
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=url("/webdriver/tests/bidi/network/support/empty.html"),
wait="complete",
)
# Track all received network.beforeRequestSent events in the events array
events = []
async def on_event(method, data):
events.append(data)
remove_listener = bidi_session.add_event_listener(
"network.beforeRequestSent", on_event
)
text_url = url(PAGE_EMPTY_TEXT)
on_before_request_sent = wait_for_event("network.beforeRequestSent")
await fetch(text_url)
await on_before_request_sent
assert len(events) == 1
assert_before_request_sent_event(
events[0], url=text_url, method="GET", redirect_count=0, is_redirect=False
)
await bidi_session.session.unsubscribe(events=["network.beforeRequestSent"])
# Fetch the text url again, with an additional parameter to bypass the cache
# check no new event is received.
await fetch(f"{text_url}?nocache")
await asyncio.sleep(0.5)
assert len(events) == 1
remove_listener()
@pytest.mark.asyncio
async def test_load_page_twice(
bidi_session, top_context, wait_for_event, url, fetch, setup_network_test
):
html_url = url(PAGE_EMPTY_HTML)
events = await setup_network_test()
on_before_request_sent = wait_for_event("network.beforeRequestSent")
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=html_url,
wait="complete",
)
await on_before_request_sent
assert len(events) == 1
assert_before_request_sent_event(
events[0], url=html_url, method="GET", redirect_count=0, is_redirect=False
)
@pytest.mark.parametrize(
"method",
[
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"PATCH",
],
)
@pytest.mark.asyncio
async def test_request_method(
bidi_session, wait_for_event, url, fetch, setup_network_test, method
):
text_url = url(PAGE_EMPTY_TEXT)
events = await setup_network_test()
on_before_request_sent = wait_for_event("network.beforeRequestSent")
await fetch(text_url, method=method)
await on_before_request_sent
assert len(events) == 1
assert_before_request_sent_event(
events[0], url=text_url, method=method, redirect_count=0, is_redirect=False
)
@pytest.mark.asyncio
async def test_request_headers(
bidi_session, wait_for_event, url, fetch, setup_network_test
):
text_url = url(PAGE_EMPTY_TEXT)
events = await setup_network_test()
on_before_request_sent = wait_for_event("network.beforeRequestSent")
await fetch(text_url, method="GET", headers={"foo": "bar"})
await on_before_request_sent
assert len(events) == 1
assert_before_request_sent_event(
events[0],
url=text_url,
method="GET",
redirect_count=0,
is_redirect=False,
headers=({"name": "foo", "value": "bar"},),
)
@pytest.mark.asyncio
async def test_request_cookies(
bidi_session, top_context, wait_for_event, url, fetch, setup_network_test
):
text_url = url(PAGE_EMPTY_TEXT)
events = await setup_network_test()
await bidi_session.script.evaluate(
expression="document.cookie = 'foo=bar';",
target=ContextTarget(top_context["context"]),
await_promise=False,
)
on_before_request_sent = wait_for_event("network.beforeRequestSent")
await fetch(text_url, method="GET")
await on_before_request_sent
assert len(events) == 1
assert_before_request_sent_event(
events[0],
url=text_url,
method="GET",
redirect_count=0,
is_redirect=False,
cookies=({"name": "foo", "value": "bar"},),
)
await bidi_session.script.evaluate(
expression="document.cookie = 'fuu=baz';",
target=ContextTarget(top_context["context"]),
await_promise=False,
)
on_before_request_sent = wait_for_event("network.beforeRequestSent")
await fetch(text_url, method="GET")
await on_before_request_sent
assert len(events) == 2
assert_before_request_sent_event(
events[1],
url=text_url,
method="GET",
redirect_count=0,
is_redirect=False,
cookies=(
{"name": "foo", "value": "bar"},
{"name": "fuu", "value": "baz"},
),
)
@pytest.mark.asyncio
async def test_redirect(
bidi_session, wait_for_event, url, fetch, setup_network_test
):
text_url = url(PAGE_EMPTY_TEXT)
redirect_url = url(f"/webdriver/tests/support/redirect.py?location={text_url}")
events = await setup_network_test()
await fetch(redirect_url, method="GET")
# Wait until we receive two events, one for the initial request and one for
# the redirection.
wait = AsyncPoll(bidi_session, timeout=2)
await wait.until(lambda _: len(events) >= 2)
assert len(events) == 2
assert_before_request_sent_event(
events[0],
url=redirect_url,
method="GET",
redirect_count=0,
is_redirect=False,
)
assert_before_request_sent_event(
events[1],
url=text_url,
method="GET",
redirect_count=1,
is_redirect=True,
)
# Check that both requests share the same requestId
assert events[0]["request"]["request"] == events[1]["request"]["request"]
@pytest.mark.asyncio
async def test_redirect_http_equiv(
bidi_session, top_context, wait_for_event, url, setup_network_test
):
# PAGE_REDIRECT_HTTP_EQUIV should redirect to PAGE_REDIRECTED_HTML immediately
http_equiv_url = url(PAGE_REDIRECT_HTTP_EQUIV)
redirected_url = url(PAGE_REDIRECTED_HTML)
events = await setup_network_test()
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=http_equiv_url,
wait="complete",
)
# Wait until we receive two events, one for the initial request and one for
# the http-equiv "redirect".
wait = AsyncPoll(bidi_session, timeout=2)
await wait.until(lambda _: len(events) >= 2)
assert len(events) == 2
assert_before_request_sent_event(
events[0],
url=http_equiv_url,
method="GET",
redirect_count=0,
is_redirect=False,
)
# http-equiv redirect should not be considered as a redirect: redirect_count
# should be 0 and is_redirect should be false.
assert_before_request_sent_event(
events[1],
url=redirected_url,
method="GET",
redirect_count=0,
is_redirect=False,
)
# Check that the http-equiv redirect request has a different requestId
assert events[0]["request"]["request"] != events[1]["request"]["request"]