blob: c98e448b9c4733fdcf6b3dcb201131caa2ff7907 [file] [log] [blame]
import asyncio
import json
from urllib.parse import quote
import pytest
from webdriver.bidi.modules.script import ContextTarget
from tests.support.sync import AsyncPoll
from ... import any_int
from .. import assert_response_event, HTTP_STATUS_AND_STATUS_TEXT
PAGE_EMPTY_HTML = "/webdriver/tests/bidi/network/support/empty.html"
PAGE_EMPTY_IMAGE = "/webdriver/tests/bidi/network/support/empty.png"
PAGE_EMPTY_SCRIPT = "/webdriver/tests/bidi/network/support/empty.js"
PAGE_EMPTY_SVG = "/webdriver/tests/bidi/network/support/empty.svg"
PAGE_EMPTY_TEXT = "/webdriver/tests/bidi/network/support/empty.txt"
RESPONSE_COMPLETED_EVENT = "network.responseCompleted"
@pytest.mark.asyncio
async def test_subscribe_status(bidi_session, top_context, wait_for_event, url, fetch):
await bidi_session.session.subscribe(events=[RESPONSE_COMPLETED_EVENT])
# Track all received network.responseCompleted events in the events array
events = []
async def on_event(method, data):
events.append(data)
remove_listener = bidi_session.add_event_listener(
RESPONSE_COMPLETED_EVENT, on_event
)
html_url = url(PAGE_EMPTY_HTML)
on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=html_url,
wait="complete",
)
await on_response_completed
assert len(events) == 1
expected_request = {"method": "GET", "url": html_url}
expected_response = {
"url": url(PAGE_EMPTY_HTML),
"fromCache": False,
"mimeType": "text/html",
"status": 200,
"statusText": "OK",
}
assert_response_event(
events[0],
expected_request=expected_request,
expected_response=expected_response,
redirect_count=0,
)
text_url = url(PAGE_EMPTY_TEXT)
on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
await fetch(text_url)
await on_response_completed
assert len(events) == 2
expected_request = {"method": "GET", "url": text_url}
expected_response = {
"url": text_url,
"fromCache": False,
"mimeType": "text/plain",
"status": 200,
"statusText": "OK",
}
assert_response_event(
events[1],
expected_request=expected_request,
expected_response=expected_response,
redirect_count=0,
)
await bidi_session.session.unsubscribe(events=[RESPONSE_COMPLETED_EVENT])
# Fetch the text url again, with an additional parameter to bypass the cache
# and check no new event is received.
await fetch(f"{text_url}?nocache")
await asyncio.sleep(0.5)
assert len(events) == 2
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)
network_events = await setup_network_test(events=[RESPONSE_COMPLETED_EVENT])
events = network_events[RESPONSE_COMPLETED_EVENT]
on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=html_url,
wait="complete",
)
await on_response_completed
assert len(events) == 1
expected_request = {"method": "GET", "url": html_url}
expected_response = {
"url": html_url,
"fromCache": False,
"mimeType": "text/html",
"status": 200,
"statusText": "OK",
"protocol": "http/1.1",
}
assert_response_event(
events[0],
expected_request=expected_request,
expected_response=expected_response,
redirect_count=0,
)
@pytest.mark.parametrize(
"status, status_text",
HTTP_STATUS_AND_STATUS_TEXT,
)
@pytest.mark.asyncio
async def test_response_status(
bidi_session, wait_for_event, url, fetch, setup_network_test, status, status_text
):
status_url = url(
f"/webdriver/tests/support/http_handlers/status.py?status={status}&nocache={RESPONSE_COMPLETED_EVENT}"
)
network_events = await setup_network_test(events=[RESPONSE_COMPLETED_EVENT])
events = network_events[RESPONSE_COMPLETED_EVENT]
on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
await fetch(status_url)
await on_response_completed
assert len(events) == 1
expected_request = {"method": "GET", "url": status_url}
expected_response = {
"url": status_url,
"fromCache": False,
"mimeType": "text/plain",
"status": status,
"statusText": status_text,
"protocol": "http/1.1",
}
assert_response_event(
events[0],
expected_response=expected_response,
redirect_count=0,
)
@pytest.mark.asyncio
async def test_response_headers(
bidi_session, wait_for_event, url, fetch, setup_network_test
):
headers_url = url(
"/webdriver/tests/support/http_handlers/headers.py?header=foo:bar&header=baz:biz"
)
network_events = await setup_network_test(events=[RESPONSE_COMPLETED_EVENT])
events = network_events[RESPONSE_COMPLETED_EVENT]
on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
await fetch(headers_url, method="GET")
await on_response_completed
assert len(events) == 1
expected_request = {"method": "GET", "url": headers_url}
expected_response = {
"url": headers_url,
"fromCache": False,
"mimeType": "text/plain",
"status": 200,
"statusText": "OK",
"headers": (
{"name": "foo", "value": "bar"},
{"name": "baz", "value": "biz"},
),
"protocol": "http/1.1",
}
assert_response_event(
events[0],
expected_request=expected_request,
redirect_count=0,
)
@pytest.mark.parametrize(
"page_url, mime_type",
[
(PAGE_EMPTY_HTML, "text/html"),
(PAGE_EMPTY_TEXT, "text/plain"),
(PAGE_EMPTY_SCRIPT, "text/javascript"),
(PAGE_EMPTY_IMAGE, "image/png"),
(PAGE_EMPTY_SVG, "image/svg+xml"),
],
)
@pytest.mark.asyncio
async def test_response_mime_type_file(
bidi_session, url, wait_for_event, fetch, setup_network_test, page_url, mime_type
):
network_events = await setup_network_test(events=[RESPONSE_COMPLETED_EVENT])
events = network_events[RESPONSE_COMPLETED_EVENT]
on_response_completed = wait_for_event(RESPONSE_COMPLETED_EVENT)
await fetch(url(page_url), method="GET")
await on_response_completed
assert len(events) == 1
expected_request = {"method": "GET", "url": url(page_url)}
expected_response = {"url": url(page_url), "mimeType": mime_type}
assert_response_event(
events[0],
expected_request=expected_request,
expected_response=expected_response,
redirect_count=0,
)
@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/http_handlers/redirect.py?location={text_url}"
)
network_events = await setup_network_test(events=[RESPONSE_COMPLETED_EVENT])
events = network_events[RESPONSE_COMPLETED_EVENT]
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
expected_request = {"method": "GET", "url": redirect_url}
assert_response_event(
events[0],
expected_request=expected_request,
redirect_count=0,
)
expected_request = {"method": "GET", "url": text_url}
assert_response_event(
events[1], expected_request=expected_request, redirect_count=1
)
# Check that both requests share the same requestId
assert events[0]["request"]["request"] == events[1]["request"]["request"]
@pytest.mark.parametrize(
"protocol,parameters",
[
("http", ""),
("https", ""),
("https", {"pipe": "header(Cross-Origin-Opener-Policy,same-origin)"}),
],
ids=["http", "https", "https coop"],
)
@pytest.mark.asyncio
async def test_redirect_document(
bidi_session, new_tab, url, setup_network_test, inline, protocol, parameters
):
network_events = await setup_network_test(events=[RESPONSE_COMPLETED_EVENT])
events = network_events[RESPONSE_COMPLETED_EVENT]
# The test starts on a url on the alternate domain, potentially with https
# and coop headers.
initial_url = inline(
"<div>bar</div>",
domain="alt",
protocol=protocol,
parameters=parameters,
)
await bidi_session.browsing_context.navigate(
context=new_tab["context"],
url=initial_url,
wait="complete",
)
# Then navigate to a cross domain page, which will redirect back to the
# initial url.
redirect_url = url(
f"/webdriver/tests/support/http_handlers/redirect.py?location={quote(initial_url)}"
)
await bidi_session.browsing_context.navigate(
context=new_tab["context"],
url=redirect_url,
wait="complete",
)
# Wait until we receive three events:
# - one for the initial request
# - two for the second navigation and its redirect
wait = AsyncPoll(bidi_session, timeout=2)
await wait.until(lambda _: len(events) >= 3)
assert len(events) == 3
expected_request = {"method": "GET", "url": initial_url}
assert_response_event(
events[0], expected_request=expected_request, redirect_count=0
)
expected_request = {"method": "GET", "url": redirect_url}
assert_response_event(
events[1], expected_request=expected_request, redirect_count=0
)
expected_request = {"method": "GET", "url": initial_url}
assert_response_event(
events[2], expected_request=expected_request, redirect_count=1
)
# Check that the last 2 requests share the same request id
assert events[1]["request"]["request"] == events[2]["request"]["request"]