Unreviewed. Update W3C WebDriver imported tests.
Tools:
* Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py:
(WebDriverW3CExecutor.__init__):
WebDriverTests:
* imported/w3c/importer.json:
* imported/w3c/tools/webdriver/webdriver/client.py:
* imported/w3c/tools/webdriver/webdriver/transport.py:
* imported/w3c/tools/wptrunner/README.rst:
* imported/w3c/tools/wptrunner/requirements_chrome.txt:
* imported/w3c/tools/wptrunner/requirements_edge.txt:
* imported/w3c/tools/wptrunner/requirements_firefox.txt:
* imported/w3c/tools/wptrunner/requirements_ie.txt:
* imported/w3c/tools/wptrunner/requirements_opera.txt:
* imported/w3c/tools/wptrunner/requirements_safari.txt: Added.
* imported/w3c/tools/wptrunner/requirements_sauce.txt:
* imported/w3c/tools/wptrunner/requirements_webkit.txt: Added.
* imported/w3c/tools/wptrunner/tox.ini:
* imported/w3c/tools/wptrunner/wptrunner/browsers/__init__.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/chrome.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/chrome_android.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/edge.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/ie.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/opera.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/safari.py: Added.
* imported/w3c/tools/wptrunner/wptrunner/browsers/sauce.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat:
* imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh:
* imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/servodriver.py:
* imported/w3c/tools/wptrunner/wptrunner/browsers/webkit.py: Added.
* imported/w3c/tools/wptrunner/wptrunner/environment.py:
* imported/w3c/tools/wptrunner/wptrunner/executors/base.py:
* imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py:
* imported/w3c/tools/wptrunner/wptrunner/executors/executorselenium.py:
* imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py:
* imported/w3c/tools/wptrunner/wptrunner/executors/executorservodriver.py:
* imported/w3c/tools/wptrunner/wptrunner/executors/executorwebkit.py: Added.
* imported/w3c/tools/wptrunner/wptrunner/executors/protocol.py: Added.
* imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py:
* imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette.js:
* imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette_resume.js: Added.
* imported/w3c/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js:
* imported/w3c/tools/wptrunner/wptrunner/testdriver-extra.js:
* imported/w3c/tools/wptrunner/wptrunner/testloader.py:
* imported/w3c/tools/wptrunner/wptrunner/testrunner.py:
* imported/w3c/tools/wptrunner/wptrunner/tests/base.py: Added.
* imported/w3c/tools/wptrunner/wptrunner/tests/test_products.py: Added.
* imported/w3c/tools/wptrunner/wptrunner/update/metadata.py:
* imported/w3c/tools/wptrunner/wptrunner/update/update.py:
* imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py:
* imported/w3c/tools/wptrunner/wptrunner/wptcommandline.py:
* imported/w3c/tools/wptrunner/wptrunner/wptrunner.py:
* imported/w3c/tools/wptrunner/wptrunner/wpttest.py:
* imported/w3c/webdriver/tests/actions/modifier_click.py:
* imported/w3c/webdriver/tests/actions/mouse_dblclick.py:
* imported/w3c/webdriver/tests/actions/mouse_pause_dblclick.py: Added.
* imported/w3c/webdriver/tests/actions/special_keys.py:
* imported/w3c/webdriver/tests/contexts/maximize_window.py:
* imported/w3c/webdriver/tests/cookies/add_cookie.py:
* imported/w3c/webdriver/tests/element_retrieval/find_element.py:
* imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py:
* imported/w3c/webdriver/tests/element_retrieval/find_elements.py:
* imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py:
* imported/w3c/webdriver/tests/element_send_keys/form_controls.py:
* imported/w3c/webdriver/tests/execute_async_script/collections.py: Added.
* imported/w3c/webdriver/tests/execute_async_script/user_prompts.py:
* imported/w3c/webdriver/tests/execute_script/collections.py: Added.
* imported/w3c/webdriver/tests/execute_script/user_prompts.py:
* imported/w3c/webdriver/tests/fullscreen_window.py:
* imported/w3c/webdriver/tests/interaction/element_clear.py:
* imported/w3c/webdriver/tests/minimize_window.py:
* imported/w3c/webdriver/tests/set_window_rect.py:
* imported/w3c/webdriver/tests/support/fixtures.py:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@230953 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index 369a13c..f9a74df 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,10 @@
+2018-04-24 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ Unreviewed. Update W3C WebDriver imported tests.
+
+ * Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py:
+ (WebDriverW3CExecutor.__init__):
+
2018-04-24 Zan Dobersek <zdobersek@igalia.com>
[WPE] Remove libgbm dependency
diff --git a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py
index 6461704..c54e062 100644
--- a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py
+++ b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py
@@ -133,7 +133,7 @@
def __init__(self, driver, server, env, timeout, expectations):
WebKitDriverServer.test_env = env
WebKitDriverServer.test_env.update(driver.browser_env())
- server_config = {'host': server.host(), 'domains': {'': server.host()}, 'ports': {'http': [str(server.port())]}}
+ server_config = {'browser_host': server.host(), 'domains': {'': server.host()}, 'ports': {'http': [str(server.port())]}}
WdspecExecutor.__init__(self, driver.browser_name(), server_config, driver.binary_path(), None, capabilities=driver.capabilities())
self._timeout = timeout
diff --git a/WebDriverTests/ChangeLog b/WebDriverTests/ChangeLog
index fc30140..4838a27 100644
--- a/WebDriverTests/ChangeLog
+++ b/WebDriverTests/ChangeLog
@@ -1,3 +1,78 @@
+2018-04-24 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ Unreviewed. Update W3C WebDriver imported tests.
+
+ * imported/w3c/importer.json:
+ * imported/w3c/tools/webdriver/webdriver/client.py:
+ * imported/w3c/tools/webdriver/webdriver/transport.py:
+ * imported/w3c/tools/wptrunner/README.rst:
+ * imported/w3c/tools/wptrunner/requirements_chrome.txt:
+ * imported/w3c/tools/wptrunner/requirements_edge.txt:
+ * imported/w3c/tools/wptrunner/requirements_firefox.txt:
+ * imported/w3c/tools/wptrunner/requirements_ie.txt:
+ * imported/w3c/tools/wptrunner/requirements_opera.txt:
+ * imported/w3c/tools/wptrunner/requirements_safari.txt: Added.
+ * imported/w3c/tools/wptrunner/requirements_sauce.txt:
+ * imported/w3c/tools/wptrunner/requirements_webkit.txt: Added.
+ * imported/w3c/tools/wptrunner/tox.ini:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/__init__.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/chrome.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/chrome_android.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/edge.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/ie.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/opera.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/safari.py: Added.
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/sauce.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/servodriver.py:
+ * imported/w3c/tools/wptrunner/wptrunner/browsers/webkit.py: Added.
+ * imported/w3c/tools/wptrunner/wptrunner/environment.py:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/base.py:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/executorselenium.py:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/executorservodriver.py:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/executorwebkit.py: Added.
+ * imported/w3c/tools/wptrunner/wptrunner/executors/protocol.py: Added.
+ * imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette.js:
+ * imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette_resume.js: Added.
+ * imported/w3c/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js:
+ * imported/w3c/tools/wptrunner/wptrunner/testdriver-extra.js:
+ * imported/w3c/tools/wptrunner/wptrunner/testloader.py:
+ * imported/w3c/tools/wptrunner/wptrunner/testrunner.py:
+ * imported/w3c/tools/wptrunner/wptrunner/tests/base.py: Added.
+ * imported/w3c/tools/wptrunner/wptrunner/tests/test_products.py: Added.
+ * imported/w3c/tools/wptrunner/wptrunner/update/metadata.py:
+ * imported/w3c/tools/wptrunner/wptrunner/update/update.py:
+ * imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py:
+ * imported/w3c/tools/wptrunner/wptrunner/wptcommandline.py:
+ * imported/w3c/tools/wptrunner/wptrunner/wptrunner.py:
+ * imported/w3c/tools/wptrunner/wptrunner/wpttest.py:
+ * imported/w3c/webdriver/tests/actions/modifier_click.py:
+ * imported/w3c/webdriver/tests/actions/mouse_dblclick.py:
+ * imported/w3c/webdriver/tests/actions/mouse_pause_dblclick.py: Added.
+ * imported/w3c/webdriver/tests/actions/special_keys.py:
+ * imported/w3c/webdriver/tests/contexts/maximize_window.py:
+ * imported/w3c/webdriver/tests/cookies/add_cookie.py:
+ * imported/w3c/webdriver/tests/element_retrieval/find_element.py:
+ * imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py:
+ * imported/w3c/webdriver/tests/element_retrieval/find_elements.py:
+ * imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py:
+ * imported/w3c/webdriver/tests/element_send_keys/form_controls.py:
+ * imported/w3c/webdriver/tests/execute_async_script/collections.py: Added.
+ * imported/w3c/webdriver/tests/execute_async_script/user_prompts.py:
+ * imported/w3c/webdriver/tests/execute_script/collections.py: Added.
+ * imported/w3c/webdriver/tests/execute_script/user_prompts.py:
+ * imported/w3c/webdriver/tests/fullscreen_window.py:
+ * imported/w3c/webdriver/tests/interaction/element_clear.py:
+ * imported/w3c/webdriver/tests/minimize_window.py:
+ * imported/w3c/webdriver/tests/set_window_rect.py:
+ * imported/w3c/webdriver/tests/support/fixtures.py:
+
2018-03-27 Brian Burg <bburg@apple.com>
REGRESSION(r229937): WebDriver tests no longer run, test runner hangs when launching wpt web server
diff --git a/WebDriverTests/imported/w3c/importer.json b/WebDriverTests/imported/w3c/importer.json
index fb47860..572547c 100644
--- a/WebDriverTests/imported/w3c/importer.json
+++ b/WebDriverTests/imported/w3c/importer.json
@@ -1,6 +1,6 @@
{
"repository": "https://github.com/w3c/web-platform-tests.git",
- "revision": "549b9cc8d48cfb683eecb3fd3909f93001d2e8f6",
+ "revision": "564cfb3a6bd13e949d5c49ad6e5f2cb3752173f3",
"paths_to_import": [
"tools/webdriver",
"tools/wptrunner",
diff --git a/WebDriverTests/imported/w3c/tools/webdriver/webdriver/client.py b/WebDriverTests/imported/w3c/tools/webdriver/webdriver/client.py
index 622c5fc..8da14a0 100644
--- a/WebDriverTests/imported/w3c/tools/webdriver/webdriver/client.py
+++ b/WebDriverTests/imported/w3c/tools/webdriver/webdriver/client.py
@@ -6,10 +6,6 @@
from six import string_types
-from mozlog import get_default_logger
-
-logger = get_default_logger()
-
def command(func):
def inner(self, *args, **kwargs):
@@ -371,6 +367,9 @@
self.alert = UserPrompt(self)
self.actions = Actions(self)
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__, self.session_id or "(disconnected)")
+
def __eq__(self, other):
return (self.session_id is not None and isinstance(other, Session) and
self.session_id == other.session_id)
@@ -632,6 +631,9 @@
assert id not in self.session._element_cache
self.session._element_cache[self.id] = self
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__, self.id)
+
def __eq__(self, other):
return (isinstance(other, Element) and self.id == other.id and
self.session == other.session)
diff --git a/WebDriverTests/imported/w3c/tools/webdriver/webdriver/transport.py b/WebDriverTests/imported/w3c/tools/webdriver/webdriver/transport.py
index 9a1670a..960cb37 100644
--- a/WebDriverTests/imported/w3c/tools/webdriver/webdriver/transport.py
+++ b/WebDriverTests/imported/w3c/tools/webdriver/webdriver/transport.py
@@ -131,13 +131,16 @@
if body is None and method == "POST":
body = {}
- try:
- payload = json.dumps(body, cls=encoder, **codec_kwargs)
- except ValueError:
- raise ValueError("Failed to encode request body as JSON:\n"
- "%s" % json.dumps(body, indent=2))
- if isinstance(payload, text_type):
- payload = body.encode("utf-8")
+ payload = None
+ if body is not None:
+ try:
+ payload = json.dumps(body, cls=encoder, **codec_kwargs)
+ except ValueError:
+ raise ValueError("Failed to encode request body as JSON:\n"
+ "%s" % json.dumps(body, indent=2))
+
+ if isinstance(payload, text_type):
+ payload = body.encode("utf-8")
if headers is None:
headers = {}
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/README.rst b/WebDriverTests/imported/w3c/tools/wptrunner/README.rst
index 4890e3a..8917922 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/README.rst
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/README.rst
@@ -179,7 +179,7 @@
key: value
-Note that unlike ini files, only `:` is a valid seperator; `=` will
+Note that unlike ini files, only `:` is a valid separator; `=` will
not work as expected. Key-value pairs may also have conditional
values of the form::
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_chrome.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_chrome.txt
index 25cc584..b5e4806 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_chrome.txt
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_chrome.txt
@@ -1,2 +1,2 @@
mozprocess == 0.26
-selenium == 3.9.0
+selenium==3.11.0
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_edge.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_edge.txt
index 25cc584..b5e4806 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_edge.txt
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_edge.txt
@@ -1,2 +1,2 @@
mozprocess == 0.26
-selenium == 3.9.0
+selenium==3.11.0
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_firefox.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_firefox.txt
index 43413cf..79fde78 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_firefox.txt
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_firefox.txt
@@ -1,6 +1,8 @@
-marionette_driver == 2.5.0
-mozprofile == 0.29
+marionette_driver==2.6.0
+mozprofile==1.0.0
mozprocess == 0.26
mozcrash == 1.0
-mozrunner == 6.14
+mozrunner==6.15
mozleak == 0.1
+mozinstall == 1.15
+mozdownload == 1.23
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_ie.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_ie.txt
index 25cc584..b5e4806 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_ie.txt
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_ie.txt
@@ -1,2 +1,2 @@
mozprocess == 0.26
-selenium == 3.9.0
+selenium==3.11.0
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_opera.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_opera.txt
index 25cc584..b5e4806 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_opera.txt
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_opera.txt
@@ -1,2 +1,2 @@
mozprocess == 0.26
-selenium == 3.9.0
+selenium==3.11.0
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_safari.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_safari.txt
new file mode 100644
index 0000000..b5e4806
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_safari.txt
@@ -0,0 +1,2 @@
+mozprocess == 0.26
+selenium==3.11.0
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_sauce.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_sauce.txt
index 51bce11..e0ae7e2 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_sauce.txt
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_sauce.txt
@@ -1,3 +1,3 @@
mozprocess == 0.26
-selenium == 3.9.0
-requests
+selenium==3.11.0
+requests==2.18.4
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/requirements_webkit.txt b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_webkit.txt
new file mode 100644
index 0000000..25cc584
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/requirements_webkit.txt
@@ -0,0 +1,2 @@
+mozprocess == 0.26
+selenium == 3.9.0
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/tox.ini b/WebDriverTests/imported/w3c/tools/wptrunner/tox.ini
index 9be8c0e..f63e2c0 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/tox.ini
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/tox.ini
@@ -2,7 +2,7 @@
xfail_strict=true
[tox]
-envlist = {py27,pypy}-{base,chrome,firefox,sauce,servo},py27-flake8
+envlist = {py27}-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo},py27-flake8
[testenv]
deps =
@@ -12,12 +12,18 @@
mock
-r{toxinidir}/requirements.txt
chrome: -r{toxinidir}/requirements_chrome.txt
+ edge: -r{toxinidir}/requirements_edge.txt
firefox: -r{toxinidir}/requirements_firefox.txt
+ ie: -r{toxinidir}/requirements_ie.txt
+ opera: -r{toxinidir}/requirements_opera.txt
+ safari: -r{toxinidir}/requirements_safari.txt
sauce: -r{toxinidir}/requirements_sauce.txt
servo: -r{toxinidir}/requirements_servo.txt
commands = pytest {posargs:--cov}
+setenv = CURRENT_TOX_ENV = {envname}
+
[testenv:py27-flake8]
# flake8 versions should be kept in sync across tools/tox.ini, tools/wpt/tox.ini, and tools/wptrunner/tox.ini
deps =
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/__init__.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/__init__.py
index 1e74863..6f0c49e 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/__init__.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/__init__.py
@@ -27,7 +27,9 @@
"edge",
"firefox",
"ie",
+ "safari",
"sauce",
"servo",
"servodriver",
- "opera"]
+ "opera",
+ "webkit"]
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome.py
index 7f9a21c..e50c592 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome.py
@@ -60,7 +60,7 @@
def env_options():
- return {"bind_hostname": "true"}
+ return {}
class ChromeBrowser(Browser):
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome_android.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome_android.py
index 3e832cb..985b1fe 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome_android.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/chrome_android.py
@@ -68,7 +68,7 @@
def env_options():
- return {"bind_hostname": "true"}
+ return {}
class ChromeAndroidBrowser(Browser):
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/edge.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/edge.py
index 094405c..184ae32 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/edge.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/edge.py
@@ -38,8 +38,7 @@
return []
def env_options():
- return {"bind_hostname": "true",
- "supports_debugger": False}
+ return {"supports_debugger": False}
class EdgeBrowser(Browser):
used_ports = set()
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py
index acec0ef..0a0ca7e 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -102,7 +102,7 @@
if kwargs["binary_args"]:
options["args"] = kwargs["binary_args"]
options["prefs"] = {
- "network.dns.localDomains": ",".join(server_config['domains'].values())
+ "network.dns.localDomains": ",".join(server_config.domains.itervalues())
}
capabilities["moz:firefoxOptions"] = options
if kwargs["certutil_binary"] is None:
@@ -122,10 +122,8 @@
# domains to localhost without relying on the network stack.
#
# https://github.com/w3c/web-platform-tests/pull/9480
- return {"host": "127.0.0.1",
- "external_host": "web-platform.test",
- "bind_hostname": "false",
- "certificate_domain": "web-platform.test",
+ return {"server_host": "127.0.0.1",
+ "bind_address": False,
"supports_debugger": True}
@@ -135,8 +133,8 @@
def update_properties():
- return (["debug", "stylo", "e10s", "os", "version", "processor", "bits"],
- {"debug", "e10s", "stylo"})
+ return (["debug", "webrender", "e10s", "os", "version", "processor", "bits"],
+ {"debug", "e10s", "webrender"})
class FirefoxBrowser(Browser):
@@ -200,7 +198,7 @@
self.profile = FirefoxProfile(preferences=preferences)
self.profile.set_preferences({"marionette.port": self.marionette_port,
"dom.disable_open_during_load": False,
- "network.dns.localDomains": ",".join(self.config['domains'].values()),
+ "network.dns.localDomains": ",".join(self.config.domains.itervalues()),
"network.proxy.type": 0,
"places.history.enabled": False,
"dom.send_after_paint_to_content": True,
@@ -304,12 +302,15 @@
def on_output(self, line):
"""Write a line of output from the firefox process to the log"""
- data = line.decode("utf8", "replace")
- if self.stack_fixer:
- data = self.stack_fixer(data)
- self.logger.process_output(self.pid(),
- data,
- command=" ".join(self.runner.command))
+ if "GLib-GObject-CRITICAL" in line:
+ return
+ if line:
+ data = line.decode("utf8", "replace")
+ if self.stack_fixer:
+ data = self.stack_fixer(data)
+ self.logger.process_output(self.pid(),
+ data,
+ command=" ".join(self.runner.command))
def is_alive(self):
if self.runner:
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/ie.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/ie.py
index 9c0007e..97d96ec 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/ie.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/ie.py
@@ -42,8 +42,7 @@
return []
def env_options():
- return {"bind_hostname": "true",
- "supports_debugger": False}
+ return {"supports_debugger": False}
class InternetExplorerBrowser(Browser):
used_ports = set()
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/opera.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/opera.py
index 693a19a..bfacfa5 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/opera.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/opera.py
@@ -60,7 +60,7 @@
def env_options():
- return {"bind_hostname": "true"}
+ return {}
class OperaBrowser(Browser):
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/safari.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/safari.py
new file mode 100644
index 0000000..3b99d22
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/safari.py
@@ -0,0 +1,84 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from ..webdriver_server import SafariDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorselenium import (SeleniumTestharnessExecutor,
+ SeleniumRefTestExecutor)
+
+
+__wptrunner__ = {"product": "safari",
+ "check_args": "check_args",
+ "browser": "SafariBrowser",
+ "executor": {"testharness": "SeleniumTestharnessExecutor",
+ "reftest": "SeleniumRefTestExecutor"},
+ "browser_kwargs": "browser_kwargs",
+ "executor_kwargs": "executor_kwargs",
+ "env_extras": "env_extras",
+ "env_options": "env_options"}
+
+
+def check_args(**kwargs):
+ require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(test_type, run_info_data, **kwargs):
+ return {"webdriver_binary": kwargs["webdriver_binary"],
+ "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
+ **kwargs):
+ from selenium.webdriver import DesiredCapabilities
+
+ executor_kwargs = base_executor_kwargs(test_type, server_config,
+ cache_manager, **kwargs)
+ executor_kwargs["close_after_done"] = True
+ executor_kwargs["capabilities"] = dict(DesiredCapabilities.SAFARI.items())
+ if kwargs["binary"] is not None:
+ raise ValueError("Safari doesn't support setting executable location")
+
+ return executor_kwargs
+
+
+def env_extras(**kwargs):
+ return []
+
+
+def env_options():
+ return {}
+
+
+class SafariBrowser(Browser):
+ """Safari is backed by safaridriver, which is supplied through
+ ``wptrunner.webdriver.SafariDriverServer``.
+ """
+
+ def __init__(self, logger, webdriver_binary, webdriver_args=None):
+ """Creates a new representation of Safari. The `webdriver_binary`
+ argument gives the WebDriver binary to use for testing. (The browser
+ binary location cannot be specified, as Safari and SafariDriver are
+ coupled.)"""
+ Browser.__init__(self, logger)
+ self.server = SafariDriverServer(self.logger,
+ binary=webdriver_binary,
+ args=webdriver_args)
+
+ def start(self, **kwargs):
+ self.server.start(block=False)
+
+ def stop(self, force=False):
+ self.server.stop(force=force)
+
+ def pid(self):
+ return self.server.pid
+
+ def is_alive(self):
+ # TODO(ato): This only indicates the driver is alive,
+ # and doesn't say anything about whether a browser session
+ # is active.
+ return self.server.is_alive()
+
+ def cleanup(self):
+ self.stop()
+
+ def executor_browser(self):
+ return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce.py
index 69ebc07..9ae2f7e 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce.py
@@ -113,8 +113,7 @@
def env_options():
- return {"bind_hostname": "true",
- "supports_debugger": False}
+ return {"supports_debugger": False}
def get_tar(url, dest):
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat
index 4554894..9d0878e 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/edge-prerun.bat
@@ -1,2 +1,9 @@
@echo off
reg add "HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\New Windows" /v "PopupMgr" /t REG_SZ /d no
+
+
+REM Download and install the Ahem font
+REM - https://wiki.saucelabs.com/display/DOCS/Downloading+Files+to+a+Sauce+Labs+Virtual+Machine+Prior+to+Testing
+REM - https://superuser.com/questions/201896/how-do-i-install-a-font-from-the-windows-command-prompt
+bitsadmin.exe /transfer "JobName" https://github.com/w3c/web-platform-tests/raw/master/fonts/Ahem.ttf "%WINDIR%\Fonts\Ahem.ttf"
+reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /v "Ahem (TrueType)" /t REG_SZ /d Ahem.ttf /f
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh
index 85c72e6..06c48bd 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/sauce_setup/safari-prerun.sh
@@ -1,2 +1,3 @@
#!/bin/bash
+curl https://raw.githubusercontent.com/w3c/web-platform-tests/master/fonts/Ahem.ttf > ~/Library/Fonts/Ahem.ttf
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool true
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py
index f163631..dd54fb0 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py
@@ -52,9 +52,8 @@
def env_options():
- return {"host": "127.0.0.1",
- "external_host": "web-platform.test",
- "bind_hostname": False,
+ return {"server_host": "127.0.0.1",
+ "bind_address": False,
"testharnessreport": "testharnessreport-servo.js",
"supports_debugger": True}
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servodriver.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servodriver.py
index 89504b2..f2ee00a 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servodriver.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servodriver.py
@@ -5,7 +5,7 @@
from mozprocess import ProcessHandler
-from tools.serve.serve import make_hosts_file
+from serve.serve import make_hosts_file
from .base import Browser, require_arg, get_free_port, browser_command, ExecutorBrowser
from ..executors import executor_kwargs as base_executor_kwargs
@@ -53,9 +53,7 @@
def env_options():
- return {"host": "127.0.0.1",
- "external_host": "web-platform.test",
- "bind_hostname": "true",
+ return {"server_host": "127.0.0.1",
"testharnessreport": "testharnessreport-servodriver.js",
"supports_debugger": True}
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/webkit.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/webkit.py
new file mode 100644
index 0000000..7d95d43
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/webkit.py
@@ -0,0 +1,98 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorselenium import (SeleniumTestharnessExecutor,
+ SeleniumRefTestExecutor)
+from ..executors.executorwebkit import WebKitDriverWdspecExecutor
+from ..webdriver_server import WebKitDriverServer
+
+
+__wptrunner__ = {"product": "webkit",
+ "check_args": "check_args",
+ "browser": "WebKitBrowser",
+ "browser_kwargs": "browser_kwargs",
+ "executor": {"testharness": "SeleniumTestharnessExecutor",
+ "reftest": "SeleniumRefTestExecutor",
+ "wdspec": "WebKitDriverWdspecExecutor"},
+ "executor_kwargs": "executor_kwargs",
+ "env_extras": "env_extras",
+ "env_options": "env_options"}
+
+
+def check_args(**kwargs):
+ require_arg(kwargs, "binary")
+ require_arg(kwargs, "webdriver_binary")
+ require_arg(kwargs, "webkit_port")
+
+
+def browser_kwargs(test_type, run_info_data, **kwargs):
+ return {"binary": kwargs["binary"],
+ "webdriver_binary": kwargs["webdriver_binary"],
+ "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def capabilities_for_port(webkit_port, binary, binary_args):
+ from selenium.webdriver import DesiredCapabilities
+
+ if webkit_port == "gtk":
+ capabilities = dict(DesiredCapabilities.WEBKITGTK.copy())
+ capabilities["webkitgtk:browserOptions"] = {
+ "binary": binary,
+ "args": binary_args
+ }
+ return capabilities
+
+ return {}
+
+
+def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
+ **kwargs):
+ executor_kwargs = base_executor_kwargs(test_type, server_config,
+ cache_manager, **kwargs)
+ executor_kwargs["close_after_done"] = True
+ capabilities = capabilities_for_port(kwargs["webkit_port"],
+ kwargs["binary"],
+ kwargs.get("binary_args", []))
+ executor_kwargs["capabilities"] = capabilities
+ return executor_kwargs
+
+
+def env_extras(**kwargs):
+ return []
+
+
+def env_options():
+ return {}
+
+
+class WebKitBrowser(Browser):
+ """Generic WebKit browser is backed by WebKit's WebDriver implementation,
+ which is supplied through ``wptrunner.webdriver.WebKitDriverServer``.
+ """
+
+ def __init__(self, logger, binary, webdriver_binary=None,
+ webdriver_args=None):
+ Browser.__init__(self, logger)
+ self.binary = binary
+ self.server = WebKitDriverServer(self.logger, binary=webdriver_binary,
+ args=webdriver_args)
+
+ def start(self, **kwargs):
+ self.server.start(block=False)
+
+ def stop(self, force=False):
+ self.server.stop(force=force)
+
+ def pid(self):
+ return self.server.pid
+
+ def is_alive(self):
+ # TODO(ato): This only indicates the driver is alive,
+ # and doesn't say anything about whether a browser session
+ # is active.
+ return self.server.is_alive()
+
+ def cleanup(self):
+ self.stop()
+
+ def executor_browser(self):
+ return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py
index 8ecbb4b..c5e31b7 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py
@@ -94,8 +94,6 @@
self.config = self.load_config()
self.setup_server_logging()
- ports = serve.get_ports(self.config, self.ssl_env)
- self.config = serve.normalise_config(self.config, ports)
assert self.env_extras_cms is None, (
"A TestEnvironment object cannot be nested")
@@ -107,7 +105,8 @@
cm.__enter__()
self.env_extras_cms.append(cm)
- self.servers = serve.start(self.config, self.ssl_env,
+ self.servers = serve.start(self.config,
+ self.ssl_env,
self.get_routes())
if self.options.get("supports_debugger") and self.debug_info and self.debug_info.interactive:
self.ignore_interrupts()
@@ -136,43 +135,36 @@
def load_config(self):
default_config_path = os.path.join(serve_path(self.test_paths), "config.default.json")
- local_config = {
- "ports": {
- "http": [8000, 8001],
- "https": [8443],
- "ws": [8888]
- },
- "check_subdomains": False,
- "bind_hostname": self.options["bind_hostname"],
- "ssl": {}
- }
-
- if "host" in self.options:
- local_config["host"] = self.options["host"]
+ override_path = os.path.join(serve_path(self.test_paths), "config.json")
with open(default_config_path) as f:
default_config = json.load(f)
- #TODO: allow non-default configuration for ssl
+ config = serve.Config(override_ssl_env=self.ssl_env, **default_config)
- local_config["external_host"] = self.options.get("external_host", None)
- local_config["ssl"]["encrypt_after_connect"] = self.options.get("encrypt_after_connect", False)
+ config.ports = {
+ "http": [8000, 8001],
+ "https": [8443],
+ "ws": [8888]
+ }
- config = serve.merge_json(default_config, local_config)
- config["doc_root"] = serve_path(self.test_paths)
+ if os.path.exists(override_path):
+ with open(override_path) as f:
+ override_obj = json.load(f)
+ config.update(override_obj)
- if not self.ssl_env.ssl_enabled:
- config["ports"]["https"] = [None]
+ config.check_subdomains = False
+ config.ssl = {}
- host = self.options.get("certificate_domain", config["host"])
- hosts = [host]
- hosts.extend("%s.%s" % (item[0], host) for item in serve.get_subdomains(host).values())
- key_file, certificate = self.ssl_env.host_cert_path(hosts)
+ if "browser_host" in self.options:
+ config.browser_host = self.options["browser_host"]
- config["key_file"] = key_file
- config["certificate"] = certificate
+ if "bind_address" in self.options:
+ config.bind_address = self.options["bind_address"]
- serve.set_computed_defaults(config)
+ config.server_host = self.options.get("server_host", None)
+ config.ssl["encrypt_after_connect"] = self.options.get("encrypt_after_connect", False)
+ config.doc_root = serve_path(self.test_paths)
return config
@@ -200,10 +192,14 @@
for path, format_args, content_type, route in [
("testharness_runner.html", {}, "text/html", "/testharness_runner.html"),
(self.options.get("testharnessreport", "testharnessreport.js"),
- {"output": self.pause_after_test}, "text/javascript",
+ {"output": self.pause_after_test}, "text/javascript;charset=utf8",
"/resources/testharnessreport.js")]:
path = os.path.normpath(os.path.join(here, path))
- route_builder.add_static(path, format_args, content_type, route)
+ # Note that .headers. files don't apply to static routes, so we need to
+ # readd any static headers here.
+ headers = {"Cache-Control": "max-age=3600"}
+ route_builder.add_static(path, format_args, content_type, route,
+ headers=headers)
data = b""
with open(os.path.join(repo_root, "resources", "testdriver.js"), "rb") as fp:
@@ -230,20 +226,23 @@
if not failed:
return
time.sleep(0.5)
- raise EnvironmentError("Servers failed to start (scheme:port): %s" % ("%s:%s" for item in failed))
+ raise EnvironmentError("Servers failed to start: %s" %
+ ", ".join("%s:%s" % item for item in failed))
def test_servers(self):
failed = []
+ host = self.config["server_host"]
for scheme, servers in self.servers.iteritems():
for port, server in servers:
if self.test_server_port:
s = socket.socket()
try:
- s.connect((self.config["host"], port))
+ s.connect((host, port))
except socket.error:
- failed.append((scheme, port))
+ failed.append((host, port))
finally:
s.close()
if not server.is_alive():
failed.append((scheme, port))
+ return failed
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py
index 7178b2e..0942bc6 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py
@@ -8,6 +8,7 @@
from abc import ABCMeta, abstractmethod
from ..testrunner import Stop
+from protocol import Protocol, BaseProtocolPart
here = os.path.split(__file__)[0]
@@ -171,7 +172,7 @@
def server_url(self, protocol):
return "%s://%s:%s" % (protocol,
- self.server_config["host"],
+ self.server_config["browser_host"],
self.server_config["ports"][protocol][0])
def test_url(self, test):
@@ -192,13 +193,16 @@
if hasattr(e, "status") and e.status in test.result_cls.statuses:
status = e.status
else:
- status = "ERROR"
+ status = "INTERNAL-ERROR"
message = unicode(getattr(e, "message", ""))
if message:
message += "\n"
message += traceback.format_exc(e)
return test.result_cls(status, message), []
+ def wait(self):
+ self.protocol.base.wait()
+
class TestharnessExecutor(TestExecutor):
convert_result = testharness_result_converter
@@ -367,25 +371,6 @@
from . import pytestrunner
-class Protocol(object):
- def __init__(self, executor, browser):
- self.executor = executor
- self.browser = browser
-
- @property
- def logger(self):
- return self.executor.logger
-
- def setup(self, runner):
- pass
-
- def teardown(self):
- pass
-
- def wait(self):
- pass
-
-
class WdspecRun(object):
def __init__(self, func, session, path, timeout):
self.func = func
@@ -421,14 +406,40 @@
if message:
message += "\n"
message += traceback.format_exc(e)
- self.result = False, ("ERROR", message)
+ self.result = False, ("INTERNAL-ERROR", message)
finally:
self.result_flag.set()
+class ConnectionlessBaseProtocolPart(BaseProtocolPart):
+ def execute_script(self, script, async=False):
+ pass
+
+ def set_timeout(self, timeout):
+ pass
+
+ def wait(self):
+ pass
+
+ def set_window(self, handle):
+ pass
+
+
+class ConnectionlessProtocol(Protocol):
+ implements = [ConnectionlessBaseProtocolPart]
+
+ def connect(self):
+ pass
+
+ def after_connect(self):
+ pass
+
+
class WebDriverProtocol(Protocol):
server_cls = None
+ implements = [ConnectionlessBaseProtocolPart]
+
def __init__(self, executor, browser):
Protocol.__init__(self, executor, browser)
self.webdriver_binary = executor.webdriver_binary
@@ -437,24 +448,21 @@
self.session_config = None
self.server = None
- def setup(self, runner):
+ def connect(self):
"""Connect to browser via the HTTP server."""
- try:
- self.server = self.server_cls(
- self.logger,
- binary=self.webdriver_binary,
- args=self.webdriver_args)
- self.server.start(block=False)
- self.logger.info(
- "WebDriver HTTP server listening at %s" % self.server.url)
- self.session_config = {"host": self.server.host,
- "port": self.server.port,
- "capabilities": self.capabilities}
- except Exception:
- self.logger.error(traceback.format_exc())
- self.executor.runner.send_message("init_failed")
- else:
- self.executor.runner.send_message("init_succeeded")
+ self.server = self.server_cls(
+ self.logger,
+ binary=self.webdriver_binary,
+ args=self.webdriver_args)
+ self.server.start(block=False)
+ self.logger.info(
+ "WebDriver HTTP server listening at %s" % self.server.url)
+ self.session_config = {"host": self.server.host,
+ "port": self.server.port,
+ "capabilities": self.capabilities}
+
+ def after_connect(self):
+ pass
def teardown(self):
if self.server is not None and self.server.is_alive:
@@ -476,3 +484,96 @@
conn.request("HEAD", self.server.base_path + "invalid")
res = conn.getresponse()
return res.status == 404
+
+
+class CallbackHandler(object):
+ """Handle callbacks from testdriver-using tests.
+
+ The default implementation here makes sense for things that are roughly like
+ WebDriver. Things that are more different to WebDriver may need to create a
+ fully custom implementation."""
+
+ def __init__(self, logger, protocol, test_window):
+ self.protocol = protocol
+ self.test_window = test_window
+ self.logger = logger
+ self.callbacks = {
+ "action": self.process_action,
+ "complete": self.process_complete
+ }
+
+ self.actions = {
+ "click": ClickAction(self.logger, self.protocol),
+ "send_keys": SendKeysAction(self.logger, self.protocol)
+ }
+
+ def __call__(self, result):
+ url, command, payload = result
+ self.logger.debug("Got async callback: %s" % result[1])
+ try:
+ callback = self.callbacks[command]
+ except KeyError:
+ raise ValueError("Unknown callback type %r" % result[1])
+ return callback(url, payload)
+
+ def process_complete(self, url, payload):
+ rv = [url] + payload
+ return True, rv
+
+ def process_action(self, url, payload):
+ parent = self.protocol.base.current_window
+ try:
+ self.protocol.base.set_window(self.test_window)
+ action = payload["action"]
+ self.logger.debug("Got action: %s" % action)
+ try:
+ action_handler = self.actions[action]
+ except KeyError:
+ raise ValueError("Unknown action %s" % action)
+ try:
+ action_handler(payload)
+ except Exception as e:
+ self.logger.warning("Action %s failed" % action)
+ self.logger.warning(traceback.format_exc())
+ self._send_message("complete", "failure")
+ else:
+ self.logger.debug("Action %s completed" % action)
+ self._send_message("complete", "success")
+ finally:
+ self.protocol.base.set_window(parent)
+
+ return False, None
+
+ def _send_message(self, message_type, status, message=None):
+ self.protocol.testdriver.send_message(message_type, status, message=message)
+
+class ClickAction(object):
+ def __init__(self, logger, protocol):
+ self.logger = logger
+ self.protocol = protocol
+
+ def __call__(self, payload):
+ selector = payload["selector"]
+ elements = self.protocol.select.elements_by_selector(selector)
+ if len(elements) == 0:
+ raise ValueError("Selector matches no elements")
+ elif len(elements) > 1:
+ raise ValueError("Selector matches multiple elements")
+ self.logger.debug("Clicking element: %s" % selector)
+ self.protocol.click.element(elements[0])
+
+class SendKeysAction(object):
+ def __init__(self, logger, protocol):
+ self.logger = logger
+ self.protocol = protocol
+
+ def __call__(self, payload):
+ selector = payload["selector"]
+ keys = payload["keys"]
+ elements = self.protocol.select.elements_by_selector(selector)
+ if len(elements) == 0:
+ raise ValueError("Selector matches no elements")
+ elif len(elements) > 1:
+ raise ValueError("Selector matches multiple elements")
+ self.logger.debug("Sending keys to element: %s" % selector)
+ self.protocol.send_keys.send_keys(elements[0], keys)
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py
index faf087b..d06ee3c 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -1,3 +1,4 @@
+import json
import os
import socket
import threading
@@ -11,8 +12,8 @@
here = os.path.join(os.path.split(__file__)[0])
-from .base import (ExecutorException,
- Protocol,
+from .base import (CallbackHandler,
+ ExecutorException,
RefTestExecutor,
RefTestImplementation,
TestExecutor,
@@ -24,12 +25,19 @@
testharness_result_converter,
reftest_result_converter,
strip_server)
-
+from .protocol import (BaseProtocolPart,
+ TestharnessProtocolPart,
+ PrefsProtocolPart,
+ Protocol,
+ StorageProtocolPart,
+ SelectorProtocolPart,
+ ClickProtocolPart,
+ SendKeysProtocolPart,
+ TestDriverProtocolPart)
from ..testrunner import Stop
from ..webdriver_server import GeckoDriverServer
-
def do_delayed_imports():
global errors, marionette
@@ -42,78 +50,17 @@
from marionette_driver import marionette, errors
-class MarionetteProtocol(Protocol):
- def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1):
- do_delayed_imports()
-
- Protocol.__init__(self, executor, browser)
- self.marionette = None
- self.marionette_port = browser.marionette_port
- self.capabilities = capabilities
- self.timeout_multiplier = timeout_multiplier
+class MarionetteBaseProtocolPart(BaseProtocolPart):
+ def __init__(self, parent):
+ super(MarionetteBaseProtocolPart, self).__init__(parent)
self.timeout = None
- self.runner_handle = None
- def setup(self, runner):
- """Connect to browser via Marionette."""
- Protocol.setup(self, runner)
+ def setup(self):
+ self.marionette = self.parent.marionette
- self.logger.debug("Connecting to Marionette on port %i" % self.marionette_port)
- startup_timeout = marionette.Marionette.DEFAULT_STARTUP_TIMEOUT * self.timeout_multiplier
- self.marionette = marionette.Marionette(host='localhost',
- port=self.marionette_port,
- socket_timeout=None,
- startup_timeout=startup_timeout)
- try:
- self.logger.debug("Waiting for Marionette connection")
- while True:
- try:
- self.marionette.raise_for_port()
- break
- except IOError:
- # When running in a debugger wait indefinitely for Firefox to start
- if self.executor.debug_info is None:
- raise
-
- self.logger.debug("Starting Marionette session")
- self.marionette.start_session()
- self.logger.debug("Marionette session started")
-
- except Exception as e:
- self.logger.warning("Failed to start a Marionette session: %s" % e)
- self.executor.runner.send_message("init_failed")
-
- else:
- try:
- self.after_connect()
- except Exception:
- self.logger.warning("Post-connection steps failed")
- self.logger.error(traceback.format_exc())
- self.executor.runner.send_message("init_failed")
- else:
- self.executor.runner.send_message("init_succeeded")
-
- def teardown(self):
- try:
- self.marionette._request_in_app_shutdown()
- self.marionette.delete_session(send_request=False)
- except Exception:
- # This is typically because the session never started
- pass
- if self.marionette is not None:
- del self.marionette
-
- @property
- def is_alive(self):
- """Check if the Marionette connection is still active."""
- try:
- self.marionette.current_window_handle
- except Exception:
- return False
- return True
-
- def after_connect(self):
- self.load_runner(self.executor.last_environment["protocol"])
+ def execute_script(self, script, async=False):
+ method = self.marionette.execute_async_script if async else self.marionette.execute_script
+ return method(script, new_sandbox=False)
def set_timeout(self, timeout):
"""Set the Marionette script timeout.
@@ -121,13 +68,60 @@
:param timeout: Script timeout in seconds
"""
- self.marionette.timeout.script = timeout
- self.timeout = timeout
+ if timeout != self.timeout:
+ self.marionette.timeout.script = timeout
+ self.timeout = timeout
- def load_runner(self, protocol):
+ @property
+ def current_window(self):
+ return self.marionette.current_window_handle
+
+ def set_window(self, handle):
+ self.marionette.switch_to_window(handle)
+
+ def wait(self):
+ try:
+ socket_timeout = self.marionette.client.socket_timeout
+ except AttributeError:
+ # This can happen if there was a crash
+ return
+ if socket_timeout:
+ try:
+ self.marionette.timeout.script = socket_timeout / 2
+ except (socket.error, IOError):
+ self.logger.debug("Socket closed")
+ return
+
+ while True:
+ try:
+ self.marionette.execute_async_script("")
+ except errors.NoSuchWindowException:
+ # The window closed
+ break
+ except errors.ScriptTimeoutException:
+ self.logger.debug("Script timed out")
+ pass
+ except (socket.timeout, IOError):
+ self.logger.debug("Socket closed")
+ break
+ except Exception as e:
+ self.logger.warning(traceback.format_exc(e))
+ break
+
+
+class MarionetteTestharnessProtocolPart(TestharnessProtocolPart):
+ def __init__(self, parent):
+ super(MarionetteTestharnessProtocolPart, self).__init__(parent)
+ self.runner_handle = None
+
+ def setup(self):
+ self.marionette = self.parent.marionette
+
+ def load_runner(self, url_protocol):
# Check if we previously had a test window open, and if we did make sure it's closed
- self.marionette.execute_script("if (window.wrappedJSObject.win) {window.wrappedJSObject.win.close()}")
- url = urlparse.urljoin(self.executor.server_url(protocol), "/testharness_runner.html")
+ self.marionette.execute_script("if (window.win) {window.win.close()}")
+ url = urlparse.urljoin(self.parent.executor.server_url(url_protocol),
+ "/testharness_runner.html")
self.logger.debug("Loading %s" % url)
self.runner_handle = self.marionette.current_window_handle
try:
@@ -142,7 +136,7 @@
self.marionette.execute_script(
"document.title = '%s'" % threading.current_thread().name.replace("'", '"'))
- def close_old_windows(self, protocol):
+ def close_old_windows(self, url_protocol):
handles = self.marionette.window_handles
runner_handle = None
try:
@@ -168,7 +162,8 @@
self.marionette.switch_to_window(runner_handle)
if runner_handle != self.runner_handle:
- self.load_runner(protocol)
+ self.load_runner(url_protocol)
+ return self.runner_handle
def dismiss_alert(self, f):
while True:
@@ -183,50 +178,36 @@
else:
break
- def wait(self):
- try:
- socket_timeout = self.marionette.client.socket_timeout
- except AttributeError:
- # This can happen if there was a crash
- return
- if socket_timeout:
+ def get_test_window(self, window_id, parent):
+ test_window = None
+ if window_id:
try:
- self.marionette.timeout.script = socket_timeout / 2
- except (socket.error, IOError):
- self.logger.debug("Socket closed")
- return
-
- self.marionette.switch_to_window(self.runner_handle)
- while True:
- try:
- self.marionette.execute_async_script("")
- except errors.NoSuchWindowException:
- # The window closed
- break
- except errors.ScriptTimeoutException:
- self.logger.debug("Script timed out")
+ # Try this, it's in Level 1 but nothing supports it yet
+ win_s = self.marionette.execute_script("return window['%s'];" % self.window_id)
+ win_obj = json.loads(win_s)
+ test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
+ except Exception:
pass
- except (socket.timeout, IOError):
- self.logger.debug("Socket closed")
- break
- except Exception as e:
- self.logger.warning(traceback.format_exc(e))
- break
- def on_environment_change(self, old_environment, new_environment):
- #Unset all the old prefs
- for name in old_environment.get("prefs", {}).iterkeys():
- value = self.executor.original_pref_values[name]
- if value is None:
- self.clear_user_pref(name)
+ if test_window is None:
+ after = self.marionette.window_handles
+ if len(after) == 2:
+ test_window = next(iter(set(after) - set([parent])))
+ elif after[0] == parent and len(after) > 2:
+ # Hope the first one here is the test window
+ test_window = after[1]
else:
- self.set_pref(name, value)
+ raise Exception("unable to find test window")
- for name, value in new_environment.get("prefs", {}).iteritems():
- self.executor.original_pref_values[name] = self.get_pref(name)
- self.set_pref(name, value)
+ assert test_window != parent
+ return test_window
- def set_pref(self, name, value):
+
+class MarionettePrefsProtocolPart(PrefsProtocolPart):
+ def setup(self):
+ self.marionette = self.parent.marionette
+
+ def set(self, name, value):
if value.lower() not in ("true", "false"):
try:
int(value)
@@ -258,7 +239,7 @@
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
self.marionette.execute_script(script)
- def clear_user_pref(self, name):
+ def clear(self, name):
self.logger.info("Clearing pref %s" % (name))
script = """
let prefInterface = Components.classes["@mozilla.org/preferences-service;1"]
@@ -269,7 +250,7 @@
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
self.marionette.execute_script(script)
- def get_pref(self, name):
+ def get(self, name):
script = """
let prefInterface = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
@@ -289,6 +270,11 @@
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
self.marionette.execute_script(script)
+
+class MarionetteStorageProtocolPart(StorageProtocolPart):
+ def setup(self):
+ self.marionette = self.parent.marionette
+
def clear_origin(self, url):
self.logger.info("Clearing origin %s" % (url))
script = """
@@ -307,12 +293,125 @@
self.marionette.execute_script(script)
+class MarionetteSelectorProtocolPart(SelectorProtocolPart):
+ def setup(self):
+ self.marionette = self.parent.marionette
+
+ def elements_by_selector(self, selector):
+ return self.marionette.find_elements("css selector", selector)
+
+
+class MarionetteClickProtocolPart(ClickProtocolPart):
+ def setup(self):
+ self.marionette = self.parent.marionette
+
+ def element(self, element):
+ return element.click()
+
+class MarionetteSendKeysProtocolPart(SendKeysProtocolPart):
+ def setup(self):
+ self.marionette = self.parent.marionette
+
+ def send_keys(self, element, keys):
+ return element.send_keys(keys)
+
+class MarionetteTestDriverProtocolPart(TestDriverProtocolPart):
+ def setup(self):
+ self.marionette = self.parent.marionette
+
+ def send_message(self, message_type, status, message=None):
+ obj = {
+ "type": "testdriver-%s" % str(message_type),
+ "status": str(status)
+ }
+ if message:
+ obj["message"] = str(message)
+ self.marionette.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
+
+
+class MarionetteProtocol(Protocol):
+ implements = [MarionetteBaseProtocolPart,
+ MarionetteTestharnessProtocolPart,
+ MarionettePrefsProtocolPart,
+ MarionetteStorageProtocolPart,
+ MarionetteSelectorProtocolPart,
+ MarionetteClickProtocolPart,
+ MarionetteSendKeysProtocolPart,
+ MarionetteTestDriverProtocolPart]
+
+ def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1):
+ do_delayed_imports()
+
+ super(MarionetteProtocol, self).__init__(executor, browser)
+ self.marionette = None
+ self.marionette_port = browser.marionette_port
+ self.capabilities = capabilities
+ self.timeout_multiplier = timeout_multiplier
+ self.runner_handle = None
+
+ def connect(self):
+ self.logger.debug("Connecting to Marionette on port %i" % self.marionette_port)
+ startup_timeout = marionette.Marionette.DEFAULT_STARTUP_TIMEOUT * self.timeout_multiplier
+ self.marionette = marionette.Marionette(host='localhost',
+ port=self.marionette_port,
+ socket_timeout=None,
+ startup_timeout=startup_timeout)
+
+ self.logger.debug("Waiting for Marionette connection")
+ while True:
+ try:
+ self.marionette.raise_for_port()
+ break
+ except IOError:
+ # When running in a debugger wait indefinitely for Firefox to start
+ if self.executor.debug_info is None:
+ raise
+
+ self.logger.debug("Starting Marionette session")
+ self.marionette.start_session()
+ self.logger.debug("Marionette session started")
+
+ def after_connect(self):
+ self.testharness.load_runner(self.executor.last_environment["protocol"])
+
+ def teardown(self):
+ try:
+ self.marionette._request_in_app_shutdown()
+ self.marionette.delete_session(send_request=False)
+ except Exception:
+ # This is typically because the session never started
+ pass
+ if self.marionette is not None:
+ del self.marionette
+ super(MarionetteProtocol, self).teardown()
+
+ @property
+ def is_alive(self):
+ try:
+ self.marionette.current_window_handle
+ except Exception:
+ return False
+ return True
+
+ def on_environment_change(self, old_environment, new_environment):
+ #Unset all the old prefs
+ for name in old_environment.get("prefs", {}).iterkeys():
+ value = self.executor.original_pref_values[name]
+ if value is None:
+ self.prefs.clear(name)
+ else:
+ self.prefs.set(name, value)
+
+ for name, value in new_environment.get("prefs", {}).iteritems():
+ self.executor.original_pref_values[name] = self.prefs.get(name)
+ self.prefs.set(name, value)
+
+
class ExecuteAsyncScriptRun(object):
def __init__(self, logger, func, protocol, url, timeout):
self.logger = logger
self.result = (None, None)
self.protocol = protocol
- self.marionette = protocol.marionette
self.func = func
self.url = url
self.timeout = timeout
@@ -322,19 +421,18 @@
index = self.url.rfind("/storage/")
if index != -1:
# Clear storage
- self.protocol.clear_origin(self.url)
+ self.protocol.storage.clear_origin(self.url)
timeout = self.timeout
try:
if timeout is not None:
- if timeout + extra_timeout != self.protocol.timeout:
- self.protocol.set_timeout(timeout + extra_timeout)
+ self.protocol.base.set_timeout(timeout + extra_timeout)
else:
# We just want it to never time out, really, but marionette doesn't
# make that possible. It also seems to time out immediately if the
# timeout is set too high. This works at least.
- self.protocol.set_timeout(2**28 - 1)
+ self.protocol.base.set_timeout(2**28 - 1)
except IOError:
self.logger.error("Lost marionette connection before starting test")
return Stop
@@ -356,14 +454,14 @@
# We didn't get any data back from the test, so check if the
# browser is still responsive
if self.protocol.is_alive:
- self.result = False, ("ERROR", None)
+ self.result = False, ("INTERNAL-ERROR", None)
else:
self.result = False, ("CRASH", None)
return self.result
def _run(self):
try:
- self.result = True, self.func(self.marionette, self.url, self.timeout)
+ self.result = True, self.func(self.protocol, self.url, self.timeout)
except errors.ScriptTimeoutException:
self.logger.debug("Got a marionette timeout")
self.result = False, ("EXTERNAL-TIMEOUT", None)
@@ -377,13 +475,15 @@
if message:
message += "\n"
message += traceback.format_exc(e)
- self.result = False, ("ERROR", e)
+ self.result = False, ("INTERNAL-ERROR", e)
finally:
self.result_flag.set()
class MarionetteTestharnessExecutor(TestharnessExecutor):
+ supports_testdriver = True
+
def __init__(self, browser, server_config, timeout_multiplier=1,
close_after_done=True, debug_info=None, capabilities=None,
**kwargs):
@@ -394,6 +494,7 @@
self.protocol = MarionetteProtocol(self, browser, capabilities, timeout_multiplier)
self.script = open(os.path.join(here, "testharness_marionette.js")).read()
+ self.script_resume = open(os.path.join(here, "testharness_marionette_resume.js")).read()
self.close_after_done = close_after_done
self.window_id = str(uuid.uuid4())
@@ -409,7 +510,7 @@
self.protocol.on_environment_change(self.last_environment, new_environment)
if new_environment["protocol"] != self.last_environment["protocol"]:
- self.protocol.load_runner(new_environment["protocol"])
+ self.protocol.testharness.load_runner(new_environment["protocol"])
def do_test(self, test):
timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
@@ -425,24 +526,34 @@
return (test.result_cls(*data), [])
- def do_testharness(self, marionette, url, timeout):
- if self.close_after_done:
- marionette.execute_script("if (window.wrappedJSObject.win) {window.wrappedJSObject.win.close()}")
- self.protocol.close_old_windows(self.protocol)
+ def do_testharness(self, protocol, url, timeout):
+ protocol.base.execute_script("if (window.win) {window.win.close()}")
+ parent_window = protocol.testharness.close_old_windows(protocol)
if timeout is not None:
timeout_ms = str(timeout * 1000)
else:
timeout_ms = "null"
- script = self.script % {"abs_url": url,
- "url": strip_server(url),
- "window_id": self.window_id,
- "timeout_multiplier": self.timeout_multiplier,
- "timeout": timeout_ms,
- "explicit_timeout": timeout is None}
+ format_map = {"abs_url": url,
+ "url": strip_server(url),
+ "window_id": self.window_id,
+ "timeout_multiplier": self.timeout_multiplier,
+ "timeout": timeout_ms,
+ "explicit_timeout": timeout is None}
- rv = marionette.execute_async_script(script, new_sandbox=False)
+ script = self.script % format_map
+
+ rv = protocol.base.execute_script(script)
+ test_window = protocol.testharness.get_test_window(self.window_id, parent_window)
+
+ handler = CallbackHandler(self.logger, protocol, test_window)
+ while True:
+ result = protocol.base.execute_script(
+ self.script_resume % format_map, async=True)
+ done, rv = handler(result)
+ if done:
+ break
return rv
@@ -506,8 +617,8 @@
self.has_window = False
if not self.has_window:
- self.protocol.marionette.execute_script(self.script)
- self.protocol.marionette.switch_to_window(self.protocol.marionette.window_handles[-1])
+ self.protocol.base.execute_script(self.script)
+ self.protocol.base.set_window(self.protocol.marionette.window_handles[-1])
self.has_window = True
result = self.implementation.run_test(test)
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorselenium.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorselenium.py
index f905fac..98c49bd 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorselenium.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorselenium.py
@@ -8,12 +8,19 @@
import urlparse
import uuid
-from .base import (Protocol,
+from .base import (CallbackHandler,
RefTestExecutor,
RefTestImplementation,
TestharnessExecutor,
extra_timeout,
strip_server)
+from .protocol import (BaseProtocolPart,
+ TestharnessProtocolPart,
+ Protocol,
+ SelectorProtocolPart,
+ ClickProtocolPart,
+ SendKeysProtocolPart,
+ TestDriverProtocolPart)
from ..testrunner import Stop
here = os.path.join(os.path.split(__file__)[0])
@@ -32,45 +39,150 @@
from selenium.webdriver.remote.remote_connection import RemoteConnection
+class SeleniumBaseProtocolPart(BaseProtocolPart):
+ def setup(self):
+ self.webdriver = self.parent.webdriver
+
+ def execute_script(self, script, async=False):
+ method = self.webdriver.execute_async_script if async else self.webdriver.execute_script
+ return method(script)
+
+ def set_timeout(self, timeout):
+ self.webdriver.set_script_timeout(timeout * 1000)
+
+ @property
+ def current_window(self):
+ return self.webdriver.current_window_handle
+
+ def set_window(self, handle):
+ self.webdriver.switch_to_window(handle)
+
+ def wait(self):
+ while True:
+ try:
+ self.webdriver.execute_async_script("")
+ except exceptions.TimeoutException:
+ pass
+ except (socket.timeout, exceptions.NoSuchWindowException,
+ exceptions.ErrorInResponseException, IOError):
+ break
+ except Exception as e:
+ self.logger.error(traceback.format_exc(e))
+ break
+
+
+class SeleniumTestharnessProtocolPart(TestharnessProtocolPart):
+ def setup(self):
+ self.webdriver = self.parent.webdriver
+
+ def load_runner(self, url_protocol):
+ url = urlparse.urljoin(self.parent.executor.server_url(url_protocol),
+ "/testharness_runner.html")
+ self.logger.debug("Loading %s" % url)
+ self.webdriver.get(url)
+ self.webdriver.execute_script("document.title = '%s'" %
+ threading.current_thread().name.replace("'", '"'))
+
+ def close_old_windows(self):
+ exclude = self.webdriver.current_window_handle
+ handles = [item for item in self.webdriver.window_handles if item != exclude]
+ for handle in handles:
+ try:
+ self.webdriver.switch_to_window(handle)
+ self.webdriver.close()
+ except exceptions.NoSuchWindowException:
+ pass
+ self.webdriver.switch_to_window(exclude)
+ return exclude
+
+ def get_test_window(self, window_id, parent):
+ test_window = None
+ if window_id:
+ try:
+ # Try this, it's in Level 1 but nothing supports it yet
+ win_s = self.webdriver.execute_script("return window['%s'];" % self.window_id)
+ win_obj = json.loads(win_s)
+ test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
+ except Exception:
+ pass
+
+ if test_window is None:
+ after = self.webdriver.window_handles
+ if len(after) == 2:
+ test_window = next(iter(set(after) - set([parent])))
+ elif after[0] == parent and len(after) > 2:
+ # Hope the first one here is the test window
+ test_window = after[1]
+ else:
+ raise Exception("unable to find test window")
+
+ assert test_window != parent
+ return test_window
+
+
+class SeleniumSelectorProtocolPart(SelectorProtocolPart):
+ def setup(self):
+ self.webdriver = self.parent.webdriver
+
+ def elements_by_selector(self, selector):
+ return self.webdriver.find_elements_by_css_selector(selector)
+
+
+class SeleniumClickProtocolPart(ClickProtocolPart):
+ def setup(self):
+ self.webdriver = self.parent.webdriver
+
+ def element(self, element):
+ return element.click()
+
+class SeleniumSendKeysProtocolPart(SendKeysProtocolPart):
+ def setup(self):
+ self.webdriver = self.parent.webdriver
+
+ def send_keys(self, element, keys):
+ return element.send_keys(keys)
+
+
+class SeleniumTestDriverProtocolPart(TestDriverProtocolPart):
+ def setup(self):
+ self.webdriver = self.parent.webdriver
+
+ def send_message(self, message_type, status, message=None):
+ obj = {
+ "type": "testdriver-%s" % str(message_type),
+ "status": str(status)
+ }
+ if message:
+ obj["message"] = str(message)
+ self.webdriver.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
+
+
class SeleniumProtocol(Protocol):
+ implements = [SeleniumBaseProtocolPart,
+ SeleniumTestharnessProtocolPart,
+ SeleniumSelectorProtocolPart,
+ SeleniumClickProtocolPart,
+ SeleniumSendKeysProtocolPart,
+ SeleniumTestDriverProtocolPart]
+
def __init__(self, executor, browser, capabilities, **kwargs):
do_delayed_imports()
- Protocol.__init__(self, executor, browser)
+ super(SeleniumProtocol, self).__init__(executor, browser)
self.capabilities = capabilities
self.url = browser.webdriver_url
self.webdriver = None
- def setup(self, runner):
+ def connect(self):
"""Connect to browser via Selenium's WebDriver implementation."""
- self.runner = runner
self.logger.debug("Connecting to Selenium on URL: %s" % self.url)
- session_started = False
- try:
- self.webdriver = webdriver.Remote(command_executor=RemoteConnection(self.url.strip("/"),
- resolve_ip=False),
- desired_capabilities=self.capabilities)
- except Exception:
- self.logger.warning(
- "Connecting to Selenium failed:\n%s" % traceback.format_exc())
- else:
- self.logger.debug("Selenium session started")
- session_started = True
+ self.webdriver = webdriver.Remote(command_executor=RemoteConnection(self.url.strip("/"),
+ resolve_ip=False),
+ desired_capabilities=self.capabilities)
- if not session_started:
- self.logger.warning("Failed to connect to Selenium")
- self.executor.runner.send_message("init_failed")
- else:
- try:
- self.after_connect()
- except Exception:
- print >> sys.stderr, traceback.format_exc()
- self.logger.warning(
- "Failed to connect to navigate initial page")
- self.executor.runner.send_message("init_failed")
- else:
- self.executor.runner.send_message("init_succeeded")
+ def after_conect(self):
+ pass
def teardown(self):
self.logger.debug("Hanging up on Selenium session")
@@ -90,35 +202,14 @@
return True
def after_connect(self):
- self.load_runner("http")
-
- def load_runner(self, protocol):
- url = urlparse.urljoin(self.executor.server_url(protocol),
- "/testharness_runner.html")
- self.logger.debug("Loading %s" % url)
- self.webdriver.get(url)
- self.webdriver.execute_script("document.title = '%s'" %
- threading.current_thread().name.replace("'", '"'))
-
- def wait(self):
- while True:
- try:
- self.webdriver.execute_async_script("")
- except exceptions.TimeoutException:
- pass
- except (socket.timeout, exceptions.NoSuchWindowException,
- exceptions.ErrorInResponseException, IOError):
- break
- except Exception as e:
- self.logger.error(traceback.format_exc(e))
- break
+ self.testharness.load_runner(self.executor.last_environment["protocol"])
class SeleniumRun(object):
- def __init__(self, func, webdriver, url, timeout):
+ def __init__(self, func, protocol, url, timeout):
self.func = func
self.result = None
- self.webdriver = webdriver
+ self.protocol = protocol
self.url = url
self.timeout = timeout
self.result_flag = threading.Event()
@@ -127,7 +218,7 @@
timeout = self.timeout
try:
- self.webdriver.set_script_timeout((timeout + extra_timeout) * 1000)
+ self.protocol.base.set_timeout((timeout + extra_timeout))
except exceptions.ErrorInResponseException:
self.logger.error("Lost WebDriver connection")
return Stop
@@ -144,7 +235,7 @@
def _run(self):
try:
- self.result = True, self.func(self.webdriver, self.url, self.timeout)
+ self.result = True, self.func(self.protocol, self.url, self.timeout)
except exceptions.TimeoutException:
self.result = False, ("EXTERNAL-TIMEOUT", None)
except (socket.timeout, exceptions.ErrorInResponseException):
@@ -154,7 +245,7 @@
if message:
message += "\n"
message += traceback.format_exc(e)
- self.result = False, ("ERROR", e)
+ self.result = False, ("INTERNAL-ERROR", e)
finally:
self.result_flag.set()
@@ -182,13 +273,13 @@
def on_environment_change(self, new_environment):
if new_environment["protocol"] != self.last_environment["protocol"]:
- self.protocol.load_runner(new_environment["protocol"])
+ self.protocol.testharness.load_runner(new_environment["protocol"])
def do_test(self, test):
url = self.test_url(test)
success, data = SeleniumRun(self.do_testharness,
- self.protocol.webdriver,
+ self.protocol,
url,
test.timeout * self.timeout_multiplier).run()
@@ -197,111 +288,28 @@
return (test.result_cls(*data), [])
- def do_testharness(self, webdriver, url, timeout):
+ def do_testharness(self, protocol, url, timeout):
format_map = {"abs_url": url,
"url": strip_server(url),
"window_id": self.window_id,
"timeout_multiplier": self.timeout_multiplier,
"timeout": timeout * 1000}
- parent = webdriver.current_window_handle
- handles = [item for item in webdriver.window_handles if item != parent]
- for handle in handles:
- try:
- webdriver.switch_to_window(handle)
- webdriver.close()
- except exceptions.NoSuchWindowException:
- pass
- webdriver.switch_to_window(parent)
+ parent_window = protocol.testharness.close_old_windows()
+ # Now start the test harness
+ protocol.base.execute_script(self.script % format_map)
+ test_window = protocol.testharness.get_test_window(webdriver, parent_window)
- webdriver.execute_script(self.script % format_map)
- try:
- # Try this, it's in Level 1 but nothing supports it yet
- win_s = webdriver.execute_script("return window['%s'];" % self.window_id)
- win_obj = json.loads(win_s)
- test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
- except Exception:
- after = webdriver.window_handles
- if len(after) == 2:
- test_window = next(iter(set(after) - set([parent])))
- elif after[0] == parent and len(after) > 2:
- # Hope the first one here is the test window
- test_window = after[1]
- else:
- raise Exception("unable to find test window")
- assert test_window != parent
-
- handler = CallbackHandler(webdriver, test_window, self.logger)
+ handler = CallbackHandler(self.logger, protocol, test_window)
while True:
- result = webdriver.execute_async_script(
- self.script_resume % format_map)
+ result = protocol.base.execute_script(
+ self.script_resume % format_map, async=True)
done, rv = handler(result)
if done:
break
return rv
-class CallbackHandler(object):
- def __init__(self, webdriver, test_window, logger):
- self.webdriver = webdriver
- self.test_window = test_window
- self.logger = logger
-
- def __call__(self, result):
- self.logger.debug("Got async callback: %s" % result[1])
- try:
- attr = getattr(self, "process_%s" % result[1])
- except AttributeError:
- raise ValueError("Unknown callback type %r" % result[1])
- else:
- return attr(result)
-
- def process_complete(self, result):
- rv = [result[0]] + result[2]
- return True, rv
-
- def process_action(self, result):
- parent = self.webdriver.current_window_handle
- try:
- self.webdriver.switch_to.window(self.test_window)
- action = result[2]["action"]
- self.logger.debug("Got action: %s" % action)
- if action == "click":
- selector = result[2]["selector"]
- elements = self.webdriver.find_elements_by_css_selector(selector)
- if len(elements) == 0:
- raise ValueError("Selector matches no elements")
- elif len(elements) > 1:
- raise ValueError("Selector matches multiple elements")
- self.logger.debug("Clicking element: %s" % selector)
- try:
- elements[0].click()
- except (exceptions.ElementNotInteractableException,
- exceptions.ElementNotVisibleException) as e:
- self._send_message("complete",
- "failure",
- e)
- self.logger.debug("Clicking element failed: %s" % str(e))
- else:
- self._send_message("complete",
- "success")
- self.logger.debug("Clicking element succeeded")
- finally:
- self.webdriver.switch_to.window(parent)
-
- return False, None
-
- def _send_message(self, message_type, status, message=None):
- obj = {
- "type": "testdriver-%s" % str(message_type),
- "status": str(status)
- }
- if message:
- obj["message"] = str(message)
- self.webdriver.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
-
-
-
class SeleniumRefTestExecutor(RefTestExecutor):
def __init__(self, browser, server_config, timeout_multiplier=1,
screenshot_cache=None, close_after_done=True,
@@ -342,11 +350,12 @@
assert dpi is None
return SeleniumRun(self._screenshot,
- self.protocol.webdriver,
+ self.protocol,
self.test_url(test),
test.timeout).run()
- def _screenshot(self, webdriver, url, timeout):
+ def _screenshot(self, protocol, url, timeout):
+ webdriver = protocol.webdriver
webdriver.get(url)
webdriver.execute_async_script(self.wait_script)
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py
index edacddd..fb79cf2 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py
@@ -13,14 +13,15 @@
from mozprocess import ProcessHandler
-from tools.serve.serve import make_hosts_file
+from serve.serve import make_hosts_file
from .base import (ExecutorException,
- Protocol,
+ ConnectionlessProtocol,
RefTestImplementation,
testharness_result_converter,
reftest_result_converter,
- WdspecExecutor, WebDriverProtocol)
+ WdspecExecutor,
+ WebDriverProtocol)
from .process import ProcessTestExecutor
from ..browsers.base import browser_command
from ..wpttest import WdspecResult, WdspecSubtestResult
@@ -50,7 +51,7 @@
self.pause_after_test = pause_after_test
self.result_data = None
self.result_flag = None
- self.protocol = Protocol(self, browser)
+ self.protocol = ConnectionlessProtocol(self, browser)
self.hosts_path = write_hosts_file(server_config)
def teardown(self):
@@ -181,7 +182,7 @@
timeout_multiplier=timeout_multiplier,
debug_info=debug_info)
- self.protocol = Protocol(self, browser)
+ self.protocol = ConnectionlessProtocol(self, browser)
self.screenshot_cache = screenshot_cache
self.implementation = RefTestImplementation(self)
self.tempdir = tempfile.mkdtemp()
@@ -284,5 +285,6 @@
class ServoDriverProtocol(WebDriverProtocol):
server_cls = ServoDriverServer
+
class ServoWdspecExecutor(WdspecExecutor):
protocol_cls = ServoDriverProtocol
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservodriver.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservodriver.py
index ed7afaf..626c987 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservodriver.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservodriver.py
@@ -33,28 +33,15 @@
self.port = browser.webdriver_port
self.session = None
- def setup(self, runner):
+ def connect(self):
"""Connect to browser via WebDriver."""
- self.runner = runner
-
url = "http://%s:%d" % (self.host, self.port)
- session_started = False
- try:
- self.session = webdriver.Session(self.host, self.port,
- extension=webdriver.servo.ServoCommandExtensions)
- self.session.start()
- except Exception:
- self.logger.warning(
- "Connecting with WebDriver failed:\n%s" % traceback.format_exc())
- else:
- self.logger.debug("session started")
- session_started = True
+ self.session = webdriver.Session(self.host, self.port,
+ extension=webdriver.servo.ServoCommandExtensions)
+ self.session.start()
- if not session_started:
- self.logger.warning("Failed to connect via WebDriver")
- self.executor.runner.send_message("init_failed")
- else:
- self.executor.runner.send_message("init_succeeded")
+ def after_connect(self):
+ pass
def teardown(self):
self.logger.debug("Hanging up on WebDriver session")
@@ -72,9 +59,6 @@
return False
return True
- def after_connect(self):
- pass
-
def wait(self):
while True:
try:
@@ -125,7 +109,7 @@
if message:
message += "\n"
message += traceback.format_exc(e)
- self.result = False, ("ERROR", e)
+ self.result = False, ("INTERNAL-ERROR", e)
finally:
self.result_flag.set()
@@ -230,7 +214,7 @@
if message:
message += "\n"
message += traceback.format_exc(e)
- return test.result_cls("ERROR", message), []
+ return test.result_cls("INTERNAL-ERROR", message), []
def screenshot(self, test, viewport_size, dpi):
# https://github.com/w3c/wptrunner/issues/166
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorwebkit.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorwebkit.py
new file mode 100644
index 0000000..c728ae1
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorwebkit.py
@@ -0,0 +1,10 @@
+from ..webdriver_server import WebKitDriverServer
+from .base import WdspecExecutor, WebDriverProtocol
+
+
+class WebKitDriverProtocol(WebDriverProtocol):
+ server_cls = WebKitDriverServer
+
+
+class WebKitDriverWdspecExecutor(WdspecExecutor):
+ protocol_cls = WebKitDriverProtocol
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/protocol.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/protocol.py
new file mode 100644
index 0000000..3c938f0
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/protocol.py
@@ -0,0 +1,292 @@
+import traceback
+from abc import ABCMeta, abstractmethod
+
+
+class Protocol(object):
+ """Backend for a specific browser-control protocol.
+
+ Each Protocol is composed of a set of ProtocolParts that implement
+ the APIs required for specific interactions. This reflects the fact
+ that not all implementaions will support exactly the same feature set.
+ Each ProtocolPart is exposed directly on the protocol through an accessor
+ attribute with a name given by its `name` property.
+
+ :param Executor executor: The Executor instance that's using this Protocol
+ :param Browser browser: The Browser using this protocol"""
+ __metaclass__ = ABCMeta
+
+ implements = []
+
+ def __init__(self, executor, browser):
+ self.executor = executor
+ self.browser = browser
+
+ for cls in self.implements:
+ name = cls.name
+ assert not hasattr(self, name)
+ setattr(self, name, cls(self))
+
+ @property
+ def logger(self):
+ """:returns: Current logger"""
+ return self.executor.logger
+
+ @property
+ def is_alive(self):
+ """Is the browser connection still active
+
+ :returns: A boolean indicating whether the connection is still active."""
+ return True
+
+ def setup(self, runner):
+ """Handle protocol setup, and send a message to the runner to indicate
+ success or failure."""
+ msg = None
+ try:
+ msg = "Failed to start protocol connection"
+ self.connect()
+
+ msg = None
+
+ for cls in self.implements:
+ getattr(self, cls.name).setup()
+
+ msg = "Post-connection steps failed"
+ self.after_connect()
+ except Exception:
+ if msg is not None:
+ self.logger.warning(msg)
+ self.logger.error(traceback.format_exc())
+ self.executor.runner.send_message("init_failed")
+ return
+ else:
+ self.executor.runner.send_message("init_succeeded")
+
+ @abstractmethod
+ def connect(self):
+ """Make a connection to the remote browser"""
+ pass
+
+ @abstractmethod
+ def after_connect(self):
+ """Run any post-connection steps. This happens after the ProtocolParts are
+ initalized so can depend on a fully-populated object."""
+ pass
+
+ def teardown(self):
+ """Run cleanup steps after the tests are finished."""
+ for cls in self.implements:
+ getattr(self, cls.name).teardown()
+
+
+class ProtocolPart(object):
+ """Base class for all ProtocolParts.
+
+ :param Protocol parent: The parent protocol"""
+ __metaclass__ = ABCMeta
+
+ name = None
+
+ def __init__(self, parent):
+ self.parent = parent
+
+ @property
+ def logger(self):
+ """:returns: Current logger"""
+ return self.parent.logger
+
+ def setup(self):
+ """Run any setup steps required for the ProtocolPart."""
+ pass
+
+ def teardown(self):
+ """Run any teardown steps required for the ProtocolPart."""
+ pass
+
+
+class BaseProtocolPart(ProtocolPart):
+ """Generic bits of protocol that are required for multiple test types"""
+ __metaclass__ = ABCMeta
+
+ name = "base"
+
+ @abstractmethod
+ def execute_script(self, script, async=False):
+ """Execute javascript in the current Window.
+
+ :param str script: The js source to execute. This is implicitly wrapped in a function.
+ :param bool async: Whether the script is asynchronous in the webdriver
+ sense i.e. whether the return value is the result of
+ the initial function call or if it waits for some callback.
+ :returns: The result of the script execution.
+ """
+ pass
+
+ @abstractmethod
+ def set_timeout(self, timeout):
+ """Set the timeout for script execution.
+
+ :param timeout: Script timeout in seconds"""
+ pass
+
+ @abstractmethod
+ def wait(self):
+ """Wait indefinitely for the browser to close"""
+ pass
+
+ @property
+ def current_window(self):
+ """Return a handle identifying the current top level browsing context
+
+ :returns: A protocol-specific handle"""
+ pass
+
+ @abstractmethod
+ def set_window(self, handle):
+ """Set the top level browsing context to one specified by a given handle.
+
+ :param handle: A protocol-specific handle identifying a top level browsing
+ context."""
+ pass
+
+
+class TestharnessProtocolPart(ProtocolPart):
+ """Protocol part required to run testharness tests."""
+ __metaclass__ = ABCMeta
+
+ name = "testharness"
+
+ @abstractmethod
+ def load_runner(self, url_protocol):
+ """Load the initial page used to control the tests.
+
+ :param str url_protocol: "https" or "http" depending on the test metadata.
+ """
+ pass
+
+ @abstractmethod
+ def close_old_windows(self, url_protocol):
+ """Close existing windows except for the initial runner window.
+ After calling this method there must be exactly one open window that
+ contains the initial runner page.
+
+ :param str url_protocol: "https" or "http" depending on the test metadata.
+ """
+ pass
+
+ @abstractmethod
+ def get_test_window(self, window_id, parent):
+ """Get the window handle dorresponding to the window containing the
+ currently active test.
+
+ :param window_id: A string containing the DOM name of the Window that
+ contains the test, or None.
+ :param parent: The handle of the runner window.
+ :returns: A protocol-specific window handle.
+ """
+ pass
+
+
+class PrefsProtocolPart(ProtocolPart):
+ """Protocol part that allows getting and setting browser prefs."""
+ __metaclass__ = ABCMeta
+
+ name = "prefs"
+
+ @abstractmethod
+ def set(self, name, value):
+ """Set the named pref to value.
+
+ :param name: A pref name of browser-specific type
+ :param value: A pref value of browser-specific type"""
+ pass
+
+ @abstractmethod
+ def get(self, name):
+ """Get the current value of a named pref
+
+ :param name: A pref name of browser-specific type
+ :returns: A pref value of browser-specific type"""
+ pass
+
+ @abstractmethod
+ def clear(self, name):
+ """Reset the value of a named pref back to the default.
+
+ :param name: A pref name of browser-specific type"""
+ pass
+
+
+class StorageProtocolPart(ProtocolPart):
+ """Protocol part for manipulating browser storage."""
+ __metaclass__ = ABCMeta
+
+ name = "storage"
+
+ @abstractmethod
+ def clear_origin(self, url):
+ """Clear all the storage for a specified origin.
+
+ :param url: A url belonging to the origin"""
+ pass
+
+
+class SelectorProtocolPart(ProtocolPart):
+ """Protocol part for selecting elements on the page."""
+ __metaclass__ = ABCMeta
+
+ name = "select"
+
+ @abstractmethod
+ def elements_by_selector(self, selector):
+ """Select elements matching a CSS selector
+
+ :param str selector: The CSS selector
+ :returns: A list of protocol-specific handles to elements"""
+ pass
+
+
+class ClickProtocolPart(ProtocolPart):
+ """Protocol part for performing trusted clicks"""
+ __metaclass__ = ABCMeta
+
+ name = "click"
+
+ @abstractmethod
+ def element(self, element):
+ """Perform a trusted click somewhere on a specific element.
+
+ :param element: A protocol-specific handle to an element."""
+ pass
+
+class SendKeysProtocolPart(ProtocolPart):
+ """Protocol part for performing trusted clicks"""
+ __metaclass__ = ABCMeta
+
+ name = "send_keys"
+
+ @abstractmethod
+ def send_keys(self, element, keys):
+ """Send keys to a specific element.
+
+ :param element: A protocol-specific handle to an element.
+ :param keys: A protocol-specific handle to a string of input keys."""
+ pass
+
+
+class TestDriverProtocolPart(ProtocolPart):
+ """Protocol part that implements the basic functionality required for
+ all testdriver-based tests."""
+ __metaclass__ = ABCMeta
+
+ name = "testdriver"
+
+ @abstractmethod
+ def send_message(self, message_type, status, message=None):
+ """Send a testdriver message to the browser.
+
+ :param str message_type: The kind of the message.
+ :param str status: Either "failure" or "success" depending on whether the
+ previous command succeeded.
+ :param str message: Additional data to add to the message."""
+ pass
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
index 8eabf27..c1936eb 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
@@ -44,7 +44,7 @@
os.environ["WD_HOST"] = session_config["host"]
os.environ["WD_PORT"] = str(session_config["port"])
os.environ["WD_CAPABILITIES"] = json.dumps(session_config["capabilities"])
- os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config)
+ os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config.as_dict())
harness = HarnessResultRecorder()
subtests = SubtestResultRecorder()
@@ -62,7 +62,7 @@
path],
plugins=[harness, subtests])
except Exception as e:
- harness.outcome = ("ERROR", str(e))
+ harness.outcome = ("INTERNAL-ERROR", str(e))
return (harness.outcome, subtests.results)
@@ -102,7 +102,19 @@
self.record(report.nodeid, "PASS")
def record_fail(self, report):
- self.record(report.nodeid, "FAIL", stack=report.longrepr)
+ # pytest outputs the stacktrace followed by an error message prefixed
+ # with "E ", e.g.
+ #
+ # def test_example():
+ # > assert "fuu" in "foobar"
+ # > E AssertionError: assert 'fuu' in 'foobar'
+ message = ""
+ for line in report.longreprtext.splitlines():
+ if line.startswith("E "):
+ message = line[1:].strip()
+ break
+
+ self.record(report.nodeid, "FAIL", message=message, stack=report.longrepr)
def record_error(self, report):
# error in setup/teardown
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette.js b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette.js
index e2b70a0..049caa4 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette.js
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette.js
@@ -1,31 +1,24 @@
-window.wrappedJSObject.timeout_multiplier = %(timeout_multiplier)d;
-window.wrappedJSObject.explicit_timeout = %(explicit_timeout)d;
+window.timeout_multiplier = %(timeout_multiplier)d;
+window.explicit_timeout = %(explicit_timeout)d;
-window.wrappedJSObject.addEventListener("message", function listener(event) {
- if (event.data.type != "complete") {
- return;
- }
- window.wrappedJSObject.removeEventListener("message", listener);
- clearTimeout(timer);
- var tests = event.data.tests;
- var status = event.data.status;
+window.message_queue = [];
- var subtest_results = tests.map(function (x) {
- return [x.name, x.status, x.message, x.stack]
- });
+window.setMessageListener = function(func) {
+ window.current_listener = func;
+ window.addEventListener(
+ "message",
+ func,
+ false
+ );
+};
- marionetteScriptFinished(["%(url)s",
- status.status,
- status.message,
- status.stack,
- subtest_results]);
-}, false);
+window.setMessageListener(function(event) {
+ window.message_queue.push(event);
+});
-window.wrappedJSObject.win = window.open("%(abs_url)s", "%(window_id)s");
+window.win = window.open("%(abs_url)s", "%(window_id)s");
-var timer = null;
-if (%(timeout)s) {
- timer = setTimeout(function() {
- window.wrappedJSObject.win.timeout();
- }, %(timeout)s);
-}
+window.timer = setTimeout(function() {
+ window.win.timeout();
+ window.win.close();
+}, %(timeout)s);
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette_resume.js b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette_resume.js
new file mode 100644
index 0000000..7a2df98
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_marionette_resume.js
@@ -0,0 +1,46 @@
+var callback = arguments[arguments.length - 1];
+
+function process_event(event) {
+ var data = event.data;
+
+ var payload = undefined;
+
+ switch(data.type) {
+ case "complete":
+ var tests = event.data.tests;
+ var status = event.data.status;
+
+ var subtest_results = tests.map(function(x) {
+ return [x.name, x.status, x.message, x.stack];
+ });
+ payload = [status.status,
+ status.message,
+ status.stack,
+ subtest_results];
+ clearTimeout(window.timer);
+ break;
+
+ case "action":
+ window.setMessageListener(function(event) {
+ window.message_queue.push(event);
+ });
+ payload = data;
+ break;
+ default:
+ return;
+ }
+
+ callback(["%(url)s", data.type, payload]);
+}
+
+window.removeEventListener("message", window.current_listener);
+if (window.message_queue.length) {
+ var next = window.message_queue.shift();
+ process_event(next);
+} else {
+ window.addEventListener(
+ "message", function f(event) {
+ window.removeEventListener("message", f);
+ process_event(event);
+ }, false);
+}
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js
index 7229777..7a2df98 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js
@@ -26,6 +26,8 @@
});
payload = data;
break;
+ default:
+ return;
}
callback(["%(url)s", data.type, payload]);
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testdriver-extra.js b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testdriver-extra.js
index 856a33e..ef962d3 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testdriver-extra.js
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testdriver-extra.js
@@ -60,4 +60,14 @@
window.opener.postMessage({"type": "action", "action": "click", "selector": selector}, "*");
return pending_promise;
};
+
+ window.test_driver_internal.send_keys = function(element, keys) {
+ const selector = get_selector(element);
+ const pending_promise = new Promise(function(resolve, reject) {
+ pending_resolve = resolve;
+ pending_reject = reject;
+ });
+ window.opener.postMessage({"type": "action", "action": "send_keys", "selector": selector, "keys": keys}, "*");
+ return pending_promise;
+ };
})();
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testloader.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testloader.py
index 199ed6c..9ac2e94 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testloader.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testloader.py
@@ -376,6 +376,7 @@
if test.tags & self.tags:
yield test
+
class ManifestLoader(object):
def __init__(self, test_paths, force_manifest_update=False, manifest_download=False):
do_delayed_imports()
@@ -430,8 +431,7 @@
manifest.write(manifest_file, manifest_path)
- def load_manifest(self, tests_path, metadata_path, url_base="/"):
- manifest_path = os.path.join(metadata_path, "MANIFEST.json")
+ def load_manifest(self, tests_path, manifest_path, url_base="/", **kwargs):
if (not os.path.exists(manifest_path) or
self.force_manifest_update):
self.update_manifest(manifest_path, tests_path, url_base, download=self.manifest_download)
@@ -444,6 +444,7 @@
return manifest_file
+
def iterfilter(filters, iter):
for f in filters:
iter = f(iter)
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py
index 16623f7..e83bff8 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py
@@ -108,7 +108,7 @@
raise
def wait(self):
- self.executor.protocol.wait()
+ self.executor.wait()
self.send_message("wait_finished")
def send_message(self, command, *args):
@@ -304,6 +304,7 @@
# This is started in the actual new thread
self.logger = None
+ self.test_count = 0
self.unexpected_count = 0
# This may not really be what we want
@@ -559,16 +560,22 @@
expected=expected,
stack=result.stack)
- # TODO: consider changing result if there is a crash dump file
-
- # Write the result of the test harness
+ # We have a couple of status codes that are used internally, but not exposed to the
+ # user. These are used to indicate that some possibly-broken state was reached
+ # and we should restart the runner before the next test.
+ # INTERNAL-ERROR indicates a Python exception was caught in the harness
+ # EXTERNAL-TIMEOUT indicates we had to forcibly kill the browser from the harness
+ # because the test didn't return a result after reaching the test-internal timeout
+ status_subns = {"INTERNAL-ERROR": "ERROR",
+ "EXTERNAL-TIMEOUT": "TIMEOUT"}
expected = test.expected()
- status = file_result.status if file_result.status != "EXTERNAL-TIMEOUT" else "TIMEOUT"
+ status = status_subns.get(file_result.status, file_result.status)
- if file_result.status in ("TIMEOUT", "EXTERNAL-TIMEOUT"):
+ if file_result.status in ("TIMEOUT", "EXTERNAL-TIMEOUT", "INTERNAL-ERROR"):
if self.browser.check_for_crashes():
status = "CRASH"
+ self.test_count += 1
is_unexpected = expected != status
if is_unexpected:
self.unexpected_count += 1
@@ -583,7 +590,7 @@
extra=file_result.extra)
restart_before_next = (test.restart_after or
- file_result.status in ("CRASH", "EXTERNAL-TIMEOUT") or
+ file_result.status in ("CRASH", "EXTERNAL-TIMEOUT", "INTERNAL-ERROR") or
((subtest_unexpected or is_unexpected) and
self.restart_on_unexpected))
@@ -789,5 +796,8 @@
self.stop_flag.set()
self.logger.debug("Stop flag set in ManagerGroup")
+ def test_count(self):
+ return sum(item.test_count for item in self.pool)
+
def unexpected_count(self):
return sum(item.unexpected_count for item in self.pool)
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/tests/base.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/tests/base.py
new file mode 100644
index 0000000..b5173f3
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/tests/base.py
@@ -0,0 +1,60 @@
+import os
+import sys
+
+from os.path import dirname, join
+
+import pytest
+
+sys.path.insert(0, join(dirname(__file__), "..", ".."))
+
+from wptrunner import browsers
+
+
+_products = browsers.product_list
+_active_products = set()
+
+if "CURRENT_TOX_ENV" in os.environ:
+ current_tox_env_split = os.environ["CURRENT_TOX_ENV"].split("-")
+
+ tox_env_extra_browsers = {
+ "chrome": {"chrome_android"},
+ "servo": {"servodriver"},
+ }
+
+ _active_products = set(_products) & set(current_tox_env_split)
+ for product in frozenset(_active_products):
+ _active_products |= tox_env_extra_browsers.get(product, set())
+else:
+ _active_products = set(_products)
+
+
+class all_products(object):
+ def __init__(self, arg, marks={}):
+ self.arg = arg
+ self.marks = marks
+
+ def __call__(self, f):
+ params = []
+ for product in _products:
+ if product in self.marks:
+ params.append(pytest.param(product, marks=self.marks[product]))
+ else:
+ params.append(product)
+ return pytest.mark.parametrize(self.arg, params)(f)
+
+
+class active_products(object):
+ def __init__(self, arg, marks={}):
+ self.arg = arg
+ self.marks = marks
+
+ def __call__(self, f):
+ params = []
+ for product in _products:
+ if product not in _active_products:
+ params.append(pytest.param(product, marks=pytest.mark.skip(reason="wrong toxenv")))
+ elif product in self.marks:
+ params.append(pytest.param(product, marks=self.marks[product]))
+ else:
+ params.append(product)
+ return pytest.mark.parametrize(self.arg, params)(f)
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/tests/test_products.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/tests/test_products.py
new file mode 100644
index 0000000..c7109c5
--- /dev/null
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/tests/test_products.py
@@ -0,0 +1,65 @@
+import os
+import sys
+
+from os.path import join, dirname
+
+import mock
+import pytest
+
+from .base import all_products, active_products
+
+sys.path.insert(0, join(dirname(__file__), "..", "..", "..", "..")) # repo root
+
+from tools import localpaths
+
+import sslutils
+
+from wptrunner import environment
+from wptrunner import products
+
+test_paths = {"/": {"tests_path": join(dirname(__file__), "..", "..", "..", "..")}} # repo root
+environment.do_delayed_imports(None, test_paths)
+
+
+@active_products("product")
+def test_load_active_product(product):
+ """test we can successfully load the product of the current testenv"""
+ products.load_product({}, product)
+ # test passes if it doesn't throw
+
+
+@all_products("product")
+def test_load_all_products(product):
+ """test every product either loads or throws ImportError"""
+ try:
+ products.load_product({}, product)
+ except ImportError:
+ pass
+
+
+@active_products("product", marks={
+ "sauce": pytest.mark.skip("needs env extras kwargs"),
+})
+def test_server_start_config(product):
+ (check_args,
+ target_browser_cls, get_browser_kwargs,
+ executor_classes, get_executor_kwargs,
+ env_options, get_env_extras, run_info_extras) = products.load_product({}, product)
+
+ env_extras = get_env_extras()
+
+ with mock.patch.object(environment.serve, "start") as start:
+ with environment.TestEnvironment(test_paths,
+ sslutils.environments["none"](None),
+ False,
+ None,
+ env_options,
+ env_extras) as test_environment:
+ start.assert_called_once()
+ args = start.call_args
+ config = args[0][0]
+ if "server_host" in env_options:
+ assert config["server_host"] == env_options["server_host"]
+ else:
+ assert config["server_host"] == config["browser_host"]
+ assert isinstance(config["bind_address"], bool)
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/metadata.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/metadata.py
index 67f46de..c70ec61 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/metadata.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/metadata.py
@@ -4,14 +4,14 @@
from base import Step, StepRunner
+
class GetUpdatePropertyList(Step):
provides = ["property_order", "boolean_properties"]
-
def create(self, state):
property_order, boolean_properties = products.load_product_update(
state.config, state.product)
- state.property_order = property_order
+ state.property_order = property_order + state.extra_properties
state.boolean_properties = boolean_properties
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py
index c985d35..91029c5 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py
@@ -92,6 +92,7 @@
state.suite_name = kwargs["suite_name"]
state.product = kwargs["product"]
state.config = kwargs["config"]
+ state.extra_properties = kwargs["extra_property"]
runner = MetadataUpdateRunner(self.logger, state)
runner.run()
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py
index 8a3f9c9..5822b36 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py
@@ -13,7 +13,7 @@
__all__ = ["SeleniumServer", "ChromeDriverServer", "OperaDriverServer",
"GeckoDriverServer", "InternetExplorerDriverServer", "EdgeDriverServer",
- "ServoDriverServer", "WebDriverServer"]
+ "ServoDriverServer", "WebKitDriverServer", "WebDriverServer"]
class WebDriverServer(object):
@@ -60,21 +60,22 @@
env=self.env,
storeOutput=False)
+ self.logger.debug("Starting WebDriver: %s" % ' '.join(self._cmd))
try:
self._proc.run()
except OSError as e:
if e.errno == errno.ENOENT:
raise IOError(
- "WebDriver HTTP server executable not found: %s" % self.binary)
+ "WebDriver executable not found: %s" % self.binary)
raise
self.logger.debug(
- "Waiting for server to become accessible: %s" % self.url)
+ "Waiting for WebDriver to become accessible: %s" % self.url)
try:
wait_for_service((self.host, self.port))
except Exception:
self.logger.error(
- "WebDriver HTTP server was not accessible "
+ "WebDriver was not accessible "
"within the timeout:\n%s" % traceback.format_exc())
raise
@@ -178,6 +179,16 @@
"--port", str(self.port)] + self._args
+class SafariDriverServer(WebDriverServer):
+ def __init__(self, logger, binary="safaridriver", port=None, args=None):
+ WebDriverServer.__init__(
+ self, logger, binary, port=port, args=args)
+
+ def make_command(self):
+ return [self.binary,
+ "--port=%s" % str(self.port)] + self._args
+
+
class ServoDriverServer(WebDriverServer):
def __init__(self, logger, binary="servo", binary_args=None, host="127.0.0.1",
port=None, args=None):
@@ -196,6 +207,14 @@
return command
+class WebKitDriverServer(WebDriverServer):
+ def __init__(self, logger, binary=None, port=None, args=None):
+ WebDriverServer.__init__(self, logger, binary, port=port, args=args)
+
+ def make_command(self):
+ return [self.binary, "--port=%s" % str(self.port)] + self._args
+
+
def cmd_arg(name, value=None):
prefix = "-" if platform.system() == "Windows" else "--"
rv = prefix + name
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptcommandline.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptcommandline.py
index ad18e42..8361ca1 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptcommandline.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptcommandline.py
@@ -4,6 +4,7 @@
import sys
from collections import OrderedDict
from distutils.spawn import find_executable
+from datetime import datetime, timedelta
import config
import wpttest
@@ -82,6 +83,36 @@
mode_group.add_argument("--verify-log-full", action="store_true",
default=False,
help="Output per-iteration test results when running verify")
+ mode_group.add_argument("--verify-repeat-loop", action="store",
+ default=10,
+ help="Number of iterations for a run that reloads each test without restart.",
+ type=int)
+ mode_group.add_argument("--verify-repeat-restart", action="store",
+ default=5,
+ help="Number of iterations, for a run that restarts the runner between each iteration",
+ type=int)
+ chaos_mode_group = mode_group.add_mutually_exclusive_group()
+ chaos_mode_group.add_argument("--verify-no-chaos-mode", action="store_false",
+ default=True,
+ dest="verify_chaos_mode",
+ help="Disable chaos mode when running on Firefox")
+ chaos_mode_group.add_argument("--verify-chaos-mode", action="store_true",
+ default=True,
+ dest="verify_chaos_mode",
+ help="Enable chaos mode when running on Firefox")
+ mode_group.add_argument("--verify-max-time", action="store",
+ default=None,
+ help="The maximum number of minutes for the job to run",
+ type=lambda x: timedelta(minutes=float(x)))
+ output_results_group = mode_group.add_mutually_exclusive_group()
+ output_results_group.add_argument("--verify-no-output-results", action="store_false",
+ dest="verify_output_results",
+ default=True,
+ help="Prints individuals test results and messages")
+ output_results_group.add_argument("--verify-output-results", action="store_true",
+ dest="verify_output_results",
+ default=True,
+ help="Disable printing individuals test results and messages")
test_selection_group = parser.add_argument_group("Test Selection")
test_selection_group.add_argument("--test-types", action="store",
@@ -145,6 +176,8 @@
help="Path to root directory containing test metadata"),
config_group.add_argument("--tests", action="store", type=abs_path, dest="tests_root",
help="Path to root directory containing test files"),
+ config_group.add_argument("--manifest", action="store", type=abs_path, dest="manifest_path",
+ help="Path to test manifest (default is ${metadata_root}/MANIFEST.json)")
config_group.add_argument("--run-info", action="store", type=abs_path,
help="Path to directory containing extra json files to add to run info")
config_group.add_argument("--product", action="store", choices=product_choices,
@@ -245,6 +278,10 @@
dest="sauce_connect_binary",
help="Path to Sauce Connect binary")
+ webkit_group = parser.add_argument_group("WebKit-specific")
+ webkit_group.add_argument("--webkit-port", dest="webkit_port",
+ help="WebKit port")
+
parser.add_argument("test_list", nargs="*",
help="List of URLs for tests to run, or paths including tests to run. "
"(equivalent to --include)")
@@ -297,9 +334,16 @@
kwargs["test_paths"]["/"] = {}
kwargs["test_paths"]["/"]["metadata_path"] = kwargs["metadata_root"]
+ if kwargs.get("manifest_path"):
+ if "/" not in kwargs["test_paths"]:
+ kwargs["test_paths"]["/"] = {}
+ kwargs["test_paths"]["/"]["manifest_path"] = kwargs["manifest_path"]
+
kwargs["suite_name"] = kwargs["config"].get("web-platform-tests", {}).get("name", "web-platform-tests")
+ check_paths(kwargs)
+
def get_test_paths(config):
# Set up test_paths
test_paths = OrderedDict()
@@ -310,7 +354,10 @@
url_base = manifest_opts.get("url_base", "/")
test_paths[url_base] = {
"tests_path": manifest_opts.get_path("tests"),
- "metadata_path": manifest_opts.get_path("metadata")}
+ "metadata_path": manifest_opts.get_path("metadata"),
+ }
+ if "manifest" in manifest_opts:
+ test_paths[url_base]["manifest_path"] = manifest_opts.get_path("manifest")
return test_paths
@@ -326,17 +373,23 @@
return None
-def check_args(kwargs):
- set_from_config(kwargs)
-
+def check_paths(kwargs):
for test_paths in kwargs["test_paths"].itervalues():
if not ("tests_path" in test_paths and
"metadata_path" in test_paths):
print "Fatal: must specify both a test path and metadata path"
sys.exit(1)
+ if "manifest_path" not in test_paths:
+ test_paths["manifest_path"] = os.path.join(test_paths["metadata_path"],
+ "MANIFEST.json")
for key, path in test_paths.iteritems():
name = key.split("_", 1)[0]
+ if name == "manifest":
+ # For the manifest we can create it later, so just check the path
+ # actually exists
+ path = os.path.dirname(path)
+
if not os.path.exists(path):
print "Fatal: %s path %s does not exist" % (name, path)
sys.exit(1)
@@ -345,6 +398,10 @@
print "Fatal: %s path %s is not a directory" % (name, path)
sys.exit(1)
+
+def check_args(kwargs):
+ set_from_config(kwargs)
+
if kwargs["product"] is None:
kwargs["product"] = "firefox"
@@ -467,6 +524,8 @@
help="Path to the folder containing test metadata"),
parser.add_argument("--tests", action="store", type=abs_path, dest="tests_root",
help="Path to web-platform-tests"),
+ parser.add_argument("--manifest", action="store", type=abs_path, dest="manifest_path",
+ help="Path to test manifest (default is ${metadata_root}/MANIFEST.json)")
parser.add_argument("--sync-path", action="store", type=abs_path,
help="Path to store git checkout of web-platform-tests during update"),
parser.add_argument("--remote_url", action="store",
@@ -491,6 +550,8 @@
help="List of glob-style paths to exclude when syncing tests")
parser.add_argument("--include", action="store", nargs="*",
help="List of glob-style paths to include which would otherwise be excluded when syncing tests")
+ parser.add_argument("--extra-property", action="append", default=[],
+ help="Extra property from run_info.json to use in metadata update")
# Should make this required iff run=logfile
parser.add_argument("run_log", nargs="*", type=abs_path,
help="Log file from run of tests")
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py
index d3d9d07..40863d8 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py
@@ -173,6 +173,7 @@
logger.info("Using %i client processes" % kwargs["processes"])
+ test_total = 0
unexpected_total = 0
kwargs["pause_after_test"] = get_pause_after_test(test_loader, **kwargs)
@@ -200,6 +201,7 @@
elif repeat > 1:
logger.info("Repetition %i / %i" % (repeat_count, repeat))
+ test_count = 0
unexpected_count = 0
logger.suite_start(test_loader.test_ids, name='web-platform-test', run_info=run_info)
for test_type in kwargs["test_types"]:
@@ -267,20 +269,32 @@
logger.critical("Main thread got signal")
manager_group.stop()
raise
+ test_count += manager_group.test_count()
unexpected_count += manager_group.unexpected_count()
+ test_total += test_count
unexpected_total += unexpected_count
logger.info("Got %i unexpected results" % unexpected_count)
if repeat_until_unexpected and unexpected_total > 0:
break
logger.suite_end()
+
+ if test_total == 0:
+ logger.error("No tests ran")
+ return False
+
return unexpected_total == 0
def check_stability(**kwargs):
import stability
- return stability.check_stability(logger, **kwargs)
-
+ return stability.check_stability(logger,
+ max_time=kwargs['verify_max_time'],
+ chaos_mode=kwargs['verify_chaos_mode'],
+ repeat_loop=kwargs['verify_repeat_loop'],
+ repeat_restart=kwargs['verify_repeat_restart'],
+ output_results=kwargs['verify_output_results'],
+ **kwargs)
def start(**kwargs):
if kwargs["list_test_groups"]:
diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wpttest.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wpttest.py
index 9f4c1be..0fb1bdd 100644
--- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wpttest.py
+++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wpttest.py
@@ -36,7 +36,7 @@
class TestharnessResult(Result):
default_expected = "OK"
- statuses = set(["OK", "ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"])
+ statuses = set(["OK", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"])
class TestharnessSubtestResult(SubtestResult):
@@ -46,12 +46,13 @@
class ReftestResult(Result):
default_expected = "PASS"
- statuses = set(["PASS", "FAIL", "ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"])
+ statuses = set(["PASS", "FAIL", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT",
+ "CRASH"])
class WdspecResult(Result):
default_expected = "OK"
- statuses = set(["OK", "ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"])
+ statuses = set(["OK", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"])
class WdspecSubtestResult(SubtestResult):
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py
index fdd43e2..85a23d4 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py
@@ -1,39 +1,9 @@
-# META: timeout=long
-
import pytest
from tests.actions.support.refine import filter_dict, get_events
from tests.actions.support.keys import Keys
-# Using local fixtures because we want to start a new session between
-# each test, otherwise the clicks in each test interfere with each other.
-@pytest.fixture(autouse=True)
-def release_actions(mod_click_session, request):
- request.addfinalizer(mod_click_session.actions.release)
-
-
-@pytest.fixture
-def mod_click_session(new_session, url, add_browser_capabilites):
- _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
- session.url = url("/webdriver/tests/actions/support/test_actions_wdspec.html")
-
- return session
-
-
-@pytest.fixture
-def key_chain(mod_click_session):
- return mod_click_session.actions.sequence("key", "keyboard_id")
-
-
-@pytest.fixture
-def mouse_chain(mod_click_session):
- return mod_click_session.actions.sequence(
- "pointer",
- "pointer_id",
- {"pointerType": "mouse"})
-
-
@pytest.mark.parametrize("modifier, prop", [
(Keys.ALT, "altKey"),
(Keys.R_ALT, "altKey"),
@@ -42,19 +12,15 @@
(Keys.SHIFT, "shiftKey"),
(Keys.R_SHIFT, "shiftKey"),
])
-def test_modifier_click(mod_click_session,
- key_chain,
- mouse_chain,
- modifier,
- prop):
+def test_modifier_click(session, test_actions_page, key_chain, mouse_chain, modifier, prop):
key_chain \
.pause(200) \
.key_down(modifier) \
.pause(200) \
.key_up(modifier)
- outer = mod_click_session.find.css("#outer", all=False)
+ outer = session.find.css("#outer", all=False)
mouse_chain.click(element=outer)
- mod_click_session.actions.perform([key_chain.dict, mouse_chain.dict])
+ session.actions.perform([key_chain.dict, mouse_chain.dict])
expected = [
{"type": "mousemove"},
{"type": "mousedown"},
@@ -71,12 +37,12 @@
e.update(defaults)
if e["type"] != "mousemove":
e[prop] = True
- filtered_events = [filter_dict(e, expected[0]) for e in get_events(mod_click_session)]
+ filtered_events = [filter_dict(e, expected[0]) for e in get_events(session)]
assert expected == filtered_events
-def test_many_modifiers_click(mod_click_session, key_chain, mouse_chain):
- outer = mod_click_session.find.css("#outer", all=False)
+def test_many_modifiers_click(session, test_actions_page, key_chain, mouse_chain):
+ outer = session.find.css("#outer", all=False)
key_chain \
.pause(0) \
.key_down(Keys.CONTROL) \
@@ -92,7 +58,7 @@
.pause(0) \
.pause(0) \
.pointer_down()
- mod_click_session.actions.perform([key_chain.dict, mouse_chain.dict])
+ session.actions.perform([key_chain.dict, mouse_chain.dict])
expected = [
{"type": "mousemove"},
# shift and ctrl presses
@@ -113,5 +79,5 @@
for e in expected[1:4]:
e["shiftKey"] = True
e["ctrlKey"] = True
- events = [filter_dict(e, expected[0]) for e in get_events(mod_click_session)]
+ events = [filter_dict(e, expected[0]) for e in get_events(session)]
assert events == expected
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_dblclick.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_dblclick.py
index bdd3905..fc53a51 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_dblclick.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_dblclick.py
@@ -1,40 +1,11 @@
import pytest
-from tests.actions.support.mouse import get_inview_center, get_viewport_rect
from tests.actions.support.refine import get_events, filter_dict
from tests.support.asserts import assert_move_to_coordinates
-_DBLCLICK_INTERVAL = 640
-
-
-# Using local fixtures because we want to start a new session between
-# each test, otherwise the clicks in each test interfere with each other.
-@pytest.fixture(autouse=True)
-def release_actions(dblclick_session, request):
- # release all actions after each test
- # equivalent to a teardown_function, but with access to session fixture
- request.addfinalizer(dblclick_session.actions.release)
-
-
-@pytest.fixture
-def dblclick_session(new_session, url, add_browser_capabilites):
- _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
- session.url = url("/webdriver/tests/actions/support/test_actions_wdspec.html")
-
- return session
-
-
-@pytest.fixture
-def mouse_chain(dblclick_session):
- return dblclick_session.actions.sequence(
- "pointer",
- "pointer_id",
- {"pointerType": "mouse"})
-
-
@pytest.mark.parametrize("click_pause", [0, 200])
-def test_dblclick_at_coordinates(dblclick_session, mouse_chain, click_pause):
+def test_dblclick_at_coordinates(session, test_actions_page, mouse_chain, click_pause):
div_point = {
"x": 82,
"y": 187,
@@ -45,7 +16,7 @@
.pause(click_pause) \
.click() \
.perform()
- events = get_events(dblclick_session)
+ events = get_events(session)
assert_move_to_coordinates(div_point, "outer", events)
expected = [
{"type": "mousedown", "button": 0},
@@ -59,51 +30,3 @@
assert len(events) == 8
filtered_events = [filter_dict(e, expected[0]) for e in events]
assert expected == filtered_events[1:]
-
-
-def test_dblclick_with_pause_after_second_pointerdown(dblclick_session, mouse_chain):
- outer = dblclick_session.find.css("#outer", all=False)
- center = get_inview_center(outer.rect, get_viewport_rect(dblclick_session))
- mouse_chain \
- .pointer_move(int(center["x"]), int(center["y"])) \
- .click() \
- .pointer_down() \
- .pause(_DBLCLICK_INTERVAL + 10) \
- .pointer_up() \
- .perform()
- events = get_events(dblclick_session)
- expected = [
- {"type": "mousedown", "button": 0},
- {"type": "mouseup", "button": 0},
- {"type": "click", "button": 0},
- {"type": "mousedown", "button": 0},
- {"type": "mouseup", "button": 0},
- {"type": "click", "button": 0},
- {"type": "dblclick", "button": 0},
- ]
- assert len(events) == 8
- filtered_events = [filter_dict(e, expected[0]) for e in events]
- assert expected == filtered_events[1:]
-
-
-def test_no_dblclick(dblclick_session, mouse_chain):
- outer = dblclick_session.find.css("#outer", all=False)
- center = get_inview_center(outer.rect, get_viewport_rect(dblclick_session))
- mouse_chain \
- .pointer_move(int(center["x"]), int(center["y"])) \
- .click() \
- .pause(_DBLCLICK_INTERVAL + 10) \
- .click() \
- .perform()
- events = get_events(dblclick_session)
- expected = [
- {"type": "mousedown", "button": 0},
- {"type": "mouseup", "button": 0},
- {"type": "click", "button": 0},
- {"type": "mousedown", "button": 0},
- {"type": "mouseup", "button": 0},
- {"type": "click", "button": 0},
- ]
- assert len(events) == 7
- filtered_events = [filter_dict(e, expected[0]) for e in events]
- assert expected == filtered_events[1:]
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_pause_dblclick.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_pause_dblclick.py
new file mode 100644
index 0000000..ad17967
--- /dev/null
+++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_pause_dblclick.py
@@ -0,0 +1,52 @@
+from tests.actions.support.mouse import get_inview_center, get_viewport_rect
+from tests.actions.support.refine import get_events, filter_dict
+
+_DBLCLICK_INTERVAL = 640
+
+
+def test_dblclick_with_pause_after_second_pointerdown(session, test_actions_page, mouse_chain):
+ outer = session.find.css("#outer", all=False)
+ center = get_inview_center(outer.rect, get_viewport_rect(session))
+ mouse_chain \
+ .pointer_move(int(center["x"]), int(center["y"])) \
+ .click() \
+ .pointer_down() \
+ .pause(_DBLCLICK_INTERVAL + 10) \
+ .pointer_up() \
+ .perform()
+ events = get_events(session)
+ expected = [
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "dblclick", "button": 0},
+ ]
+ assert len(events) == 8
+ filtered_events = [filter_dict(e, expected[0]) for e in events]
+ assert expected == filtered_events[1:]
+
+
+def test_no_dblclick(session, test_actions_page, mouse_chain):
+ outer = session.find.css("#outer", all=False)
+ center = get_inview_center(outer.rect, get_viewport_rect(session))
+ mouse_chain \
+ .pointer_move(int(center["x"]), int(center["y"])) \
+ .click() \
+ .pause(_DBLCLICK_INTERVAL + 10) \
+ .click() \
+ .perform()
+ events = get_events(session)
+ expected = [
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ ]
+ assert len(events) == 7
+ filtered_events = [filter_dict(e, expected[0]) for e in events]
+ assert expected == filtered_events[1:]
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/special_keys.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/special_keys.py
index f50bbc6..d2a4422 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/actions/special_keys.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/special_keys.py
@@ -2,9 +2,10 @@
import pytest
import time
+from tests.support.fixtures import configuration
from tests.actions.support.keys import ALL_EVENTS, Keys
from tests.actions.support.refine import filter_dict, get_keys, get_events
-
+from webdriver import error
@pytest.mark.parametrize("name,expected", ALL_EVENTS.items())
def test_webdriver_special_key_sends_keydown(session,
@@ -20,6 +21,9 @@
document.body.addEventListener("keydown",
function(e) { e.preventDefault() });
""")
+ if (session.capabilities["browserName"] == 'internet explorer'):
+ key_reporter.click()
+ session.execute_script("resetEvents();")
key_chain.key_down(getattr(Keys, name)).perform()
# only interested in keydown
@@ -43,3 +47,37 @@
assert entered_keys == expected["key"]
else:
assert len(entered_keys) == 0
+
+
+@pytest.mark.parametrize("value", [
+ (u"f"),
+ (u"\u0BA8\u0BBF"),
+ (u"\u1100\u1161\u11A8"),
+])
+def test_multiple_codepoint_keys_behave_correctly(session,
+ key_reporter,
+ key_chain,
+ value):
+ key_chain \
+ .key_down(value) \
+ .key_up(value) \
+ .perform()
+
+ assert get_keys(key_reporter) == value
+
+
+@pytest.mark.parametrize("value", [
+ (u"fa"),
+ (u"\u0BA8\u0BBFb"),
+ (u"\u0BA8\u0BBF\u0BA8"),
+ (u"\u1100\u1161\u11A8c")
+])
+def test_invalid_multiple_codepoint_keys_fail(session,
+ key_reporter,
+ key_chain,
+ value):
+ with pytest.raises(error.InvalidArgumentException):
+ key_chain \
+ .key_down(value) \
+ .key_up(value) \
+ .perform()
\ No newline at end of file
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/contexts/maximize_window.py b/WebDriverTests/imported/w3c/webdriver/tests/contexts/maximize_window.py
index e9257e6..6143dc1 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/contexts/maximize_window.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/contexts/maximize_window.py
@@ -12,6 +12,12 @@
return session.transport.send("POST", "session/%s/window/maximize" % session.session_id)
+def is_fullscreen(session):
+ # At the time of writing, WebKit does not conform to the Fullscreen API specification.
+ # Remove the prefixed fallback when https://bugs.webkit.org/show_bug.cgi?id=158125 is fixed.
+ return session.execute_script("return !!(window.fullScreen || document.webkitIsFullScreen)")
+
+
# 10.7.3 Maximize Window
@@ -137,11 +143,11 @@
"""
session.window.fullscreen()
- assert session.execute_script("return window.fullScreen") is True
+ assert is_fullscreen(session) is True
response = maximize(session)
assert_success(response)
- assert session.execute_script("return window.fullScreen") is False
+ assert is_fullscreen(session) is False
def test_restore_the_window(session):
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py b/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py
index ff4a0c9..88b79fb 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py
@@ -36,21 +36,22 @@
assert cookie["name"] == "hello"
assert cookie["value"] == "world"
- assert cookie["domain"] == ".%s" % server_config["domains"][""]
+ assert cookie["domain"] == ".%s" % server_config["domains"][""] or cookie["domain"] == "%s" % server_config["domains"][""]
def test_add_cookie_for_ip(session, url, server_config, configuration):
- session.url = "http://127.0.0.1:%s/404" % (server_config["ports"]["http"][0])
+ session.url = "http://127.0.0.1:%s/common/blank.html" % (server_config["ports"]["http"][0])
clear_all_cookies(session)
create_cookie_request = {
"cookie": {
"name": "hello",
"value": "world",
- "domain": configuration["host"],
+ "domain": "127.0.0.1",
"path": "/",
"httpOnly": False,
"secure": False
}
}
+
result = session.transport.send("POST", "session/%s/cookie" % session.session_id, create_cookie_request)
assert result.status == 200
assert "value" in result.body
@@ -78,7 +79,7 @@
def test_add_non_session_cookie(session, url):
session.url = url("/common/blank.html")
clear_all_cookies(session)
- a_year_from_now = int((datetime.utcnow() + timedelta(days=365)).strftime("%s"))
+ a_year_from_now = int((datetime.utcnow() + timedelta(days=365) - datetime.utcfromtimestamp(0)).total_seconds())
create_cookie_request = {
"cookie": {
"name": "hello",
@@ -174,4 +175,4 @@
assert cookie["name"] == "hello"
assert cookie["value"] == "world"
- assert cookie["domain"] == ".%s" % server_config["domains"][""]
+ assert cookie["domain"] == ".%s" % server_config["domains"][""] or cookie["domain"] == "%s" % server_config["domains"][""]
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element.py
index 454e3c3..dddb28cb 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element.py
@@ -51,6 +51,39 @@
assert_success(response)
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>link text</a>", "link text"),
+ ("<a href=#> link text </a>", "link text"),
+ ("<a href=#>link<br>text</a>", "link\ntext"),
+ ("<a href=#>link&text</a>", "link&text"),
+ ("<a href=#>LINK TEXT</a>", "LINK TEXT"),
+ ("<a href=# style='text-transform: uppercase'>link text</a>", "LINK TEXT"),
+])
+def test_find_element_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline(document)
+
+ response = find_element(session, "link text", value)
+ assert_success(response)
+
+
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>partial link text</a>", "link"),
+ ("<a href=#> partial link text </a>", "link"),
+ ("<a href=#>partial link text</a>", "k t"),
+ ("<a href=#>partial link<br>text</a>", "k\nt"),
+ ("<a href=#>partial link&text</a>", "k&t"),
+ ("<a href=#>PARTIAL LINK TEXT</a>", "LINK"),
+ ("<a href=# style='text-transform: uppercase'>partial link text</a>", "LINK"),
+])
+def test_find_element_partial_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline(document)
+
+ response = find_element(session, "partial link text", value)
+ assert_success(response)
+
+
@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
def test_no_element(session, using, value):
# Step 8 - 9
@@ -65,7 +98,8 @@
("tag name", "a"),
("xpath", "//*[name()='a']")])
def test_xhtml_namespace(session, using, value):
- session.url = inline("""<a href="#" id="linkText">full link text</a>""", doctype="xhtml")
+ session.url = inline("""<a href="#" id="linkText">full link text</a>""",
+ doctype="xhtml")
expected = session.execute_script("return document.links[0]")
response = find_element(session, using, value)
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py
index d79d512..f6b9858 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py
@@ -31,7 +31,6 @@
session.close()
response = find_element(session, "notReal", "css selector", "foo")
-
assert_error(response, "no such window")
@@ -49,6 +48,41 @@
assert_success(response)
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>link text</a>", "link text"),
+ ("<a href=#> link text </a>", "link text"),
+ ("<a href=#>link<br>text</a>", "link\ntext"),
+ ("<a href=#>link&text</a>", "link&text"),
+ ("<a href=#>LINK TEXT</a>", "LINK TEXT"),
+ ("<a href=# style='text-transform: uppercase'>link text</a>", "LINK TEXT"),
+])
+def test_find_element_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline("<div>{0}</div>".format(document))
+ element = session.find.css("div", all=False)
+
+ response = find_element(session, element.id, "link text", value)
+ assert_success(response)
+
+
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>partial link text</a>", "link"),
+ ("<a href=#> partial link text </a>", "link"),
+ ("<a href=#>partial link text</a>", "k t"),
+ ("<a href=#>partial link<br>text</a>", "k\nt"),
+ ("<a href=#>partial link&text</a>", "k&t"),
+ ("<a href=#>PARTIAL LINK TEXT</a>", "LINK"),
+ ("<a href=# style='text-transform: uppercase'>partial link text</a>", "LINK"),
+])
+def test_find_element_partial_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline("<div>{0}</div>".format(document))
+ element = session.find.css("div", all=False)
+
+ response = find_element(session, element.id, "partial link text", value)
+ assert_success(response)
+
+
@pytest.mark.parametrize("using,value",[("css selector", "#wontExist")])
def test_no_element(session, using, value):
# Step 8 - 9
@@ -65,7 +99,8 @@
("tag name", "a"),
("xpath", "//*[name()='a']")])
def test_xhtml_namespace(session, using, value):
- session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
+ session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""",
+ doctype="xhtml")
from_element = session.execute_script("""return document.querySelector("p")""")
expected = session.execute_script("return document.links[0]")
@@ -76,7 +111,17 @@
def test_parent_htmldocument(session):
session.url = inline("")
+ from_element = session.execute_script("""return document.querySelector("body")""")
+ expected = session.execute_script("return document.documentElement")
+
+ response = find_element(session, from_element.id, "xpath", "..")
+ value = assert_success(response)
+ assert_same_element(session, value, expected)
+
+
+def test_parent_of_document_node_errors(session):
+ session.url = inline("")
from_element = session.execute_script("return document.documentElement")
response = find_element(session, from_element.id, "xpath", "..")
- assert_success(response)
+ assert_error(response, "invalid selector")
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements.py
index a00ae23..781dd3b 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements.py
@@ -30,10 +30,7 @@
session.window_handle = new_window
session.close()
- response = session.transport.send("POST",
- "session/%s/elements" % session.session_id,
- {"using": "css selector", "value": "foo"})
-
+ response = find_elements(session, "css selector", "foo")
assert_error(response, "no such window")
@@ -52,6 +49,51 @@
assert len(response.body["value"]) == 1
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>link text</a>", "link text"),
+ ("<a href=#> link text </a>", "link text"),
+ ("<a href=#>link<br>text</a>", "link\ntext"),
+ ("<a href=#>link&text</a>", "link&text"),
+ ("<a href=#>LINK TEXT</a>", "LINK TEXT"),
+ ("<a href=# style='text-transform: uppercase'>link text</a>", "LINK TEXT"),
+])
+def test_find_elements_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline("<a href=#>not wanted</a><br/>{0}".format(document))
+ expected = session.execute_script("return document.links[1];")
+
+ response = find_elements(session, "link text", value)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
+
+ found_element = value[0]
+ assert_same_element(session, found_element, expected)
+
+
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>partial link text</a>", "link"),
+ ("<a href=#> partial link text </a>", "link"),
+ ("<a href=#>partial link text</a>", "k t"),
+ ("<a href=#>partial link<br>text</a>", "k\nt"),
+ ("<a href=#>partial link&text</a>", "k&t"),
+ ("<a href=#>PARTIAL LINK TEXT</a>", "LINK"),
+ ("<a href=# style='text-transform: uppercase'>partial link text</a>", "LINK"),
+])
+def test_find_elements_partial_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline("<a href=#>not wanted</a><br/>{0}".format(document))
+ expected = session.execute_script("return document.links[1];")
+
+ response = find_elements(session, "partial link text", value)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
+
+ found_element = value[0]
+ assert_same_element(session, found_element, expected)
+
+
@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
def test_no_element(session, using, value):
# Step 8 - 9
@@ -67,8 +109,9 @@
("tag name", "a"),
("xpath", "//*[name()='a']")])
def test_xhtml_namespace(session, using, value):
- session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
- expected = session.execute_script("return document.links[0]")
+ session.url = inline("""<a href="#" id="linkText">full link text</a>""",
+ doctype="xhtml")
+ expected = session.execute_script("return document.links[0];")
response = find_elements(session, using, value)
value = assert_success(response)
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py
index 486d7cb..4dd8a4a 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py
@@ -48,6 +48,53 @@
assert_success(response)
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>link text</a>", "link text"),
+ ("<a href=#> link text </a>", "link text"),
+ ("<a href=#>link<br>text</a>", "link\ntext"),
+ ("<a href=#>link&text</a>", "link&text"),
+ ("<a href=#>LINK TEXT</a>", "LINK TEXT"),
+ ("<a href=# style='text-transform: uppercase'>link text</a>", "LINK TEXT"),
+])
+def test_find_elements_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline("<div><a href=#>not wanted</a><br/>{0}</div>".format(document))
+ element = session.find.css("div", all=False)
+ expected = session.execute_script("return document.links[1];")
+
+ response = find_elements(session, element.id, "link text", value)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
+
+ found_element = value[0]
+ assert_same_element(session, found_element, expected)
+
+
+@pytest.mark.parametrize("document,value", [
+ ("<a href=#>partial link text</a>", "link"),
+ ("<a href=#> partial link text </a>", "link"),
+ ("<a href=#>partial link text</a>", "k t"),
+ ("<a href=#>partial link<br>text</a>", "k\nt"),
+ ("<a href=#>partial link&text</a>", "k&t"),
+ ("<a href=#>PARTIAL LINK TEXT</a>", "LINK"),
+ ("<a href=# style='text-transform: uppercase'>partial link text</a>", "LINK"),
+])
+def test_find_elements_partial_link_text(session, document, value):
+ # Step 8 - 9
+ session.url = inline("<div><a href=#>not wanted</a><br/>{0}</div>".format(document))
+ element = session.find.css("div", all=False)
+ expected = session.execute_script("return document.links[1];")
+
+ response = find_elements(session, element.id, "partial link text", value)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
+
+ found_element = value[0]
+ assert_same_element(session, found_element, expected)
+
+
@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
def test_no_element(session, using, value):
# Step 8 - 9
@@ -64,7 +111,8 @@
("tag name", "a"),
("xpath", "//*[name()='a']")])
def test_xhtml_namespace(session, using, value):
- session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
+ session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""",
+ doctype="xhtml")
from_element = session.execute_script("""return document.querySelector("p")""")
expected = session.execute_script("return document.links[0]")
@@ -79,9 +127,21 @@
def test_parent_htmldocument(session):
session.url = inline("")
- from_element = session.execute_script("return document.documentElement")
+ from_element = session.execute_script("""return document.querySelector("body")""")
+ expected = session.execute_script("return document.documentElement")
response = find_elements(session, from_element.id, "xpath", "..")
value = assert_success(response)
assert isinstance(value, list)
assert len(value) == 1
+
+ found_element = value[0]
+ assert_same_element(session, found_element, expected)
+
+
+def test_parent_of_document_node_errors(session):
+ session.url = inline("")
+ from_element = session.execute_script("return document.documentElement")
+
+ response = find_elements(session, from_element.id, "xpath", "..")
+ assert_error(response, "invalid selector")
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/form_controls.py b/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/form_controls.py
index 855d662..28df05f 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/form_controls.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/form_controls.py
@@ -20,10 +20,10 @@
def add_event_listeners(element):
element.session.execute_script("""
- let [target] = arguments;
window.events = [];
- for (let expected of ["focus", "change", "keypress", "keydown", "keyup", "input"]) {
- target.addEventListener(expected, ({type}) => window.events.push(type));
+ var trackedEvents = ["focus", "change", "keypress", "keydown", "keyup", "input"];
+ for (var i = 0; i < trackedEvents.length; i++) {
+ arguments[0].addEventListener(trackedEvents[i], function(eventObject) { window.events.push(eventObject.type) });
}
""", args=(element,))
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/execute_async_script/collections.py b/WebDriverTests/imported/w3c/webdriver/tests/execute_async_script/collections.py
new file mode 100644
index 0000000..5affdc9
--- /dev/null
+++ b/WebDriverTests/imported/w3c/webdriver/tests/execute_async_script/collections.py
@@ -0,0 +1,158 @@
+import os
+
+from tests.support.asserts import assert_same_element, assert_success
+from tests.support.inline import inline
+
+
+def execute_async_script(session, script, args=None):
+ if args is None:
+ args = []
+ body = {"script": script, "args": args}
+ return session.transport.send(
+ "POST",
+ "/session/{session_id}/execute/async".format(**vars(session)),
+ body)
+
+
+def test_arguments(session):
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ function func() {
+ return arguments;
+ }
+ resolve(func("foo", "bar"));
+ """)
+ assert_success(response, [u"foo", u"bar"])
+
+
+def test_array(session):
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ resolve([1, 2]);
+ """)
+ assert_success(response, [1, 2])
+
+
+def test_file_list(session, tmpdir):
+ files = [tmpdir.join("foo.txt"), tmpdir.join("bar.txt")]
+
+ session.url = inline("<input type=file multiple>")
+ upload = session.find.css("input", all=False)
+ for file in files:
+ file.write("morn morn")
+ upload.send_keys(str(file))
+
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ resolve(document.querySelector('input').files);
+ """)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == len(files)
+ for expected, actual in zip(files, value):
+ assert isinstance(actual, dict)
+ assert "name" in actual
+ assert isinstance(actual["name"], basestring)
+ assert os.path.basename(str(expected)) == actual["name"]
+
+
+def test_html_all_collection(session):
+ session.url = inline("""
+ <p>foo
+ <p>bar
+ """)
+ html = session.find.css("html", all=False)
+ head = session.find.css("head", all=False)
+ body = session.find.css("body", all=False)
+ ps = session.find.css("p")
+
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ resolve(document.all);
+ """)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ # <html>, <head>, <body>, <p>, <p>
+ assert len(value) == 5
+
+ assert_same_element(session, html, value[0])
+ assert_same_element(session, head, value[1])
+ assert_same_element(session, body, value[2])
+ assert_same_element(session, ps[0], value[3])
+ assert_same_element(session, ps[1], value[4])
+
+
+def test_html_collection(session):
+ session.url = inline("""
+ <p>foo
+ <p>bar
+ """)
+ ps = session.find.css("p")
+
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ resolve(document.getElementsByTagName('p'));
+ """)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(ps, value):
+ assert_same_element(session, expected, actual)
+
+
+def test_html_form_controls_collection(session):
+ session.url = inline("""
+ <form>
+ <input>
+ <input>
+ </form>
+ """)
+ inputs = session.find.css("input")
+
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ resolve(document.forms[0].elements);
+ """)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(inputs, value):
+ assert_same_element(session, expected, actual)
+
+
+def test_html_options_collection(session):
+ session.url = inline("""
+ <select>
+ <option>
+ <option>
+ </select>
+ """)
+ options = session.find.css("option")
+
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ resolve(document.querySelector('select').options);
+ """)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(options, value):
+ assert_same_element(session, expected, actual)
+
+
+def test_node_list(session):
+ session.url = inline("""
+ <p>foo
+ <p>bar
+ """)
+ ps = session.find.css("p")
+
+ response = execute_async_script(session, """
+ let [resolve] = arguments;
+ resolve(document.querySelectorAll('p'));
+ """)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(ps, value):
+ assert_same_element(session, expected, actual)
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/execute_async_script/user_prompts.py b/WebDriverTests/imported/w3c/webdriver/tests/execute_async_script/user_prompts.py
index 03e1762..67f5512 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/execute_async_script/user_prompts.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/execute_async_script/user_prompts.py
@@ -7,52 +7,66 @@
def test_handle_prompt_accept(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
- session.execute_async_script("window.alert('Hello');")
+ value = session.execute_async_script("window.alert('Hello');")
+ assert value is None
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.accept()
def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
- session.execute_async_script("window.alert('Hello');")
+ value = session.execute_async_script("window.alert('Hello');")
+ assert value is None
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.dismiss()
def test_handle_prompt_dismiss_and_notify(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss and notify"})}})
+ value = session.execute_async_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_async_script("window.alert('Hello');")
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.dismiss()
def test_handle_prompt_accept_and_notify(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept and notify"})}})
+ value = session.execute_async_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_async_script("window.alert('Hello');")
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.accept()
def test_handle_prompt_ignore(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "ignore"})}})
+ value = session.execute_async_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_async_script("window.alert('Hello');")
+ title = session.title
session.alert.dismiss()
def test_handle_prompt_default(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
+ value = session.execute_async_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_async_script("window.alert('Hello');")
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.dismiss()
def test_handle_prompt_twice(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
- session.execute_async_script("window.alert('Hello');window.alert('Bye');")
+ value = session.execute_async_script("window.alert('Hello');window.alert('Bye');")
+ assert value is None
+ session.alert.dismiss()
# The first alert has been accepted by the user prompt handler, the second one remains.
# FIXME: this is how browsers currently work, but the spec should clarify if this is the
# expected behavior, see https://github.com/w3c/webdriver/issues/1153.
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/execute_script/collections.py b/WebDriverTests/imported/w3c/webdriver/tests/execute_script/collections.py
new file mode 100644
index 0000000..d96c7fe
--- /dev/null
+++ b/WebDriverTests/imported/w3c/webdriver/tests/execute_script/collections.py
@@ -0,0 +1,136 @@
+import os
+
+from tests.support.asserts import assert_same_element, assert_success
+from tests.support.inline import inline
+
+
+def execute_script(session, script, args=None):
+ if args is None:
+ args = []
+ body = {"script": script, "args": args}
+ return session.transport.send(
+ "POST",
+ "/session/{session_id}/execute/sync".format(**vars(session)),
+ body)
+
+
+def test_arguments(session):
+ response = execute_script(session, """
+ function func() {
+ return arguments;
+ }
+ return func("foo", "bar");
+ """)
+ assert_success(response, [u"foo", u"bar"])
+
+
+def test_array(session):
+ response = execute_script(session, "return [1, 2]")
+ assert_success(response, [1, 2])
+
+
+def test_file_list(session, tmpdir):
+ files = [tmpdir.join("foo.txt"), tmpdir.join("bar.txt")]
+
+ session.url = inline("<input type=file multiple>")
+ upload = session.find.css("input", all=False)
+ for file in files:
+ file.write("morn morn")
+ upload.send_keys(str(file))
+
+ response = execute_script(session, "return document.querySelector('input').files")
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == len(files)
+ for expected, actual in zip(files, value):
+ assert isinstance(actual, dict)
+ assert "name" in actual
+ assert isinstance(actual["name"], basestring)
+ assert os.path.basename(str(expected)) == actual["name"]
+
+
+def test_html_all_collection(session):
+ session.url = inline("""
+ <p>foo
+ <p>bar
+ """)
+ html = session.find.css("html", all=False)
+ head = session.find.css("head", all=False)
+ body = session.find.css("body", all=False)
+ ps = session.find.css("p")
+
+ response = execute_script(session, "return document.all")
+ value = assert_success(response)
+ assert isinstance(value, list)
+ # <html>, <head>, <body>, <p>, <p>
+ assert len(value) == 5
+
+ assert_same_element(session, html, value[0])
+ assert_same_element(session, head, value[1])
+ assert_same_element(session, body, value[2])
+ assert_same_element(session, ps[0], value[3])
+ assert_same_element(session, ps[1], value[4])
+
+
+def test_html_collection(session):
+ session.url = inline("""
+ <p>foo
+ <p>bar
+ """)
+ ps = session.find.css("p")
+
+ response = execute_script(session, "return document.getElementsByTagName('p')")
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(ps, value):
+ assert_same_element(session, expected, actual)
+
+
+def test_html_form_controls_collection(session):
+ session.url = inline("""
+ <form>
+ <input>
+ <input>
+ </form>
+ """)
+ inputs = session.find.css("input")
+
+ response = execute_script(session, "return document.forms[0].elements")
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(inputs, value):
+ assert_same_element(session, expected, actual)
+
+
+def test_html_options_collection(session):
+ session.url = inline("""
+ <select>
+ <option>
+ <option>
+ </select>
+ """)
+ options = session.find.css("option")
+
+ response = execute_script(session, "return document.querySelector('select').options")
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(options, value):
+ assert_same_element(session, expected, actual)
+
+
+def test_node_list(session):
+ session.url = inline("""
+ <p>foo
+ <p>bar
+ """)
+ ps = session.find.css("p")
+
+ response = execute_script(session, "return document.querySelectorAll('p')")
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 2
+ for expected, actual in zip(ps, value):
+ assert_same_element(session, expected, actual)
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/execute_script/user_prompts.py b/WebDriverTests/imported/w3c/webdriver/tests/execute_script/user_prompts.py
index 8d91bdd..befa8d8 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/execute_script/user_prompts.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/execute_script/user_prompts.py
@@ -7,52 +7,66 @@
def test_handle_prompt_accept(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
- session.execute_script("window.alert('Hello');")
+ value = session.execute_script("window.alert('Hello');")
+ assert value is None
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.accept()
def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
- session.execute_script("window.alert('Hello');")
+ value = session.execute_script("window.alert('Hello');")
+ assert value is None
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.dismiss()
def test_handle_prompt_dismiss_and_notify(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss and notify"})}})
+ value = session.execute_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_script("window.alert('Hello');")
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.dismiss()
def test_handle_prompt_accept_and_notify(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept and notify"})}})
+ value = session.execute_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_script("window.alert('Hello');")
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.accept()
def test_handle_prompt_ignore(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "ignore"})}})
+ value = session.execute_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_script("window.alert('Hello');")
+ title = session.title
session.alert.dismiss()
def test_handle_prompt_default(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
+ value = session.execute_script("window.alert('Hello');")
+ assert value is None
with pytest.raises(error.UnexpectedAlertOpenException):
- session.execute_script("window.alert('Hello');")
+ title = session.title
with pytest.raises(error.NoSuchAlertException):
session.alert.dismiss()
def test_handle_prompt_twice(new_session, add_browser_capabilites):
_, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
- session.execute_script("window.alert('Hello');window.alert('Bye');")
+ value = session.execute_script("window.alert('Hello');window.alert('Bye');")
+ assert value is None
+ session.alert.dismiss()
# The first alert has been accepted by the user prompt handler, the second one remains.
# FIXME: this is how browsers currently work, but the spec should clarify if this is the
# expected behavior, see https://github.com/w3c/webdriver/issues/1153.
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/fullscreen_window.py b/WebDriverTests/imported/w3c/webdriver/tests/fullscreen_window.py
index 43eecc5..36dd78f 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/fullscreen_window.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/fullscreen_window.py
@@ -16,6 +16,12 @@
return session.transport.send("POST", "session/%s/window/fullscreen" % session.session_id)
+def is_fullscreen(session):
+ # At the time of writing, WebKit does not conform to the Fullscreen API specification.
+ # Remove the prefixed fallback when https://bugs.webkit.org/show_bug.cgi?id=158125 is fixed.
+ return session.execute_script("return !!(window.fullScreen || document.webkitIsFullScreen)")
+
+
# 10.7.5 Fullscreen Window
@@ -135,11 +141,6 @@
assert read_global(session, "dismiss3") == None
-def is_fullscreen(session):
- # At the time of writing, WebKit does not conform to the Fullscreen API specification.
- # Remove the prefixed fallback when https://bugs.webkit.org/show_bug.cgi?id=158125 is fixed.
- return session.execute_script("return !!(window.fullScreen || document.webkitIsFullScreen)")
-
def test_fullscreen(session):
"""
4. Call fullscreen an element with the current top-level browsing
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/interaction/element_clear.py b/WebDriverTests/imported/w3c/webdriver/tests/interaction/element_clear.py
index 0443995..ceec0e2 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/interaction/element_clear.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/interaction/element_clear.py
@@ -9,13 +9,13 @@
)
from tests.support.inline import inline
-
def add_event_listeners(element):
element.session.execute_script("""
- let [target] = arguments;
+ var target = arguments[0];
window.events = [];
- for (let expected of ["focus", "blur", "change"]) {
- target.addEventListener(expected, ({type}) => window.events.push(type));
+ var expectedEvents = ["focus", "blur", "change"];
+ for (var i = 0; i < expectedEvents.length; i++) {
+ target.addEventListener(expectedEvents[i], function (eventObject) { window.events.push(eventObject.type) });
}
""", args=(element,))
@@ -272,7 +272,6 @@
assert_element_has_focus(session.execute_script("return document.body"))
-
def test_designmode(session):
session.url = inline("foobar")
element = session.find.css("body", all=False)
@@ -323,7 +322,7 @@
def is_valid(element):
return session.execute_script("""
- let [input] = arguments;
+ var input = arguments[0];
return input.validity.valid;
""", args=(element,))
@@ -361,12 +360,12 @@
""")
element = session.find.css("input", all=False)
assert element.property("value") == "foobar"
- assert session.execute_script("return window.scrollY") == 0
+ assert session.execute_script("return window.pageYOffset") == 0
# scroll to the bottom right of the page
session.execute_script("""
- let {scrollWidth, scrollHeight} = document.body;
- window.scrollTo(scrollWidth, scrollHeight);
+ var body = document.body;
+ window.scrollTo(body.scrollWidth, body.scrollHeight);
""")
# clear and scroll back to the top of the page
@@ -376,12 +375,18 @@
# check if element cleared is scrolled into view
rect = session.execute_script("""
- let [input] = arguments;
- return input.getBoundingClientRect();
+ var input = arguments[0];
+ var rect = input.getBoundingClientRect();
+ return {"top": rect.top,
+ "left": rect.left,
+ "height": rect.height,
+ "width": rect.width};
""", args=(element,))
window = session.execute_script("""
- let {innerHeight, innerWidth, pageXOffset, pageYOffset} = window;
- return {innerHeight, innerWidth, pageXOffset, pageYOffset};
+ return {"innerHeight": window.innerHeight,
+ "innerWidth": window.innerWidth,
+ "pageXOffset": window.pageXOffset,
+ "pageYOffset": window.pageYOffset};
""")
assert rect["top"] < (window["innerHeight"] + window["pageYOffset"]) and \
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/minimize_window.py b/WebDriverTests/imported/w3c/webdriver/tests/minimize_window.py
index 5c0ef72..ff451de 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/minimize_window.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/minimize_window.py
@@ -10,6 +10,11 @@
return session.transport.send("POST", "session/%s/window/minimize" % session.session_id)
+def is_fullscreen(session):
+ # At the time of writing, WebKit does not conform to the Fullscreen API specification.
+ # Remove the prefixed fallback when https://bugs.webkit.org/show_bug.cgi?id=158125 is fixed.
+ return session.execute_script("return !!(window.fullScreen || document.webkitIsFullScreen)")
+
# 10.7.4 Minimize Window
@@ -135,11 +140,11 @@
"""
session.window.fullscreen()
- assert session.execute_script("return window.fullScreen") is True
+ assert is_fullscreen(session) is True
response = minimize(session)
assert_success(response)
- assert session.execute_script("return window.fullScreen") is False
+ assert is_fullscreen(session) is False
assert session.execute_script("return document.hidden") is True
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/set_window_rect.py b/WebDriverTests/imported/w3c/webdriver/tests/set_window_rect.py
index f945f19..d032b9b 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/set_window_rect.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/set_window_rect.py
@@ -13,6 +13,11 @@
def set_window_rect(session, rect):
return session.transport.send("POST", "session/%s/window/rect" % session.session_id, rect)
+def is_fullscreen(session):
+ # At the time of writing, WebKit does not conform to the Fullscreen API specification.
+ # Remove the prefixed fallback when https://bugs.webkit.org/show_bug.cgi?id=158125 is fixed.
+ return session.execute_script("return !!(window.fullScreen || document.webkitIsFullScreen)")
+
# 10.7.2 Set Window Rect
@@ -293,14 +298,14 @@
3. Exit fullscreen document.
"""
session.window.fullscreen()
- assert session.execute_script("return window.fullScreen") is True
+ assert is_fullscreen(session) is True
response = set_window_rect(session, {"width": 400, "height": 400})
value = assert_success(response)
assert value["width"] == 400
assert value["height"] == 400
- assert session.execute_script("return window.fullScreen") is False
+ assert is_fullscreen(session) is False
def test_restore_from_minimized(session):
diff --git a/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py b/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py
index 844ae03..6a20fec 100644
--- a/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py
+++ b/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py
@@ -1,28 +1,26 @@
+from __future__ import print_function
+
import json
import os
import urlparse
import re
+import sys
import webdriver
-import mozlog
-from tests.support.asserts import assert_error
from tests.support.http_request import HTTPRequest
from tests.support.wait import wait
-from tests.support import merge_dictionaries
default_host = "http://127.0.0.1"
default_port = "4444"
-logger = mozlog.get_default_logger()
-
def ignore_exceptions(f):
def inner(*args, **kwargs):
try:
return f(*args, **kwargs)
except webdriver.error.WebDriverException as e:
- logger.warning("Ignored exception %s" % e)
+ print("Ignored exception %s" % e, file=sys.stderr)
inner.__name__ = f.__name__
return inner
@@ -182,7 +180,8 @@
global _current_session
if _current_session is not None and _current_session.session_id:
_current_session.end()
- _current_session = None
+
+ _current_session = None
def create_session(body):
global _current_session
@@ -215,7 +214,7 @@
def url(server_config):
def inner(path, protocol="http", query="", fragment=""):
port = server_config["ports"][protocol][0]
- host = "%s:%s" % (server_config["host"], port)
+ host = "%s:%s" % (server_config["browser_host"], port)
return urlparse.urlunsplit((protocol, host, path, query, fragment))
inner.__name__ = "url"