mirror of
https://github.com/servo/servo.git
synced 2025-08-23 22:35:33 +01:00
Update web-platform-tests to revision 58eb04cecbbec2e18531ab440225e38944a9c444
This commit is contained in:
parent
25e8bf69e6
commit
665817d2a6
35333 changed files with 1818077 additions and 16036 deletions
|
@ -2,3 +2,4 @@
|
|||
@lukeis
|
||||
@AutomatedTester
|
||||
@shs96c
|
||||
@mjzffr
|
||||
|
|
34
tests/wpt/web-platform-tests/webdriver/actions/conftest.py
Normal file
34
tests/wpt/web-platform-tests/webdriver/actions/conftest.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def key_chain(session):
|
||||
return session.actions.sequence("key", "keyboard_id")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mouse_chain(session):
|
||||
return session.actions.sequence(
|
||||
"pointer",
|
||||
"pointer_id",
|
||||
{"pointerType": "mouse"})
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def release_actions(session, request):
|
||||
# release all actions after each test
|
||||
# equivalent to a teardown_function, but with access to session fixture
|
||||
request.addfinalizer(session.actions.release)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def key_reporter(session, test_actions_page, request):
|
||||
"""Represents focused input element from `test_keys_page` fixture."""
|
||||
input_el = session.find.css("#keys", all=False)
|
||||
input_el.click()
|
||||
return input_el
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_actions_page(session, url):
|
||||
session.url = url("/webdriver/actions/support/test_actions_wdspec.html")
|
|
@ -1,72 +1,9 @@
|
|||
# META: timeout=long
|
||||
|
||||
import pytest
|
||||
|
||||
from support.keys import Keys
|
||||
|
||||
|
||||
def get_events(session):
|
||||
"""Return list of key events recorded in the test_keys_page fixture."""
|
||||
events = session.execute_script("return allEvents.events;") or []
|
||||
# `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in
|
||||
# test_keys_wdspec.html), so this converts them back into unicode literals.
|
||||
for e in events:
|
||||
# example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char)
|
||||
if e["key"].startswith(u"U+"):
|
||||
key = e["key"]
|
||||
hex_suffix = key[key.index("+") + 1:]
|
||||
e["key"] = unichr(int(hex_suffix, 16))
|
||||
return events
|
||||
|
||||
|
||||
def get_keys(input_el):
|
||||
"""Get printable characters entered into `input_el`.
|
||||
|
||||
:param input_el: HTML input element.
|
||||
"""
|
||||
rv = input_el.property("value")
|
||||
if rv is None:
|
||||
return ""
|
||||
else:
|
||||
return rv
|
||||
|
||||
|
||||
def filter_dict(source, d):
|
||||
"""Filter `source` dict to only contain same keys as `d` dict.
|
||||
|
||||
:param source: dictionary to filter.
|
||||
:param d: dictionary whose keys determine the filtering.
|
||||
"""
|
||||
return {k: source[k] for k in d.keys()}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def key_reporter(session, test_keys_page, request):
|
||||
"""Represents focused input element from `test_keys_page` fixture."""
|
||||
input_el = session.find.css("#keys", all=False)
|
||||
input_el.click()
|
||||
return input_el
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_keys_page(session, server):
|
||||
session.url = server.where_is("test_keys_wdspec.html")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def key_chain(session):
|
||||
return session.actions.sequence("key", "keyboard_id")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def release_actions(session, request):
|
||||
# release all actions after each test
|
||||
# equivalent to a teardown_function, but with access to session fixture
|
||||
request.addfinalizer(session.actions.release)
|
||||
|
||||
|
||||
def test_no_actions_send_no_events(session, key_reporter, key_chain):
|
||||
key_chain.perform()
|
||||
assert len(get_keys(key_reporter)) == 0
|
||||
assert len(get_events(session)) == 0
|
||||
from support.refine import get_keys, filter_dict, get_events
|
||||
|
||||
|
||||
def test_lone_keyup_sends_no_events(session, key_reporter, key_chain):
|
||||
|
@ -220,24 +157,6 @@ def test_sequence_of_keydown_printable_keys_sends_events(session,
|
|||
assert get_keys(key_reporter) == "ab"
|
||||
|
||||
|
||||
def test_release_char_sequence_sends_keyup_events_in_reverse(session,
|
||||
key_reporter,
|
||||
key_chain):
|
||||
key_chain \
|
||||
.key_down("a") \
|
||||
.key_down("b") \
|
||||
.perform()
|
||||
# reset so we only see the release events
|
||||
session.execute_script("resetEvents();")
|
||||
session.actions.release()
|
||||
expected = [
|
||||
{"code": "KeyB", "key": "b", "type": "keyup"},
|
||||
{"code": "KeyA", "key": "a", "type": "keyup"},
|
||||
]
|
||||
events = [filter_dict(e, expected[0]) for e in get_events(session)]
|
||||
assert events == expected
|
||||
|
||||
|
||||
def test_sequence_of_keydown_character_keys(session, key_reporter, key_chain):
|
||||
key_chain.send_keys("ef").perform()
|
||||
expected = [
|
||||
|
@ -251,9 +170,3 @@ def test_sequence_of_keydown_character_keys(session, key_reporter, key_chain):
|
|||
events = [filter_dict(e, expected[0]) for e in get_events(session)]
|
||||
assert events == expected
|
||||
assert get_keys(key_reporter) == "ef"
|
||||
|
||||
|
||||
def test_release_no_actions_sends_no_events(session, key_reporter, key_chain):
|
||||
session.actions.release()
|
||||
assert len(get_keys(key_reporter)) == 0
|
||||
assert len(get_events(session)) == 0
|
31
tests/wpt/web-platform-tests/webdriver/actions/mouse.py
Normal file
31
tests/wpt/web-platform-tests/webdriver/actions/mouse.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from support.refine import get_events, filter_dict
|
||||
|
||||
|
||||
def test_click_at_coordinates(session, test_actions_page, mouse_chain):
|
||||
div_point = {
|
||||
"x": 82,
|
||||
"y": 187,
|
||||
}
|
||||
button = 0
|
||||
mouse_chain \
|
||||
.pointer_move(div_point["x"], div_point["y"], duration=1000) \
|
||||
.pointer_down(button) \
|
||||
.pointer_up(button) \
|
||||
.perform()
|
||||
events = get_events(session)
|
||||
assert len(events) == 4
|
||||
for e in events:
|
||||
if e["type"] != "mousemove":
|
||||
assert e["pageX"] == div_point["x"]
|
||||
assert e["pageY"] == div_point["y"]
|
||||
assert e["target"] == "outer"
|
||||
if e["type"] != "mousedown":
|
||||
assert e["buttons"] == 0
|
||||
assert e["button"] == button
|
||||
expected = [
|
||||
{"type": "mousedown", "buttons": 1},
|
||||
{"type": "mouseup", "buttons": 0},
|
||||
{"type": "click", "buttons": 0},
|
||||
]
|
||||
filtered_events = [filter_dict(e, expected[0]) for e in events]
|
||||
assert expected == filtered_events[1:]
|
31
tests/wpt/web-platform-tests/webdriver/actions/sequence.py
Normal file
31
tests/wpt/web-platform-tests/webdriver/actions/sequence.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from support.refine import get_keys, filter_dict, get_events
|
||||
|
||||
|
||||
def test_no_actions_send_no_events(session, key_reporter, key_chain):
|
||||
key_chain.perform()
|
||||
assert len(get_keys(key_reporter)) == 0
|
||||
assert len(get_events(session)) == 0
|
||||
|
||||
|
||||
def test_release_char_sequence_sends_keyup_events_in_reverse(session,
|
||||
key_reporter,
|
||||
key_chain):
|
||||
key_chain \
|
||||
.key_down("a") \
|
||||
.key_down("b") \
|
||||
.perform()
|
||||
# reset so we only see the release events
|
||||
session.execute_script("resetEvents();")
|
||||
session.actions.release()
|
||||
expected = [
|
||||
{"code": "KeyB", "key": "b", "type": "keyup"},
|
||||
{"code": "KeyA", "key": "a", "type": "keyup"},
|
||||
]
|
||||
events = [filter_dict(e, expected[0]) for e in get_events(session)]
|
||||
assert events == expected
|
||||
|
||||
|
||||
def test_release_no_actions_sends_no_events(session, key_reporter):
|
||||
session.actions.release()
|
||||
assert len(get_keys(key_reporter)) == 0
|
||||
assert len(get_events(session)) == 0
|
|
@ -0,0 +1,33 @@
|
|||
def get_events(session):
|
||||
"""Return list of key events recorded in the test_keys_page fixture."""
|
||||
events = session.execute_script("return allEvents.events;") or []
|
||||
# `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in
|
||||
# test_keys_wdspec.html), so this converts them back into unicode literals.
|
||||
for e in events:
|
||||
# example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char)
|
||||
if "key" in e and e["key"].startswith(u"U+"):
|
||||
key = e["key"]
|
||||
hex_suffix = key[key.index("+") + 1:]
|
||||
e["key"] = unichr(int(hex_suffix, 16))
|
||||
return events
|
||||
|
||||
|
||||
def get_keys(input_el):
|
||||
"""Get printable characters entered into `input_el`.
|
||||
|
||||
:param input_el: HTML input element.
|
||||
"""
|
||||
rv = input_el.property("value")
|
||||
if rv is None:
|
||||
return ""
|
||||
else:
|
||||
return rv
|
||||
|
||||
|
||||
def filter_dict(source, d):
|
||||
"""Filter `source` dict to only contain same keys as `d` dict.
|
||||
|
||||
:param source: dictionary to filter.
|
||||
:param d: dictionary whose keys determine the filtering.
|
||||
"""
|
||||
return {k: source[k] for k in d.keys()}
|
|
@ -0,0 +1,131 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<head>
|
||||
<title>Test Actions</title>
|
||||
<style>
|
||||
div { padding:0px; margin: 0px; }
|
||||
#resultContainer { width: 600px; height: 60px; }
|
||||
#outer { width: 100px; height: 50px; background-color: #ccc; }
|
||||
#trackPointer {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border: solid 1px red;
|
||||
position: fixed; }
|
||||
</style>
|
||||
<script>
|
||||
var allEvents = {events: []};
|
||||
function displayMessage(message) {
|
||||
document.getElementById("events").innerHTML = "<p>" + message + "</p>";
|
||||
}
|
||||
|
||||
function appendMessage(message) {
|
||||
document.getElementById("events").innerHTML += "<p>" + message + "</p>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape |key| if it's in a surrogate-half character range.
|
||||
*
|
||||
* Example: given "\ud83d" return "U+d83d".
|
||||
*
|
||||
* Otherwise JSON.stringify will convert it to U+FFFD (REPLACEMENT CHARACTER)
|
||||
* when returning a value from executeScript, for example.
|
||||
*/
|
||||
function escapeSurrogateHalf(key) {
|
||||
if (typeof key !== "undefined" && key.length === 1) {
|
||||
var charCode = key.charCodeAt(0);
|
||||
var highSurrogate = charCode >= 0xD800 && charCode <= 0xDBFF;
|
||||
var surrogate = highSurrogate || (charCode >= 0xDC00 && charCode <= 0xDFFF);
|
||||
if (surrogate) {
|
||||
key = "U+" + charCode.toString(16);
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
function recordKeyboardEvent(event) {
|
||||
var key = escapeSurrogateHalf(event.key);
|
||||
allEvents.events.push({
|
||||
"code": event.code,
|
||||
"key": key,
|
||||
"which": event.which,
|
||||
"location": event.location,
|
||||
"ctrl": event.ctrlKey,
|
||||
"meta": event.metaKey,
|
||||
"shift": event.shiftKey,
|
||||
"repeat": event.repeat,
|
||||
"type": event.type
|
||||
});
|
||||
appendMessage(`${event.type}(` +
|
||||
`code: ${event.code}, ` +
|
||||
`key: ${key}, ` +
|
||||
`which: ${event.which})`);
|
||||
}
|
||||
|
||||
function recordPointerEvent(event) {
|
||||
allEvents.events.push({
|
||||
"type": event.type,
|
||||
"button": event.button,
|
||||
"buttons": event.buttons,
|
||||
"pageX": event.pageX,
|
||||
"pageY": event.pageY,
|
||||
"target": event.target.id
|
||||
});
|
||||
appendMessage(`${event.type}(` +
|
||||
`button: ${event.button}, ` +
|
||||
`pageX: ${event.pageX}, ` +
|
||||
`pageY: ${event.pageY}, ` +
|
||||
`button: ${event.button}, ` +
|
||||
`buttons: ${event.buttons}, ` +
|
||||
`target id: ${event.target.id})`);
|
||||
}
|
||||
|
||||
function recordFirstPointerMove(event) {
|
||||
recordPointerEvent(event);
|
||||
window.removeEventListener("mousemove", recordFirstPointerMove);
|
||||
}
|
||||
|
||||
function resetEvents() {
|
||||
allEvents.events.length = 0;
|
||||
displayMessage("");
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
var keyReporter = document.getElementById("keys");
|
||||
["keyup", "keypress", "keydown"].forEach((e) => {
|
||||
keyReporter.addEventListener(e, recordKeyboardEvent);
|
||||
});
|
||||
var outer = document.getElementById("outer");
|
||||
["click", "dblclick", "mousedown",
|
||||
"mouseup", "contextmenu"].forEach((e) => {
|
||||
outer.addEventListener(e, recordPointerEvent);
|
||||
});
|
||||
window.addEventListener("mousemove", recordFirstPointerMove);
|
||||
//visual cue for mousemove
|
||||
var pointer = document.getElementById("trackPointer");
|
||||
window.addEventListener("mousemove", (e) => {
|
||||
setTimeout(() => {
|
||||
let offset = 15;
|
||||
pointer.style.top = e.pageY + offset + "px";
|
||||
pointer.style.left = e.pageX + offset + "px";
|
||||
}, 30);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="trackPointer"></div>
|
||||
<div>
|
||||
<h2>KeyReporter</h2>
|
||||
<input type="text" id="keys" size="80">
|
||||
</div>
|
||||
<div>
|
||||
<h2>ClickReporter</h2>
|
||||
<div id="outer">
|
||||
</div>
|
||||
</div>
|
||||
<div id="resultContainer">
|
||||
<h2>Events</h2>
|
||||
<div id="events"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,41 +1,12 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import pytest
|
||||
import webdriver
|
||||
from support.fixtures import (
|
||||
create_frame, create_session, create_window, http, server_config, session,
|
||||
url)
|
||||
|
||||
from util import cleanup
|
||||
from util.http_request import HTTPRequest
|
||||
|
||||
default_host = "http://127.0.0.1"
|
||||
default_port = "4444"
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def _session(request):
|
||||
host = os.environ.get("WD_HOST", default_host)
|
||||
port = int(os.environ.get("WD_PORT", default_port))
|
||||
capabilities = json.loads(os.environ.get("WD_CAPABILITIES", "{}"))
|
||||
|
||||
session = webdriver.Session(host, port, desired_capabilities=capabilities)
|
||||
|
||||
def destroy():
|
||||
if session.session_id is not None:
|
||||
session.end()
|
||||
|
||||
request.addfinalizer(destroy)
|
||||
|
||||
return session
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def session(_session, request):
|
||||
# finalisers are popped off a stack,
|
||||
# making their ordering reverse
|
||||
request.addfinalizer(lambda: cleanup.switch_to_top_level_browsing_context(_session))
|
||||
request.addfinalizer(lambda: cleanup.restore_windows(_session))
|
||||
request.addfinalizer(lambda: cleanup.dismiss_user_prompts(_session))
|
||||
|
||||
return _session
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def http(session):
|
||||
return HTTPRequest(session.transport.host, session.transport.port)
|
||||
pytest.fixture()(create_frame)
|
||||
pytest.fixture()(create_session)
|
||||
pytest.fixture()(create_window)
|
||||
pytest.fixture()(http)
|
||||
pytest.fixture()(server_config)
|
||||
pytest.fixture(scope="function")(session)
|
||||
pytest.fixture()(url)
|
||||
|
|
|
@ -25,10 +25,11 @@ def test_window_size_types(http, session):
|
|||
with http.get("/session/%s/window/size" % session.session_id) as resp:
|
||||
assert resp.status == 200
|
||||
body = json.load(resp)
|
||||
assert "width" in body
|
||||
assert "height" in body
|
||||
assert isinstance(body["width"], int)
|
||||
assert isinstance(body["height"], int)
|
||||
assert "value" in body
|
||||
assert "width" in body["value"]
|
||||
assert "height" in body["value"]
|
||||
assert isinstance(body["value"]["width"], int)
|
||||
assert isinstance(body["value"]["height"], int)
|
||||
|
||||
size = session.window.size
|
||||
assert isinstance(size, tuple)
|
||||
|
@ -83,10 +84,11 @@ def test_window_position_types(http, session):
|
|||
with http.get("/session/%s/window/position" % session.session_id) as resp:
|
||||
assert resp.status == 200
|
||||
body = json.load(resp)
|
||||
assert "x" in body
|
||||
assert "y" in body
|
||||
assert isinstance(body["x"], int)
|
||||
assert isinstance(body["y"], int)
|
||||
assert "value" in body
|
||||
assert "x" in body["value"]
|
||||
assert "y" in body["value"]
|
||||
assert isinstance(body["value"]["x"], int)
|
||||
assert isinstance(body["value"]["y"], int)
|
||||
|
||||
pos = session.window.position
|
||||
assert isinstance(pos, tuple)
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
import json
|
||||
import pytest
|
||||
import types
|
||||
import urllib
|
||||
|
||||
import webdriver
|
||||
|
||||
|
||||
def inline(doc):
|
||||
return "data:text/html;charset=utf-8,%s" % urllib.quote(doc)
|
||||
|
||||
from support.inline import inline
|
||||
from support.asserts import assert_error, assert_success
|
||||
|
||||
alert_doc = inline("<script>window.alert()</script>")
|
||||
frame_doc = inline("<p>frame")
|
||||
|
@ -16,89 +11,83 @@ one_frame_doc = inline("<iframe src='%s'></iframe>" % frame_doc)
|
|||
two_frames_doc = inline("<iframe src='%s'></iframe>" % one_frame_doc)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def new_window(session):
|
||||
"""Open new window and return the window handle."""
|
||||
windows_before = session.window_handles
|
||||
name = session.execute_script("window.open()")
|
||||
assert len(session.window_handles) == len(windows_before) + 1
|
||||
new_windows = session.window_handles - windows_before
|
||||
return new_windows.pop()
|
||||
|
||||
|
||||
# TODO(ato): 7.1 Get
|
||||
|
||||
|
||||
def test_get_current_url_no_browsing_context(session, new_window):
|
||||
def test_get_current_url_no_browsing_context(session, create_window):
|
||||
# 7.2 step 1
|
||||
session.window_handle = new_window
|
||||
session.window_handle = create_window()
|
||||
session.close()
|
||||
with pytest.raises(webdriver.NoSuchWindowException):
|
||||
session.url = "about:blank"
|
||||
|
||||
result = session.transport.send("GET", "session/%s/url" % session.session_id)
|
||||
|
||||
assert_error(result, "no such window")
|
||||
|
||||
|
||||
def test_get_current_url_alert_prompt(session):
|
||||
# 7.2 step 2
|
||||
session.url = alert_doc
|
||||
with pytest.raises(webdriver.UnexpectedAlertOpenException):
|
||||
session.url = "about:blank"
|
||||
|
||||
result = session.transport.send("GET", "session/%s/url" % session.session_id)
|
||||
|
||||
assert_error(result, "unexpected alert open")
|
||||
|
||||
def test_get_current_url_matches_location(session):
|
||||
# 7.2 step 3
|
||||
url = session.execute_script("return window.location.href")
|
||||
assert session.url == url
|
||||
|
||||
|
||||
def test_get_current_url_payload(http, session):
|
||||
def test_get_current_url_payload(session):
|
||||
# 7.2 step 4-5
|
||||
session.start()
|
||||
with http.get("/session/%s/url" % session.session_id) as resp:
|
||||
assert resp.status == 200
|
||||
body = json.load(resp)
|
||||
assert "value" in body
|
||||
assert isinstance(body["value"], types.StringTypes)
|
||||
|
||||
result = session.transport.send("GET", "session/%s/url" % session.session_id)
|
||||
|
||||
assert result.status == 200
|
||||
assert isinstance(result.body["value"], basestring)
|
||||
|
||||
def test_get_current_url_special_pages(session):
|
||||
session.url = "about:blank"
|
||||
assert session.url == "about:blank"
|
||||
|
||||
result = session.transport.send("GET", "session/%s/url" % session.session_id)
|
||||
|
||||
"""
|
||||
Disabled due to https://bugzilla.mozilla.org/show_bug.cgi?id=1332122
|
||||
assert_success(result, "about:blank")
|
||||
|
||||
# TODO(ato): This test requires modification to pass on Windows
|
||||
def test_get_current_url_file_protocol(session):
|
||||
# tests that the browsing context remains the same
|
||||
# when navigated privileged documents
|
||||
session.url = "file:///"
|
||||
assert session.url == "file:///"
|
||||
"""
|
||||
|
||||
result = session.transport.send("GET", "session/%s/url" % session.session_id)
|
||||
|
||||
assert_success(result, "file:///")
|
||||
|
||||
# TODO(ato): Test for http:// and https:// protocols.
|
||||
# We need to expose a fixture for accessing
|
||||
# documents served by wptserve in order to test this.
|
||||
|
||||
def test_set_malformed_url(session):
|
||||
result = session.transport.send("POST",
|
||||
"session/%s/url" % session.session_id,
|
||||
{"url": "foo"})
|
||||
|
||||
def test_get_current_url_malformed_url(session):
|
||||
session.url = "foo"
|
||||
assert session.url
|
||||
|
||||
assert_error(result, "invalid argument")
|
||||
|
||||
def test_get_current_url_after_modified_location(session):
|
||||
session.execute_script("window.location.href = 'about:blank'")
|
||||
assert session.url == "about:blank"
|
||||
session.execute_script("window.location.href = 'about:blank#wd_test_modification'")
|
||||
|
||||
result = session.transport.send("GET", "session/%s/url" % session.session_id)
|
||||
|
||||
def test_get_current_url_nested_browsing_context(session):
|
||||
session.url = one_frame_doc
|
||||
top_level_url = session.url
|
||||
frame = session.find.css("iframe", all=False)
|
||||
session.switch_frame(frame)
|
||||
assert session.url == top_level_url
|
||||
assert_success(result, "about:blank#wd_test_modification")
|
||||
|
||||
def test_get_current_url_nested_browsing_context(session, create_frame):
|
||||
session.url = "about:blank#wd_from_within_frame"
|
||||
session.switch_frame(create_frame())
|
||||
|
||||
result = session.transport.send("GET", "session/%s/url" % session.session_id)
|
||||
|
||||
assert_success(result, "about:blank#wd_from_within_frame")
|
||||
|
||||
def test_get_current_url_nested_browsing_contexts(session):
|
||||
session.url = two_frames_doc
|
||||
|
@ -108,6 +97,6 @@ def test_get_current_url_nested_browsing_contexts(session):
|
|||
session.switch_frame(outer_frame)
|
||||
|
||||
inner_frame = session.find.css("iframe", all=False)
|
||||
session.switch_frame(frame)
|
||||
session.switch_frame(inner_frame)
|
||||
|
||||
assert session.url == top_level_url
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
from merge_dictionaries import merge_dictionaries
|
77
tests/wpt/web-platform-tests/webdriver/support/asserts.py
Normal file
77
tests/wpt/web-platform-tests/webdriver/support/asserts.py
Normal file
|
@ -0,0 +1,77 @@
|
|||
# WebDriver specification ID: dfn-error-response-data
|
||||
errors = {
|
||||
"element click intercepted": 400,
|
||||
"element not selectable": 400,
|
||||
"element not interactable": 400,
|
||||
"insecure certificate": 400,
|
||||
"invalid argument": 400,
|
||||
"invalid cookie domain": 400,
|
||||
"invalid coordinates": 400,
|
||||
"invalid element state": 400,
|
||||
"invalid selector": 400,
|
||||
"invalid session id": 404,
|
||||
"javascript error": 500,
|
||||
"move target out of bounds": 500,
|
||||
"no such alert": 400,
|
||||
"no such cookie": 404,
|
||||
"no such element": 404,
|
||||
"no such frame": 400,
|
||||
"no such window": 400,
|
||||
"script timeout": 408,
|
||||
"session not created": 500,
|
||||
"stale element reference": 400,
|
||||
"timeout": 408,
|
||||
"unable to set cookie": 500,
|
||||
"unable to capture screen": 500,
|
||||
"unexpected alert open": 500,
|
||||
"unknown command": 404,
|
||||
"unknown error": 500,
|
||||
"unknown method": 405,
|
||||
"unsupported operation": 500,
|
||||
}
|
||||
|
||||
# WebDriver specification ID: dfn-send-an-error
|
||||
#
|
||||
# > When required to send an error, with error code, a remote end must run the
|
||||
# > following steps:
|
||||
# >
|
||||
# > 1. Let http status and name be the error response data for error code.
|
||||
# > 2. Let message be an implementation-defined string containing a
|
||||
# > human-readable description of the reason for the error.
|
||||
# > 3. Let stacktrace be an implementation-defined string containing a stack
|
||||
# > trace report of the active stack frames at the time when the error
|
||||
# > occurred.
|
||||
# > 4. Let data be a new JSON Object initialised with the following properties:
|
||||
# >
|
||||
# > error
|
||||
# > name
|
||||
# > message
|
||||
# > message
|
||||
# > stacktrace
|
||||
# > stacktrace
|
||||
# >
|
||||
# > 5. Send a response with status and data as arguments.
|
||||
def assert_error(response, error_code):
|
||||
"""Verify that the provided wdclient.Response instance described a valid
|
||||
error response as defined by `dfn-send-an-error` and the provided error
|
||||
code.
|
||||
|
||||
:param response: wdclient.Response instance
|
||||
:param error_code: string value of the expected "error code"
|
||||
"""
|
||||
assert response.status == errors[error_code]
|
||||
assert "value" in response.body
|
||||
assert response.body["value"]["error"] == error_code
|
||||
assert isinstance(response.body["value"]["message"], basestring)
|
||||
assert isinstance(response.body["value"]["stacktrace"], basestring)
|
||||
|
||||
def assert_success(response, value):
|
||||
"""Verify that the provided wdclient.Response instance described a valid
|
||||
error response as defined by `dfn-send-an-error` and the provided error
|
||||
code.
|
||||
:param response: wdclient.Response instance
|
||||
:param value: expected value of the response body
|
||||
"""
|
||||
|
||||
assert response.status == 200
|
||||
assert response.body["value"] == value
|
144
tests/wpt/web-platform-tests/webdriver/support/fixtures.py
Normal file
144
tests/wpt/web-platform-tests/webdriver/support/fixtures.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
import json
|
||||
import os
|
||||
import urlparse
|
||||
|
||||
import webdriver
|
||||
|
||||
from support.http_request import HTTPRequest
|
||||
from support import merge_dictionaries
|
||||
|
||||
default_host = "http://127.0.0.1"
|
||||
default_port = "4444"
|
||||
|
||||
def _ensure_valid_window(session):
|
||||
"""If current window is not open anymore, ensure to have a valid one selected."""
|
||||
try:
|
||||
session.window_handle
|
||||
except webdriver.NoSuchWindowException:
|
||||
session.window_handle = session.handles[0]
|
||||
|
||||
|
||||
def _dismiss_user_prompts(session):
|
||||
"""Dismisses any open user prompts in windows."""
|
||||
current_window = session.window_handle
|
||||
|
||||
for window in _windows(session):
|
||||
session.window_handle = window
|
||||
try:
|
||||
session.alert.dismiss()
|
||||
except webdriver.NoSuchAlertException:
|
||||
pass
|
||||
|
||||
session.window_handle = current_window
|
||||
|
||||
def _restore_windows(session):
|
||||
"""Closes superfluous windows opened by the test without ending
|
||||
the session implicitly by closing the last window.
|
||||
"""
|
||||
current_window = session.window_handle
|
||||
|
||||
for window in _windows(session, exclude=[current_window]):
|
||||
session.window_handle = window
|
||||
if len(session.window_handles) > 1:
|
||||
session.close()
|
||||
|
||||
session.window_handle = current_window
|
||||
|
||||
def _switch_to_top_level_browsing_context(session):
|
||||
"""If the current browsing context selected by WebDriver is a
|
||||
`<frame>` or an `<iframe>`, switch it back to the top-level
|
||||
browsing context.
|
||||
"""
|
||||
session.switch_frame(None)
|
||||
|
||||
def _windows(session, exclude=None):
|
||||
"""Set of window handles, filtered by an `exclude` list if
|
||||
provided.
|
||||
"""
|
||||
if exclude is None:
|
||||
exclude = []
|
||||
wins = [w for w in session.handles if w not in exclude]
|
||||
return set(wins)
|
||||
|
||||
def create_frame(session):
|
||||
"""Create an `iframe` element in the current browsing context and insert it
|
||||
into the document. Return an element reference."""
|
||||
def create_frame():
|
||||
append = """
|
||||
var frame = document.createElement('iframe');
|
||||
document.body.appendChild(frame);
|
||||
return frame;
|
||||
"""
|
||||
response = session.execute_script(append)
|
||||
|
||||
return create_frame
|
||||
|
||||
def create_window(session):
|
||||
"""Open new window and return the window handle."""
|
||||
def create_window():
|
||||
windows_before = session.handles
|
||||
name = session.execute_script("window.open()")
|
||||
assert len(session.handles) == len(windows_before) + 1
|
||||
new_windows = list(set(session.handles) - set(windows_before))
|
||||
return new_windows.pop()
|
||||
return create_window
|
||||
|
||||
def http(session):
|
||||
return HTTPRequest(session.transport.host, session.transport.port)
|
||||
|
||||
def server_config():
|
||||
return json.loads(os.environ.get("WD_SERVER_CONFIG"))
|
||||
|
||||
def create_session(request):
|
||||
"""Provide a factory function that produces wdclient `Session` instances.
|
||||
If the `WD_CAPABILITIES` environment variable is set, it will be parsed as
|
||||
JSON and the resulting object will be included in the WebDriver "Create
|
||||
Session" command. Additional capabilities may be specified as an optional
|
||||
argument to this function, but the operation will fail if any values
|
||||
conflict with those specified via the environment. If the session is still
|
||||
active at the completion of the test, it will be destroyed
|
||||
automatically."""
|
||||
|
||||
def create_session(test_capabilities=None):
|
||||
host = os.environ.get("WD_HOST", default_host)
|
||||
port = int(os.environ.get("WD_PORT", default_port))
|
||||
if test_capabilities is None:
|
||||
test_capabilities = {}
|
||||
env_capabilities = json.loads(os.environ.get("WD_CAPABILITIES", "{}"))
|
||||
|
||||
capabilities = merge_dictionaries(env_capabilities, test_capabilities)
|
||||
session = webdriver.Session(host, port, capabilities=capabilities)
|
||||
|
||||
def destroy():
|
||||
if session.session_id is not None:
|
||||
session.end()
|
||||
|
||||
# finalisers are popped off a stack, making their ordering reverse
|
||||
request.addfinalizer(destroy)
|
||||
request.addfinalizer(lambda: _switch_to_top_level_browsing_context(session))
|
||||
request.addfinalizer(lambda: _restore_windows(session))
|
||||
request.addfinalizer(lambda: _dismiss_user_prompts(session))
|
||||
request.addfinalizer(lambda: _ensure_valid_window(session))
|
||||
|
||||
return session
|
||||
|
||||
return create_session
|
||||
|
||||
# Create a wdclient `Session` object for each Pytest "session". If the
|
||||
# `WD_CAPABILITIES` environment variable is set, it will be parsed as JSON and
|
||||
# the resulting object will be included in the WebDriver "Create Session"
|
||||
# command. If the session is still active at the completion of the test, it
|
||||
# will be destroyed automatically.
|
||||
def session(create_session):
|
||||
return create_session()
|
||||
|
||||
def url(server_config):
|
||||
def inner(path, query="", fragment=""):
|
||||
rv = urlparse.urlunsplit(("http",
|
||||
"%s:%s" % (server_config["host"],
|
||||
server_config["ports"]["http"][0]),
|
||||
path,
|
||||
query,
|
||||
fragment))
|
||||
return rv
|
||||
return inner
|
19
tests/wpt/web-platform-tests/webdriver/support/inline.py
Normal file
19
tests/wpt/web-platform-tests/webdriver/support/inline.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
import urllib
|
||||
|
||||
def inline(doc, doctype="html", mime="text/html;charset=utf-8"):
|
||||
if doctype == "html":
|
||||
mime = "text/html;charset=utf-8"
|
||||
elif doctype == "xhtml":
|
||||
mime = "application/xhtml+xml"
|
||||
doc = r"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>XHTML might be the future</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{}
|
||||
</body>
|
||||
</html>""".format(doc)
|
||||
return "data:{},{}".format(mime, urllib.quote(doc))
|
|
@ -0,0 +1,49 @@
|
|||
def iteritems(d):
|
||||
"""Create a key-value iterator for the given dict in both Python 2.x and
|
||||
Python 3.x environments"""
|
||||
if hasattr(d, "iteritems"):
|
||||
return d.iteritems()
|
||||
return d.items()
|
||||
|
||||
def merge_dictionaries(first, second):
|
||||
"""Given two dictionaries, create a third that defines all specified
|
||||
key/value pairs. This merge_dictionaries is performed "deeply" on any nested
|
||||
dictionaries. If a value is defined for the same key by both dictionaries,
|
||||
an exception will be raised."""
|
||||
result = dict(first)
|
||||
|
||||
for key, value in iteritems(second):
|
||||
if key in result and result[key] != value:
|
||||
if isinstance(result[key], dict) and isinstance(value, dict):
|
||||
result[key] = merge_dictionaries(result[key], value)
|
||||
elif result[key] != value:
|
||||
raise TypeError("merge_dictionaries: refusing to overwrite " +
|
||||
"attribute: `%s`" % key)
|
||||
else:
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
assert merge_dictionaries({}, {}) == {}
|
||||
assert merge_dictionaries({}, {"a": 23}) == {"a": 23}
|
||||
assert merge_dictionaries({"a": 23}, {"b": 45}) == {"a": 23, "b": 45}
|
||||
|
||||
e = None
|
||||
try:
|
||||
merge_dictionaries({"a": 23}, {"a": 45})
|
||||
except Exception as _e:
|
||||
e = _e
|
||||
assert isinstance(e, TypeError)
|
||||
|
||||
assert merge_dictionaries({"a": 23}, {"a": 23}) == {"a": 23}
|
||||
|
||||
assert merge_dictionaries({"a": {"b": 23}}, {"a": {"c": 45}}) == {"a": {"b": 23, "c": 45}}
|
||||
assert merge_dictionaries({"a": {"b": 23}}, {"a": {"b": 23}}) == {"a": {"b": 23}}
|
||||
|
||||
e = None
|
||||
try:
|
||||
merge_dictionaries({"a": {"b": 23}}, {"a": {"b": 45}})
|
||||
except Exception as _e:
|
||||
e = _e
|
||||
assert isinstance(e, TypeError)
|
|
@ -1 +0,0 @@
|
|||
pass
|
|
@ -1,43 +0,0 @@
|
|||
import webdriver
|
||||
|
||||
def dismiss_user_prompts(session):
|
||||
"""Dismisses any open user prompts in windows."""
|
||||
current_window = session.window_handle
|
||||
|
||||
for window in _windows(session):
|
||||
session.window_handle = window
|
||||
try:
|
||||
session.alert.dismiss()
|
||||
except webdriver.NoSuchAlertException:
|
||||
pass
|
||||
|
||||
session.window_handle = current_window
|
||||
|
||||
def restore_windows(session):
|
||||
"""Closes superfluous windows opened by the test without ending
|
||||
the session implicitly by closing the last window.
|
||||
"""
|
||||
current_window = session.window_handle
|
||||
|
||||
for window in _windows(session, exclude=[current_window]):
|
||||
session.window_handle = window
|
||||
if len(session.window_handles) > 1:
|
||||
session.close()
|
||||
|
||||
session.window_handle = current_window
|
||||
|
||||
def switch_to_top_level_browsing_context(session):
|
||||
"""If the current browsing context selected by WebDriver is a
|
||||
`<frame>` or an `<iframe>`, switch it back to the top-level
|
||||
browsing context.
|
||||
"""
|
||||
session.switch_frame(None)
|
||||
|
||||
def _windows(session, exclude=None):
|
||||
"""Set of window handles, filtered by an `exclude` list if
|
||||
provided.
|
||||
"""
|
||||
if exclude is None:
|
||||
exclude = []
|
||||
wins = [w for w in session.handles if w not in exclude]
|
||||
return set(wins)
|
Loading…
Add table
Add a link
Reference in a new issue