diff --git a/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini b/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini index dd4ffcf4345..76b398963ae 100644 --- a/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini +++ b/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini @@ -1,4 +1,5 @@ [url-in-tags-revoke.window.html] + expected: TIMEOUT [Fetching a blob URL immediately before revoking it works in an iframe.] expected: FAIL @@ -14,3 +15,6 @@ [Opening a blob URL in a new window by clicking an tag works immediately before revoking the URL.] expected: FAIL + [Fetching a blob URL immediately before revoking it works in diff --git a/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-initial.html b/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-initial.html index 24543d5c5fd..77aa9cd11a3 100644 --- a/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-initial.html +++ b/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-initial.html @@ -1,35 +1,45 @@ - + - +
diff --git a/tests/wpt/web-platform-tests/css/css-properties-values-api/resources/utils.js b/tests/wpt/web-platform-tests/css/css-properties-values-api/resources/utils.js index c4dc3fd5a8d..bef59560f68 100644 --- a/tests/wpt/web-platform-tests/css/css-properties-values-api/resources/utils.js +++ b/tests/wpt/web-platform-tests/css/css-properties-values-api/resources/utils.js @@ -50,6 +50,14 @@ function any_initial_value(syntax) { // generated. If a single string is used as the argument, it is assumed to be // the syntax. function generate_property(reg) { + // Verify that only valid keys are specified. This prevents the caller from + // accidentally supplying 'inherited' instead of 'inherits', for example. + if (typeof(reg) === 'object') { + const permitted = new Set(['name', 'syntax', 'initialValue', 'inherits']); + if (!Object.keys(reg).every(k => permitted.has(k))) + throw new Error('generate_property: invalid parameter'); + } + let syntax = typeof(reg) === 'string' ? reg : reg.syntax; let initial = typeof(reg.initialValue) === 'undefined' ? any_initial_value(syntax) : reg.initialValue; diff --git a/tests/wpt/web-platform-tests/css/css-properties-values-api/self-utils.html b/tests/wpt/web-platform-tests/css/css-properties-values-api/self-utils.html index 530c5f677ad..05aa4b2fb03 100644 --- a/tests/wpt/web-platform-tests/css/css-properties-values-api/self-utils.html +++ b/tests/wpt/web-platform-tests/css/css-properties-values-api/self-utils.html @@ -32,4 +32,10 @@ test(function(){ } }, 'Generated properties respect inherits flag'); +test(function(){ + assert_throws(new Error(), () => generate_property({syntax: '', foo: 1})); + assert_throws(new Error(), () => generate_property({syntax: '', inherited: false})); + assert_throws(new Error(), () => generate_property({syntax: '', initial: '10px'})); +}, 'Can\'t generate property with unknown fields'); + diff --git a/tests/wpt/web-platform-tests/css/css-transforms/text-perspective-001.html b/tests/wpt/web-platform-tests/css/css-transforms/text-perspective-001.html new file mode 100644 index 00000000000..e98b3e73b36 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-transforms/text-perspective-001.html @@ -0,0 +1,27 @@ + + +CSS Test: Text is not incorrectly clipped in presence of perspective. + + + + + +
+
+

X

+
+
diff --git a/tests/wpt/web-platform-tests/css/geometry/META.yml b/tests/wpt/web-platform-tests/css/geometry/META.yml index 9e3a7979ed8..98a2ae9860b 100644 --- a/tests/wpt/web-platform-tests/css/geometry/META.yml +++ b/tests/wpt/web-platform-tests/css/geometry/META.yml @@ -1,5 +1,4 @@ spec: https://drafts.fxtf.org/geometry/ suggested_reviewers: - peterjoel - - tschneidereit - dirkschulze diff --git a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1-ref.html b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1-ref.html index a9d8056ccab..b64aa46bf2e 100644 --- a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1-ref.html +++ b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1-ref.html @@ -9,7 +9,7 @@ p { height: 50px; width: 200px; border: thin solid; - background-image: url(../backgrounds/blue-32x32.png); + background-image: url(support/blue-32x32.png); background-repeat: no-repeat; } diff --git a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1.html b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1.html index 2a8bfdf65b0..68351aef6e5 100644 --- a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1.html +++ b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-position-1.html @@ -11,7 +11,7 @@ p { height: 50px; width: 200px; border: thin solid; - background-image: url(../backgrounds/blue-32x32.png); + background-image: url(support/blue-32x32.png); background-repeat: no-repeat; } diff --git a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1-ref.html b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1-ref.html index 16b89c1d805..5385c46ef52 100644 --- a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1-ref.html +++ b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1-ref.html @@ -9,7 +9,7 @@ p { height: 50px; width: 200px; border: thin solid; - background-image: url(../backgrounds/blue-32x32.png); + background-image: url(support/blue-32x32.png); background-repeat: no-repeat; } diff --git a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1.html b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1.html index e91f8c26ce1..f52ceeeabe1 100644 --- a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1.html +++ b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/calc-background-size-1.html @@ -11,7 +11,7 @@ p { height: 50px; width: 200px; border: thin solid; - background-image: url(../backgrounds/blue-32x32.png); + background-image: url(support/blue-32x32.png); background-repeat: no-repeat; } diff --git a/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/support/blue-32x32.png b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/support/blue-32x32.png new file mode 100644 index 00000000000..deefd19b2ac Binary files /dev/null and b/tests/wpt/web-platform-tests/css/vendor-imports/mozilla/mozilla-central-reftests/values3/support/blue-32x32.png differ diff --git a/tests/wpt/web-platform-tests/html/dom/elements/the-innertext-idl-attribute/getter-tests.js b/tests/wpt/web-platform-tests/html/dom/elements/the-innertext-idl-attribute/getter-tests.js index 5139ec97b05..4dd2b6be206 100644 --- a/tests/wpt/web-platform-tests/html/dom/elements/the-innertext-idl-attribute/getter-tests.js +++ b/tests/wpt/web-platform-tests/html/dom/elements/the-innertext-idl-attribute/getter-tests.js @@ -273,6 +273,11 @@ testText("
abc
def
ghi", " testText("
abc
def\n123
ghi", "abcdef\n123ghi", "Single newline in two-row inline-table"); +/**** display:table-row/table-cell/table-caption ****/ +testText("
", "", "display:table-row on the element itself"); +testText("
", "", "display:table-cell on the element itself"); +testText("
", "", "display:table-caption on the element itself"); + /**** Lists ****/ testText("
  1. abc", "abc", "
      list items get no special treatment"); @@ -293,6 +298,9 @@ testText("
      abc

      def", "abc\ndef", "

      induces just one line brea testText("
      abc


      def", "abc\ndef", "


      induces just one line break"); testText("

      ", "abc", "
      content rendered"); testText("
      abcdef", "abcdef", "comment ignored"); +testText("
      ", "", "
      "); +testText("

      ", "", "empty

      "); +testText("

      ", "", "empty
      "); /**** text-transform ****/ @@ -308,11 +316,13 @@ testText("
      abc123
      456
      789
      def", "abc123\n456\n789def", testText("
      abc
      123
      def", "abc\n123\ndef", "floats induce a block boundary"); testText("
      abc123def", "abc\n123\ndef", "floats induce a block boundary"); +testText("
      123", "123", "float on the element itself"); /**** position ****/ testText("
      abc
      123
      def", "abc\n123\ndef", "position:absolute induces a block boundary"); testText("
      abc123def", "abc\n123\ndef", "position:absolute induces a block boundary"); +testText("
      123", "123", "position:absolute on the element itself"); testText("
      abc
      123
      def", "abc\n123\ndef", "position:relative has no effect"); testText("
      abc123def", "abc123def", "position:relative has no effect"); diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html new file mode 100644 index 00000000000..3e437494c0a --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html @@ -0,0 +1,33 @@ + + + + + Reference: Combobox block-size test + + + + + + +
      + +
      +
      +
      + + + diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size.html new file mode 100644 index 00000000000..4aecc596ce6 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size.html @@ -0,0 +1,38 @@ + + + + + Test: Combobox block-size test + + + + + + + + + +
      + +
      +
      +
      + + + diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-empty-ref.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-empty-ref.html new file mode 100644 index 00000000000..31ba23a5cf8 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-empty-ref.html @@ -0,0 +1,35 @@ + + + + + Reference: empty SELECT + + + + + + + +
      + + + +
      + + + +
      + + + +
      + + + diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-empty.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-empty.html new file mode 100644 index 00000000000..6568a6de349 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-empty.html @@ -0,0 +1,33 @@ + + + + + Test: empty SELECT + + + + + + + + + +
      + + + +
      + + + +
      + + + +
      + + + diff --git a/tests/wpt/web-platform-tests/pointerevents/META.yml b/tests/wpt/web-platform-tests/pointerevents/META.yml index ef94157ef9a..be61ddddaf6 100644 --- a/tests/wpt/web-platform-tests/pointerevents/META.yml +++ b/tests/wpt/web-platform-tests/pointerevents/META.yml @@ -4,6 +4,5 @@ suggested_reviewers: - jacobrossi - plehegar - scottgonzalez - - staktrace - RByers - NavidZ diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client-message-queue.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client-message-queue.https.html new file mode 100644 index 00000000000..caa4f9445d3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client-message-queue.https.html @@ -0,0 +1,211 @@ + +Service Worker: postMessage to Client (message queue) + + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client.https.html index b1dc41a018f..15d2e889337 100644 --- a/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client.https.html +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage-to-client.https.html @@ -51,208 +51,4 @@ promise_test(t => { }) .then(e => { assert_equals(e.data, 'quit'); }); }, 'postMessage from ServiceWorker to Client.'); - -// This function creates a message listener that captures all messages -// sent to this window and matches them with corresponding requests. -// This frees test code from having to use clunky constructs just to -// avoid race conditions, since the relative order of message and -// request arrival doesn't matter. -function create_message_listener(t) { - const listener = { - messages: new Set(), - requests: new Set(), - waitFor: function(predicate) { - for (const event of this.messages) { - // If a message satisfying the predicate has already - // arrived, it gets matched to this request. - if (predicate(event)) { - this.messages.delete(event); - return Promise.resolve(event); - } - } - - // If no match was found, the request is stored and a - // promise is returned. - const request = { predicate }; - const promise = new Promise(resolve => request.resolve = resolve); - this.requests.add(request); - return promise; - } - }; - window.onmessage = t.step_func(event => { - for (const request of listener.requests) { - // If the new message matches a stored request's - // predicate, the request's promise is resolved with this - // message. - if (request.predicate(event)) { - listener.requests.delete(request); - request.resolve(event); - return; - } - }; - - // No outstanding request for this message, store it in case - // it's requested later. - listener.messages.add(event); - }); - return listener; -} - -async function service_worker_register_and_activate(t, script, scope) { - const registration = await service_worker_unregister_and_register(t, script, scope); - t.add_cleanup(() => registration.unregister()); - const worker = registration.installing; - await wait_for_state(t, worker, 'activated'); - return worker; -} - -// Add an iframe (parent) whose document contains a nested iframe -// (child), then set the child's src attribute to child_url and return -// its Window (without waiting for it to finish loading). -async function with_nested_iframes(t, child_url) { - const parent = await with_iframe('resources/nested-iframe-parent.html?role=parent'); - t.add_cleanup(() => parent.remove()); - const child = parent.contentWindow.document.getElementById('child'); - child.setAttribute('src', child_url); - return child.contentWindow; -} - -// Returns a predicate matching a fetch message with the specified -// key. -function fetch_message(key) { - return event => event.data.type === 'fetch' && event.data.key === key; -} - -// Returns a predicate matching a ping message with the specified -// payload. -function ping_message(data) { - return event => event.data.type === 'ping' && event.data.data === data; -} - -// A client message queue test is a testharness.js test with some -// additional setup: -// 1. A listener (see create_message_listener) -// 2. An active service worker -// 3. Two nested iframes -// 4. A state transition function that controls the order of events -// during the test -function client_message_queue_test(url, test_function, description) { - promise_test(async t => { - t.listener = create_message_listener(t); - - const script = 'resources/stalling-service-worker.js'; - const scope = 'resources/'; - t.service_worker = await service_worker_register_and_activate(t, script, scope); - - // We create two nested iframes such that both are controlled by - // the newly installed service worker. - const child_url = url + '?role=child'; - t.frame = await with_nested_iframes(t, child_url); - - t.state_transition = async function(from, to, scripts) { - // A state transition begins with the child's parser - // fetching a script due to a diff --git a/tests/wpt/web-platform-tests/speech-api/META.yml b/tests/wpt/web-platform-tests/speech-api/META.yml index 17263d91d36..ac4b89b0349 100644 --- a/tests/wpt/web-platform-tests/speech-api/META.yml +++ b/tests/wpt/web-platform-tests/speech-api/META.yml @@ -1,4 +1,3 @@ spec: https://w3c.github.io/speech-api/ suggested_reviewers: - - andrenatal - gshires diff --git a/tests/wpt/web-platform-tests/subresource-integrity/META.yml b/tests/wpt/web-platform-tests/subresource-integrity/META.yml index 740ad1412f6..2b8891ec6b4 100644 --- a/tests/wpt/web-platform-tests/subresource-integrity/META.yml +++ b/tests/wpt/web-platform-tests/subresource-integrity/META.yml @@ -1,8 +1,6 @@ spec: https://w3c.github.io/webappsec-subresource-integrity/ suggested_reviewers: - metromoxie - - fmarier - jonathanKingston - mikewest - hillbrad - - mastahyeti diff --git a/tests/wpt/web-platform-tests/tools/wpt/run.py b/tests/wpt/web-platform-tests/tools/wpt/run.py index a2cd1c0b115..b977d8a0cd6 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/run.py +++ b/tests/wpt/web-platform-tests/tools/wpt/run.py @@ -264,6 +264,8 @@ class Chrome(BrowserSetup): if kwargs["browser_channel"] == "dev": logger.info("Automatically turning on experimental features for Chrome Dev") kwargs["binary_args"].append("--enable-experimental-web-platform-features") + # TODO(foolip): remove after unified plan is enabled on Chrome stable + kwargs["binary_args"].append("--enable-features=RTCUnifiedPlanByDefault") # Allow audio autoplay without a user gesture. kwargs["binary_args"].append("--autoplay-policy=no-user-gesture-required") diff --git a/tests/wpt/web-platform-tests/tools/wpt/utils.py b/tests/wpt/web-platform-tests/tools/wpt/utils.py index 1e622a63859..fa60230389d 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/utils.py +++ b/tests/wpt/web-platform-tests/tools/wpt/utils.py @@ -1,7 +1,6 @@ import logging import os import subprocess -import sys import tarfile import zipfile from io import BytesIO @@ -49,20 +48,6 @@ def call(*args): raise -def get_git_cmd(repo_path): - """Create a function for invoking git commands as a subprocess.""" - def git(cmd, *args): - full_cmd = ["git", cmd] + list(args) - try: - logger.debug(" ".join(full_cmd)) - return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT).strip() - except subprocess.CalledProcessError as e: - logger.error("Git command exited with status %i" % e.returncode) - logger.error(e.output) - sys.exit(1) - return git - - def seekable(fileobj): """Attempt to use file.seek on given file, with fallbacks.""" try: @@ -94,21 +79,6 @@ def unzip(fileobj, dest=None, limit=None): os.chmod(os.path.join(dest, info.filename), perm) -class pwd(object): - """Create context for temporarily changing present working directory.""" - def __init__(self, dir): - self.dir = dir - self.old_dir = None - - def __enter__(self): - self.old_dir = os.path.abspath(os.curdir) - os.chdir(self.dir) - - def __exit__(self, *args, **kwargs): - os.chdir(self.old_dir) - self.old_dir = None - - def get(url): """Issue GET request to a given URL and return the response.""" import requests diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py index 2b7c091c847..e819f242e2d 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py @@ -818,14 +818,10 @@ class ManagerGroup(object): self.pool.add(manager) self.wait() - def is_alive(self): - """Boolean indicating whether any manager in the group is still alive""" - return any(manager.is_alive() for manager in self.pool) - def wait(self): """Wait for all the managers in the group to finish""" - for item in self.pool: - item.join() + for manager in self.pool: + manager.join() def stop(self): """Set the stop flag so that all managers in the group stop as soon @@ -834,7 +830,7 @@ class ManagerGroup(object): self.logger.debug("Stop flag set in ManagerGroup") def test_count(self): - return sum(item.test_count for item in self.pool) + return sum(manager.test_count for manager in self.pool) def unexpected_count(self): - return sum(item.unexpected_count for item in self.pool) + return sum(manager.unexpected_count for manager in self.pool) diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py index 0a5b1352e21..d0c1106b0f9 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py @@ -275,8 +275,8 @@ def run_tests(config, test_paths, product, **kwargs): logger.critical("Main thread got signal") manager_group.stop() raise - test_count += manager_group.test_count() - unexpected_count += manager_group.unexpected_count() + test_count += manager_group.test_count() + unexpected_count += manager_group.unexpected_count() test_total += test_count unexpected_total += unexpected_count diff --git a/tests/wpt/web-platform-tests/url/META.yml b/tests/wpt/web-platform-tests/url/META.yml index 459152f6f07..3a789a0d513 100644 --- a/tests/wpt/web-platform-tests/url/META.yml +++ b/tests/wpt/web-platform-tests/url/META.yml @@ -1,7 +1,6 @@ spec: https://url.spec.whatwg.org/ suggested_reviewers: - mikewest - - smola - domenic - Sebmaster - annevk diff --git a/tests/wpt/web-platform-tests/webaudio/META.yml b/tests/wpt/web-platform-tests/webaudio/META.yml index 37276da5334..e8f8cc59489 100644 --- a/tests/wpt/web-platform-tests/webaudio/META.yml +++ b/tests/wpt/web-platform-tests/webaudio/META.yml @@ -1,5 +1,4 @@ spec: https://webaudio.github.io/web-audio-api/ suggested_reviewers: - - chrislo - padenot - rtoy diff --git a/tests/wpt/web-platform-tests/webdriver/tests/conftest.py b/tests/wpt/web-platform-tests/webdriver/tests/conftest.py index d16883256ac..42b82c9ecf2 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/conftest.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/conftest.py @@ -1,234 +1 @@ -import copy -import json -import os -import urlparse - -import pytest -import webdriver - -from tests.support import defaults -from tests.support.helpers import cleanup_session -from tests.support.http_request import HTTPRequest -from tests.support.sync import Poll - - -_current_session = None -_custom_session = False - - -def pytest_configure(config): - # register the capabilities marker - config.addinivalue_line("markers", - "capabilities: mark test to use capabilities") - - -@pytest.fixture -def capabilities(): - """Default capabilities to use for a new WebDriver session.""" - return {} - - -def pytest_generate_tests(metafunc): - if "capabilities" in metafunc.fixturenames: - marker = metafunc.definition.get_closest_marker(name="capabilities") - if marker: - metafunc.parametrize("capabilities", marker.args, ids=None) - - -@pytest.fixture -def add_event_listeners(session): - """Register listeners for tracked events on element.""" - def add_event_listeners(element, tracked_events): - element.session.execute_script(""" - let element = arguments[0]; - let trackedEvents = arguments[1]; - - if (!("events" in window)) { - window.events = []; - } - - for (var i = 0; i < trackedEvents.length; i++) { - element.addEventListener(trackedEvents[i], function (event) { - window.events.push(event.type); - }); - } - """, args=(element, tracked_events)) - return add_event_listeners - - -@pytest.fixture -def create_cookie(session, url): - """Create a cookie""" - def create_cookie(name, value, **kwargs): - if kwargs.get("path", None) is not None: - session.url = url(kwargs["path"]) - - session.set_cookie(name, value, **kwargs) - return session.cookies(name) - - return create_cookie - - -@pytest.fixture -def create_frame(session): - """Create an `iframe` element in the current browsing context and insert it - into the document. Return a reference to the newly-created element.""" - def create_frame(): - append = """ - var frame = document.createElement('iframe'); - document.body.appendChild(frame); - return frame; - """ - return session.execute_script(append) - - return create_frame - - -@pytest.fixture -def create_window(session): - """Open new window and return the window handle.""" - def create_window(): - windows_before = session.handles - name = session.execute_script("window.open()") - assert len(session.handles) == len(windows_before) + 1 - new_windows = list(set(session.handles) - set(windows_before)) - return new_windows.pop() - return create_window - - -@pytest.fixture -def http(configuration): - return HTTPRequest(configuration["host"], configuration["port"]) - - -@pytest.fixture -def server_config(): - return json.loads(os.environ.get("WD_SERVER_CONFIG")) - - -@pytest.fixture(scope="session") -def configuration(): - host = os.environ.get("WD_HOST", defaults.DRIVER_HOST) - port = int(os.environ.get("WD_PORT", str(defaults.DRIVER_PORT))) - capabilities = json.loads(os.environ.get("WD_CAPABILITIES", "{}")) - - return { - "host": host, - "port": port, - "capabilities": capabilities - } - - -@pytest.fixture(scope="function") -def session(capabilities, configuration, request): - """Create and start a session for a test that does not itself test session creation. - - By default the session will stay open after each test, but we always try to start a - new one and assume that if that fails there is already a valid session. This makes it - possible to recover from some errors that might leave the session in a bad state, but - does not demand that we start a new session per test.""" - global _current_session - - # Update configuration capabilities with custom ones from the - # capabilities fixture, which can be set by tests - caps = copy.deepcopy(configuration["capabilities"]) - caps.update(capabilities) - caps = {"alwaysMatch": caps} - - # If there is a session with different capabilities active, end it now - if _current_session is not None and ( - caps != _current_session.requested_capabilities): - _current_session.end() - _current_session = None - - if _current_session is None: - _current_session = webdriver.Session( - configuration["host"], - configuration["port"], - capabilities=caps) - try: - _current_session.start() - except webdriver.error.SessionNotCreatedException: - if not _current_session.session_id: - raise - - # Enforce a fixed default window size - _current_session.window.size = defaults.WINDOW_SIZE - - yield _current_session - - cleanup_session(_current_session) - - -@pytest.fixture(scope="function") -def current_session(): - return _current_session - - -@pytest.fixture -def url(server_config): - def inner(path, protocol="http", query="", fragment=""): - port = server_config["ports"][protocol][0] - host = "%s:%s" % (server_config["browser_host"], port) - return urlparse.urlunsplit((protocol, host, path, query, fragment)) - - inner.__name__ = "url" - return inner - - -@pytest.fixture -def create_dialog(session): - """Create a dialog (one of "alert", "prompt", or "confirm") and provide a - function to validate that the dialog has been "handled" (either accepted or - dismissed) by returning some value.""" - - def create_dialog(dialog_type, text=None): - assert dialog_type in ("alert", "confirm", "prompt"), ( - "Invalid dialog type: '%s'" % dialog_type) - - if text is None: - text = "" - - assert isinstance(text, basestring), "`text` parameter must be a string" - - # Script completes itself when the user prompt has been opened. - # For prompt() dialogs, add a value for the 'default' argument, - # as some user agents (IE, for example) do not produce consistent - # values for the default. - session.execute_async_script(""" - let dialog_type = arguments[0]; - let text = arguments[1]; - - setTimeout(function() { - if (dialog_type == 'prompt') { - window.dialog_return_value = window[dialog_type](text, ''); - } else { - window.dialog_return_value = window[dialog_type](text); - } - }, 0); - """, args=(dialog_type, text)) - - wait = Poll( - session, - timeout=15, - ignored_exceptions=webdriver.NoSuchAlertException, - message="No user prompt with text '{}' detected".format(text)) - wait.until(lambda s: s.alert.text == text) - - return create_dialog - - -@pytest.fixture -def closed_window(session, create_window): - original_handle = session.window_handle - - new_handle = create_window() - session.window_handle = new_handle - - session.close() - assert new_handle not in session.handles, "Unable to close window {}".format(new_handle) - - yield new_handle - - session.window_handle = original_handle - +pytest_plugins = "tests.support.fixtures" diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_click/center_point.py b/tests/wpt/web-platform-tests/webdriver/tests/element_click/center_point.py index b3d2ea7a109..21bf8f31fd8 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/element_click/center_point.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/element_click/center_point.py @@ -51,7 +51,7 @@ def square(size): """.format(size=size)) diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py b/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py index cdf313bc04b..1dea6ce6877 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py @@ -1,3 +1,6 @@ +import base64 +import imghdr + from webdriver import Element, NoSuchAlertException, WebDriverException @@ -189,3 +192,10 @@ def assert_move_to_coordinates(point, target, events): assert e["pageX"] == point["x"] assert e["pageY"] == point["y"] assert e["target"] == target + + +def assert_png(screenshot): + """Test that screenshot is a Base64 encoded PNG file.""" + image = base64.decodestring(screenshot) + mime_type = imghdr.what("", image) + assert mime_type == "png", "Expected image to be PNG, but it was {}".format(mime_type) diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py b/tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py new file mode 100644 index 00000000000..d16883256ac --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py @@ -0,0 +1,234 @@ +import copy +import json +import os +import urlparse + +import pytest +import webdriver + +from tests.support import defaults +from tests.support.helpers import cleanup_session +from tests.support.http_request import HTTPRequest +from tests.support.sync import Poll + + +_current_session = None +_custom_session = False + + +def pytest_configure(config): + # register the capabilities marker + config.addinivalue_line("markers", + "capabilities: mark test to use capabilities") + + +@pytest.fixture +def capabilities(): + """Default capabilities to use for a new WebDriver session.""" + return {} + + +def pytest_generate_tests(metafunc): + if "capabilities" in metafunc.fixturenames: + marker = metafunc.definition.get_closest_marker(name="capabilities") + if marker: + metafunc.parametrize("capabilities", marker.args, ids=None) + + +@pytest.fixture +def add_event_listeners(session): + """Register listeners for tracked events on element.""" + def add_event_listeners(element, tracked_events): + element.session.execute_script(""" + let element = arguments[0]; + let trackedEvents = arguments[1]; + + if (!("events" in window)) { + window.events = []; + } + + for (var i = 0; i < trackedEvents.length; i++) { + element.addEventListener(trackedEvents[i], function (event) { + window.events.push(event.type); + }); + } + """, args=(element, tracked_events)) + return add_event_listeners + + +@pytest.fixture +def create_cookie(session, url): + """Create a cookie""" + def create_cookie(name, value, **kwargs): + if kwargs.get("path", None) is not None: + session.url = url(kwargs["path"]) + + session.set_cookie(name, value, **kwargs) + return session.cookies(name) + + return create_cookie + + +@pytest.fixture +def create_frame(session): + """Create an `iframe` element in the current browsing context and insert it + into the document. Return a reference to the newly-created element.""" + def create_frame(): + append = """ + var frame = document.createElement('iframe'); + document.body.appendChild(frame); + return frame; + """ + return session.execute_script(append) + + return create_frame + + +@pytest.fixture +def create_window(session): + """Open new window and return the window handle.""" + def create_window(): + windows_before = session.handles + name = session.execute_script("window.open()") + assert len(session.handles) == len(windows_before) + 1 + new_windows = list(set(session.handles) - set(windows_before)) + return new_windows.pop() + return create_window + + +@pytest.fixture +def http(configuration): + return HTTPRequest(configuration["host"], configuration["port"]) + + +@pytest.fixture +def server_config(): + return json.loads(os.environ.get("WD_SERVER_CONFIG")) + + +@pytest.fixture(scope="session") +def configuration(): + host = os.environ.get("WD_HOST", defaults.DRIVER_HOST) + port = int(os.environ.get("WD_PORT", str(defaults.DRIVER_PORT))) + capabilities = json.loads(os.environ.get("WD_CAPABILITIES", "{}")) + + return { + "host": host, + "port": port, + "capabilities": capabilities + } + + +@pytest.fixture(scope="function") +def session(capabilities, configuration, request): + """Create and start a session for a test that does not itself test session creation. + + By default the session will stay open after each test, but we always try to start a + new one and assume that if that fails there is already a valid session. This makes it + possible to recover from some errors that might leave the session in a bad state, but + does not demand that we start a new session per test.""" + global _current_session + + # Update configuration capabilities with custom ones from the + # capabilities fixture, which can be set by tests + caps = copy.deepcopy(configuration["capabilities"]) + caps.update(capabilities) + caps = {"alwaysMatch": caps} + + # If there is a session with different capabilities active, end it now + if _current_session is not None and ( + caps != _current_session.requested_capabilities): + _current_session.end() + _current_session = None + + if _current_session is None: + _current_session = webdriver.Session( + configuration["host"], + configuration["port"], + capabilities=caps) + try: + _current_session.start() + except webdriver.error.SessionNotCreatedException: + if not _current_session.session_id: + raise + + # Enforce a fixed default window size + _current_session.window.size = defaults.WINDOW_SIZE + + yield _current_session + + cleanup_session(_current_session) + + +@pytest.fixture(scope="function") +def current_session(): + return _current_session + + +@pytest.fixture +def url(server_config): + def inner(path, protocol="http", query="", fragment=""): + port = server_config["ports"][protocol][0] + host = "%s:%s" % (server_config["browser_host"], port) + return urlparse.urlunsplit((protocol, host, path, query, fragment)) + + inner.__name__ = "url" + return inner + + +@pytest.fixture +def create_dialog(session): + """Create a dialog (one of "alert", "prompt", or "confirm") and provide a + function to validate that the dialog has been "handled" (either accepted or + dismissed) by returning some value.""" + + def create_dialog(dialog_type, text=None): + assert dialog_type in ("alert", "confirm", "prompt"), ( + "Invalid dialog type: '%s'" % dialog_type) + + if text is None: + text = "" + + assert isinstance(text, basestring), "`text` parameter must be a string" + + # Script completes itself when the user prompt has been opened. + # For prompt() dialogs, add a value for the 'default' argument, + # as some user agents (IE, for example) do not produce consistent + # values for the default. + session.execute_async_script(""" + let dialog_type = arguments[0]; + let text = arguments[1]; + + setTimeout(function() { + if (dialog_type == 'prompt') { + window.dialog_return_value = window[dialog_type](text, ''); + } else { + window.dialog_return_value = window[dialog_type](text); + } + }, 0); + """, args=(dialog_type, text)) + + wait = Poll( + session, + timeout=15, + ignored_exceptions=webdriver.NoSuchAlertException, + message="No user prompt with text '{}' detected".format(text)) + wait.until(lambda s: s.alert.text == text) + + return create_dialog + + +@pytest.fixture +def closed_window(session, create_window): + original_handle = session.window_handle + + new_handle = create_window() + session.window_handle = new_handle + + session.close() + assert new_handle not in session.handles, "Unable to close window {}".format(new_handle) + + yield new_handle + + session.window_handle = original_handle + diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/helpers.py b/tests/wpt/web-platform-tests/webdriver/tests/support/helpers.py index b2db3e7b0d3..5dd7a323d8c 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/support/helpers.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/support/helpers.py @@ -117,3 +117,11 @@ def is_element_in_viewport(session, element): return !(rect.right < 0 || rect.bottom < 0 || rect.left > viewport.width || rect.top > viewport.height) """, args=(element,)) + + +def document_dimensions(session): + return tuple(session.execute_script(""" + let {devicePixelRatio} = window; + let {width, height} = document.documentElement.getBoundingClientRect(); + return [width * devicePixelRatio, height * devicePixelRatio]; + """)) diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/image.py b/tests/wpt/web-platform-tests/webdriver/tests/support/image.py new file mode 100644 index 00000000000..1eb3a187a43 --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/support/image.py @@ -0,0 +1,11 @@ +import base64 +import struct + +from tests.support.asserts import assert_png + + +def png_dimensions(screenshot): + assert_png(screenshot) + image = base64.decodestring(screenshot) + width, height = struct.unpack(">LL", image[16:24]) + return int(width), int(height) diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/inline.py b/tests/wpt/web-platform-tests/webdriver/tests/support/inline.py index 3bf56c84bed..8b4f1657cff 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/support/inline.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/support/inline.py @@ -2,7 +2,7 @@ import urllib def inline(doc, doctype="html", mime="text/html;charset=utf-8", protocol="http"): - from ..conftest import server_config, url + from .fixtures import server_config, url build_url = url(server_config()) if doctype == "html": diff --git a/tests/wpt/web-platform-tests/xhr/send-content-type-charset.htm b/tests/wpt/web-platform-tests/xhr/send-content-type-charset.htm index 4e75df23468..0a91e1fbd7e 100644 --- a/tests/wpt/web-platform-tests/xhr/send-content-type-charset.htm +++ b/tests/wpt/web-platform-tests/xhr/send-content-type-charset.htm @@ -4,8 +4,6 @@ XMLHttpRequest: send() - charset parameter of Content-Type - -
      @@ -45,8 +43,8 @@ ) request( "text/plain;charset=utf-8", - "text/plain;charset=UTF-8", - "Correct text/plain MIME with charset" + "text/plain;charset=utf-8", + "If charset= param is UTF-8 (case-insensitive), it should not be changed" ) request( "text/x-pink-unicorn", @@ -70,8 +68,8 @@ ) request( "text/plain;charset=utf-8;charset=waddup", - "text/plain;charset=UTF-8", - "charset given but wrong, fix it (known MIME, bogus charset)" + "text/plain;charset=utf-8;charset=waddup", + "If charset= param is UTF-8 (case-insensitive), it should not be changed (bogus charset)" ) request( "text/plain;charset=shift-jis", @@ -81,7 +79,7 @@ request( "text/x-pink-unicorn; charset=windows-1252; charset=bogus; notrelated; charset=ascii", "text/x-pink-unicorn;charset=UTF-8", - "Multiple charset parameters deduplicate, bogus parameter dropped" + "Multiple non-UTF-8 charset parameters deduplicate, bogus parameter dropped" ) request( null, @@ -90,20 +88,20 @@ ) request( "text/plain;charset= utf-8", - "text/plain;charset=UTF-8", - "charset with space") + "text/plain;charset= utf-8", + "charset with space that is UTF-8 does not change") request( "text/plain;charset=\"utf-8\"", - "text/plain;charset=UTF-8", - "charset in double quotes") + "text/plain;charset=\"utf-8\"", + "charset in double quotes that is UTF-8 does not change") request( "text/plain;charset=\" utf-8\"", "text/plain;charset=UTF-8", "charset in double quotes with space") request( "text/plain;charset=\"u\\t\\f-8\"", - "text/plain;charset=UTF-8", - "charset in double quotes with backslashes") + "text/plain;charset=\"u\\t\\f-8\"", + "charset in double quotes with backslashes that is UTF-8 does not change") request( "YO/yo;charset=x;yo=YO; X=y", "yo/yo;charset=UTF-8;yo=YO;x=y",