summaryrefslogtreecommitdiff
path: root/test/fixtures/wpt
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2019-05-22 15:52:56 +0200
committerJoyee Cheung <joyeec9h3@gmail.com>2019-05-24 18:49:04 +0200
commit2e77735c4f1b8437fca812134a28d48cad9d5808 (patch)
treefbaef8c123f947eccac2344542df46c9b44306f0 /test/fixtures/wpt
parent3293bbf77a4e940ccb8f250b65129b3c4dc44fb5 (diff)
downloadandroid-node-v8-2e77735c4f1b8437fca812134a28d48cad9d5808.tar.gz
android-node-v8-2e77735c4f1b8437fca812134a28d48cad9d5808.tar.bz2
android-node-v8-2e77735c4f1b8437fca812134a28d48cad9d5808.zip
test: update wpt/resources to e1fddfbf80
Using `git node wpt resources` PR-URL: https://github.com/nodejs/node/pull/27822 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Michaël Zasso <targos@protonmail.com>
Diffstat (limited to 'test/fixtures/wpt')
-rw-r--r--test/fixtures/wpt/LICENSE.md34
-rw-r--r--test/fixtures/wpt/README.md2
-rw-r--r--test/fixtures/wpt/resources/idlharness.js210
-rw-r--r--test/fixtures/wpt/resources/testdriver-actions.js24
-rw-r--r--test/fixtures/wpt/resources/testdriver.js86
-rw-r--r--test/fixtures/wpt/resources/testharness.js124
-rw-r--r--test/fixtures/wpt/versions.json2
7 files changed, 363 insertions, 119 deletions
diff --git a/test/fixtures/wpt/LICENSE.md b/test/fixtures/wpt/LICENSE.md
index 6b346a528c..ad4858c874 100644
--- a/test/fixtures/wpt/LICENSE.md
+++ b/test/fixtures/wpt/LICENSE.md
@@ -1,33 +1,11 @@
-# Dual-License for W3C Test Suites
+# The 3-Clause BSD License
-All documents in this Repository are licensed by contributors to be distributed under both the [W3C Test Suite License](#w3c-test-suite-license) and the [W3C 3-clause BSD License](#w3c-3-clause-bsd-license), reproduced below. The choice of license is up to the licensee. For more information, see [Licenses for W3C Test Suites](https://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html)
-
-# W3C Test Suite License
-
-This document, Test Suites and other documents that link to this statement are provided by the copyright holders under the following license: By using and/or copying this document, or the W3C document from which this statement is linked, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
-
-Permission to copy, and distribute the contents of this document, or the W3C document from which this statement is linked, in any medium for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the document, or portions thereof, that you use:
-
-* A link or URL to the original W3C document.
-* The pre-existing copyright notice of the original author, or if it doesn't exist, a notice (hypertext is preferred, but a textual representation is permitted) of the form: "Copyright © [$date-of-document] World Wide Web Consortium, (MIT, ERCIM, Keio, Beihang) and others. All Rights Reserved. http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html"
-* If it exists, the STATUS of the W3C document.
-
-When space permits, inclusion of the full text of this NOTICE should be provided. We request that authorship attribution be provided in any software, documents, or other items or products that you create pursuant to the implementation of the contents of this document, or any portion thereof.
-
-No right to create modifications or derivatives of W3C documents is granted pursuant to this license. However, if additional requirements (documented in the Copyright FAQ) are satisfied, the right to create modifications or derivatives is sometimes granted by the W3C to individuals complying with those requirements.
-
-If a Test Suite distinguishes the test harness (or, framework for navigation) and the actual tests, permission is given to remove or alter the harness or navigation if the Test Suite in question allows to do so. The tests themselves shall NOT be changed in any way.
-
-The name and trademarks of W3C and other copyright holders may NOT be used in advertising or publicity pertaining to this document or other documents that link to this statement without specific, written prior permission. Title to copyright in this document will at all times remain with copyright holders. Permission is given to use the trademarked string "W3C" within claims of performance concerning W3C Specifications or features described therein, and there only, if the test suite so authorizes.
-
-THIS WORK IS PROVIDED BY W3C, MIT, ERCIM, KEIO, BEIHANG, THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL W3C, MIT, ERCIM, KEIO, BEIHANG, THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# W3C 3-clause BSD License
+Copyright 2019 web-platform-tests contributors
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-* Redistributions of works must retain the original copyright notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the original copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-* Neither the name of the W3C nor the names of its contributors may be used to endorse or promote products derived from this work without specific prior written permission.
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md
index 51450f918b..760ad95b0c 100644
--- a/test/fixtures/wpt/README.md
+++ b/test/fixtures/wpt/README.md
@@ -13,7 +13,7 @@ Last update:
- console: https://github.com/web-platform-tests/wpt/tree/9786a4b131/console
- encoding: https://github.com/web-platform-tests/wpt/tree/a093a659ed/encoding
- url: https://github.com/web-platform-tests/wpt/tree/75b0f336c5/url
-- resources: https://github.com/web-platform-tests/wpt/tree/679a364421/resources
+- resources: https://github.com/web-platform-tests/wpt/tree/e1fddfbf80/resources
- interfaces: https://github.com/web-platform-tests/wpt/tree/712c9f275e/interfaces
- html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/0c3bed38df/html/webappapis/microtask-queuing
- html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/ddfe9c089b/html/webappapis/timers
diff --git a/test/fixtures/wpt/resources/idlharness.js b/test/fixtures/wpt/resources/idlharness.js
index f1a39ae9f2..c7a040996b 100644
--- a/test/fixtures/wpt/resources/idlharness.js
+++ b/test/fixtures/wpt/resources/idlharness.js
@@ -298,7 +298,9 @@ IdlArray.prototype.add_dependency_idls = function(raw_idls, options)
}.bind(this));
deps.forEach(function(name) {
- new_options.only.push(name);
+ if (!new_options.only.includes(name)) {
+ new_options.only.push(name);
+ }
const follow_up = new Set();
for (const dep_type of ["inheritance", "implements", "includes"]) {
@@ -306,13 +308,19 @@ IdlArray.prototype.add_dependency_idls = function(raw_idls, options)
const inheriting = parsed[dep_type];
const inheritor = parsed.name || parsed.target;
const deps = [inheriting];
- // For A includes B, we can ignore A unless B is being tested.
+ // For A includes B, we can ignore A, unless B (or some of its
+ // members) is being tested.
if (dep_type !== "includes"
- || (inheriting in this.members && !this.members[inheriting].untested)) {
+ || inheriting in this.members && !this.members[inheriting].untested
+ || this.partials.some(function(p) {
+ return p.name === inheriting;
+ })) {
deps.push(inheritor);
}
for (const dep of deps) {
- new_options.only.push(dep);
+ if (!new_options.only.includes(dep)) {
+ new_options.only.push(dep);
+ }
all_deps.add(dep);
follow_up.add(dep);
}
@@ -718,9 +726,6 @@ function exposed_in(globals) {
self instanceof ServiceWorkerGlobalScope) {
return globals.has("ServiceWorker");
}
- if ('NodeScope' in self) {
- return true;
- }
throw new IdlHarnessError("Unexpected global object");
}
@@ -1669,7 +1674,122 @@ IdlInterface.prototype.test_self = function()
}.bind(this), this.name + " interface: legacy window alias");
}
- // TODO: Test named constructors if I find any interfaces that have them.
+
+ if (this.has_extended_attribute("NamedConstructor")) {
+ var constructors = this.extAttrs
+ .filter(function(attr) { return attr.name == "NamedConstructor"; });
+ if (constructors.length !== 1) {
+ throw new IdlHarnessError("Internal error: missing support for multiple NamedConstructor extended attributes");
+ }
+ var constructor = constructors[0];
+ var min_length = minOverloadLength([constructor]);
+
+ subsetTestByKey(this.name, test, function()
+ {
+ // This function tests WebIDL as of 2019-01-14.
+
+ // "for every [NamedConstructor] extended attribute on an exposed
+ // interface, a corresponding property must exist on the ECMAScript
+ // global object. The name of the property is the
+ // [NamedConstructor]'s identifier, and its value is an object
+ // called a named constructor, ... . The property has the attributes
+ // { [[Writable]]: true, [[Enumerable]]: false,
+ // [[Configurable]]: true }."
+ var name = constructor.rhs.value;
+ assert_own_property(self, name);
+ var desc = Object.getOwnPropertyDescriptor(self, name);
+ assert_equals(desc.value, self[name], "wrong value in " + name + " property descriptor");
+ assert_true(desc.writable, name + " should be writable");
+ assert_false(desc.enumerable, name + " should not be enumerable");
+ assert_true(desc.configurable, name + " should be configurable");
+ assert_false("get" in desc, name + " should not have a getter");
+ assert_false("set" in desc, name + " should not have a setter");
+ }.bind(this), this.name + " interface: named constructor");
+
+ subsetTestByKey(this.name, test, function()
+ {
+ // This function tests WebIDL as of 2019-01-14.
+
+ // "2. Let F be ! CreateBuiltinFunction(realm, steps,
+ // realm.[[Intrinsics]].[[%FunctionPrototype%]])."
+ var name = constructor.rhs.value;
+ var value = self[name];
+ assert_equals(typeof value, "function", "type of value in " + name + " property descriptor");
+ assert_not_equals(value, this.get_interface_object(), "wrong value in " + name + " property descriptor");
+ assert_equals(Object.getPrototypeOf(value), Function.prototype, "wrong value for " + name + "'s prototype");
+ }.bind(this), this.name + " interface: named constructor object");
+
+ subsetTestByKey(this.name, test, function()
+ {
+ // This function tests WebIDL as of 2019-01-14.
+
+ // "7. Let proto be the interface prototype object of interface I
+ // in realm.
+ // "8. Perform ! DefinePropertyOrThrow(F, "prototype",
+ // PropertyDescriptor{
+ // [[Value]]: proto, [[Writable]]: false,
+ // [[Enumerable]]: false, [[Configurable]]: false
+ // })."
+ var name = constructor.rhs.value;
+ var expected = this.get_interface_object().prototype;
+ var desc = Object.getOwnPropertyDescriptor(self[name], "prototype");
+ assert_equals(desc.value, expected, "wrong value for " + name + ".prototype");
+ assert_false(desc.writable, "prototype should not be writable");
+ assert_false(desc.enumerable, "prototype should not be enumerable");
+ assert_false(desc.configurable, "prototype should not be configurable");
+ assert_false("get" in desc, "prototype should not have a getter");
+ assert_false("set" in desc, "prototype should not have a setter");
+ }.bind(this), this.name + " interface: named constructor prototype property");
+
+ subsetTestByKey(this.name, test, function()
+ {
+ // This function tests WebIDL as of 2019-01-14.
+
+ // "3. Perform ! SetFunctionName(F, id)."
+ var name = constructor.rhs.value;
+ var desc = Object.getOwnPropertyDescriptor(self[name], "name");
+ assert_equals(desc.value, name, "wrong value for " + name + ".name");
+ assert_false(desc.writable, "name should not be writable");
+ assert_false(desc.enumerable, "name should not be enumerable");
+ assert_true(desc.configurable, "name should be configurable");
+ assert_false("get" in desc, "name should not have a getter");
+ assert_false("set" in desc, "name should not have a setter");
+ }.bind(this), this.name + " interface: named constructor name");
+
+ subsetTestByKey(this.name, test, function()
+ {
+ // This function tests WebIDL as of 2019-01-14.
+
+ // "4. Initialize S to the effective overload set for constructors
+ // with identifier id on interface I and with argument count 0.
+ // "5. Let length be the length of the shortest argument list of
+ // the entries in S.
+ // "6. Perform ! SetFunctionLength(F, length)."
+ var name = constructor.rhs.value;
+ var desc = Object.getOwnPropertyDescriptor(self[name], "length");
+ assert_equals(desc.value, min_length, "wrong value for " + name + ".length");
+ assert_false(desc.writable, "length should not be writable");
+ assert_false(desc.enumerable, "length should not be enumerable");
+ assert_true(desc.configurable, "length should be configurable");
+ assert_false("get" in desc, "length should not have a getter");
+ assert_false("set" in desc, "length should not have a setter");
+ }.bind(this), this.name + " interface: named constructor length");
+
+ subsetTestByKey(this.name, test, function()
+ {
+ // This function tests WebIDL as of 2019-01-14.
+
+ // "1. Let steps be the following steps:
+ // " 1. If NewTarget is undefined, then throw a TypeError."
+ var name = constructor.rhs.value;
+ var args = constructor.arguments.map(function(arg) {
+ return create_suitable_object(arg.idlType);
+ });
+ assert_throws(new TypeError(), function() {
+ self[name](...args);
+ }.bind(this));
+ }.bind(this), this.name + " interface: named constructor without 'new'");
+ }
subsetTestByKey(this.name, test, function()
{
@@ -2304,22 +2424,7 @@ IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject
}
}
-IdlInterface.prototype.add_iterable_members = function(member)
-{
- this.members.push(new IdlInterfaceMember(
- { type: "operation", name: "entries", idlType: "iterator", arguments: []}));
- this.members.push(new IdlInterfaceMember(
- { type: "operation", name: "keys", idlType: "iterator", arguments: []}));
- this.members.push(new IdlInterfaceMember(
- { type: "operation", name: "values", idlType: "iterator", arguments: []}));
- this.members.push(new IdlInterfaceMember(
- { type: "operation", name: "forEach", idlType: "void",
- arguments:
- [{ name: "callback", idlType: {idlType: "function"}},
- { name: "thisValue", idlType: {idlType: "any"}, optional: true}]}));
-};
-
-IdlInterface.prototype.test_to_json_operation = function(memberHolderObject, member) {
+IdlInterface.prototype.test_to_json_operation = function(desc, memberHolderObject, member) {
var instanceName = memberHolderObject && memberHolderObject.constructor.name
|| member.name + " object";
if (member.has_extended_attribute("Default")) {
@@ -2335,38 +2440,40 @@ IdlInterface.prototype.test_to_json_operation = function(memberHolderObject, mem
this.array.assert_type_is(json[k], type);
delete json[k];
}, this);
- }.bind(this), "Test default toJSON operation of " + instanceName);
+ }.bind(this), this.name + " interface: default toJSON operation on " + desc);
} else {
subsetTestByKey(this.name, test, function() {
assert_true(this.array.is_json_type(member.idlType), JSON.stringify(member.idlType) + " is not an appropriate return value for the toJSON operation of " + instanceName);
this.array.assert_type_is(memberHolderObject.toJSON(), member.idlType);
- }.bind(this), "Test toJSON operation of " + instanceName);
+ }.bind(this), this.name + " interface: toJSON operation on " + desc);
}
};
IdlInterface.prototype.test_member_iterable = function(member)
{
- var isPairIterator = member.idlType.length === 2;
subsetTestByKey(this.name, test, function()
{
- var descriptor = Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, Symbol.iterator);
- assert_true(descriptor.writable, "property should be writable");
- assert_true(descriptor.configurable, "property should be configurable");
- assert_false(descriptor.enumerable, "property should not be enumerable");
- assert_equals(this.get_interface_object().prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name");
- }.bind(this), "Testing Symbol.iterator property of iterable interface " + this.name);
-
- if (isPairIterator) {
- subsetTestByKey(this.name, test, function() {
- assert_equals(this.get_interface_object().prototype[Symbol.iterator], this.get_interface_object().prototype["entries"], "entries method is not the same as @@iterator");
- }.bind(this), "Testing pair iterable interface " + this.name);
- } else {
- subsetTestByKey(this.name, test, function() {
- ["entries", "keys", "values", "forEach", Symbol.Iterator].forEach(function(property) {
- assert_equals(this.get_interface_object().prototype[property], Array.prototype[property], property + " function is not the same as Array one");
+ var isPairIterator = member.idlType.length === 2;
+ var proto = this.get_interface_object().prototype;
+ var descriptor = Object.getOwnPropertyDescriptor(proto, Symbol.iterator);
+
+ assert_true(descriptor.writable, "@@iterator property should be writable");
+ assert_true(descriptor.configurable, "@@iterator property should be configurable");
+ assert_false(descriptor.enumerable, "@@iterator property should not be enumerable");
+ assert_equals(typeof descriptor.value, "function", "@@iterator property should be a function");
+ assert_equals(descriptor.value.length, 0, "@@iterator function object length should be 0");
+ assert_equals(descriptor.value.name, isPairIterator ? "entries" : "values", "@@iterator function object should have the right name");
+
+ if (isPairIterator) {
+ assert_equals(proto["entries"], proto[Symbol.iterator], "entries method should be the same as @@iterator method");
+ } else {
+ assert_equals(proto[Symbol.iterator], Array.prototype[Symbol.iterator], "@@iterator method should be the same as Array prototype's");
+ ["entries", "keys", "values", "forEach", Symbol.iterator].forEach(function(property) {
+ var propertyName = property === Symbol.iterator ? "@@iterator" : property;
+ assert_equals(proto[property], Array.prototype[property], propertyName + " method should be the same as Array prototype's");
}.bind(this));
- }.bind(this), "Testing value iterable interface " + this.name);
- }
+ }
+ }.bind(this), this.name + " interface: iterable<" + member.idlType.map(function(t) { return t.idlType; }).join(", ") + ">");
};
IdlInterface.prototype.test_member_stringifier = function(member)
@@ -2435,19 +2542,6 @@ IdlInterface.prototype.test_members = function()
for (var i = 0; i < this.members.length; i++)
{
var member = this.members[i];
- switch (member.type) {
- case "iterable":
- this.add_iterable_members(member);
- break;
- // TODO: add setlike and maplike handling.
- default:
- break;
- }
- }
-
- for (var i = 0; i < this.members.length; i++)
- {
- var member = this.members[i];
if (member.untested) {
continue;
}
@@ -2743,7 +2837,7 @@ IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect
}
if (member.is_to_json_regular_operation()) {
- this.test_to_json_operation(obj, member);
+ this.test_to_json_operation(desc, obj, member);
}
}
};
diff --git a/test/fixtures/wpt/resources/testdriver-actions.js b/test/fixtures/wpt/resources/testdriver-actions.js
index 46c68858e4..43d8b1df00 100644
--- a/test/fixtures/wpt/resources/testdriver-actions.js
+++ b/test/fixtures/wpt/resources/testdriver-actions.js
@@ -7,7 +7,7 @@
function Actions() {
this.sourceTypes = new Map([["key", KeySource],
["pointer", PointerSource],
- ["general", GeneralSource]]);
+ ["none", GeneralSource]]);
this.sources = new Map();
this.sourceOrder = [];
for (let sourceType of this.sourceTypes.keys()) {
@@ -17,11 +17,19 @@
for (let sourceType of this.sourceTypes.keys()) {
this.currentSources.set(sourceType, null);
}
- this.createSource("general");
+ this.createSource("none");
this.tickIdx = 0;
}
Actions.prototype = {
+ ButtonType: {
+ LEFT: 0,
+ MIDDLE: 1,
+ RIGHT: 2,
+ BACK: 3,
+ FORWARD: 4,
+ },
+
/**
* Generate the action sequence suitable for passing to
* test_driver.action_sequence
@@ -62,7 +70,7 @@
* If no name is passed, a new source with the given type is
* created.
*
- * @param {String} type - Source type ('general', 'key', or 'pointer')
+ * @param {String} type - Source type ('none', 'key', or 'pointer')
* @param {String?} name - Name of the source
* @returns {Source} Source object for that source.
*/
@@ -98,7 +106,7 @@
* @returns {Actions}
*/
addKeyboard: function(name, set=true) {
- this.createSource("key", name, true);
+ this.createSource("key", name);
if (set) {
this.setKeyboard(name);
}
@@ -125,7 +133,7 @@
* @returns {Actions}
*/
addPointer: function(name, pointerType="mouse", set=true) {
- this.createSource("pointer", name, true, {pointerType: pointerType});
+ this.createSource("pointer", name, {pointerType: pointerType});
if (set) {
this.setPointer(name);
}
@@ -187,7 +195,7 @@
* @returns {Actions}
*/
pause: function(duration) {
- this.getSource("general").addPause(this, duration);
+ this.getSource("none").addPause(this, duration);
return this;
},
@@ -225,7 +233,7 @@
* pointer source
* @returns {Actions}
*/
- pointerDown: function({button=0, sourceName=null}={}) {
+ pointerDown: function({button=this.ButtonType.LEFT, sourceName=null}={}) {
let source = this.getSource("pointer", sourceName);
source.pointerDown(this, button);
return this;
@@ -239,7 +247,7 @@
* source
* @returns {Actions}
*/
- pointerUp: function({button=0, sourceName=null}={}) {
+ pointerUp: function({button=this.ButtonType.LEFT, sourceName=null}={}) {
let source = this.getSource("pointer", sourceName);
source.pointerUp(this, button);
return this;
diff --git a/test/fixtures/wpt/resources/testdriver.js b/test/fixtures/wpt/resources/testdriver.js
index e0741e8d61..031be1b7e5 100644
--- a/test/fixtures/wpt/resources/testdriver.js
+++ b/test/fixtures/wpt/resources/testdriver.js
@@ -192,32 +192,89 @@
* @returns {Promise} fufiled after the actions are performed, or rejected in
* the cases the WebDriver command errors
*/
- action_sequence(actions) {
+ action_sequence: function(actions) {
return window.test_driver_internal.action_sequence(actions);
+ },
+
+ /**
+ * Generates a test report on the current page
+ *
+ * The generate_test_report function generates a report (to be observed
+ * by ReportingObserver) for testing purposes, as described in
+ * {@link https://w3c.github.io/reporting/#generate-test-report-command}
+ *
+ * @returns {Promise} fulfilled after the report is generated, or
+ * rejected if the report generation fails
+ */
+ generate_test_report: function(message) {
+ return window.test_driver_internal.generate_test_report(message);
}
};
window.test_driver_internal = {
/**
- * Triggers a user-initiated click
+ * This flag should be set to `true` by any code which implements the
+ * internal methods defined below for automation purposes. Doing so
+ * allows the library to signal failure immediately when an automated
+ * implementation of one of the methods is not available.
+ */
+ in_automation: false,
+
+ /**
+ * Waits for a user-initiated click
*
* @param {Element} element - element to be clicked
* @param {{x: number, y: number} coords - viewport coordinates to click at
- * @returns {Promise} fulfilled after click occurs or rejected if click fails
+ * @returns {Promise} fulfilled after click occurs
*/
click: function(element, coords) {
- return Promise.reject(new Error("unimplemented"));
+ if (this.in_automation) {
+ return Promise.reject(new Error('Not implemented'));
+ }
+
+ return new Promise(function(resolve, reject) {
+ element.addEventListener("click", resolve);
+ });
},
/**
- * Triggers a user-initiated click
+ * Waits for an element to receive a series of key presses
*
- * @param {Element} element - element to be clicked
- * @param {String} keys - keys to send to the element
- * @returns {Promise} fulfilled after keys are sent or rejected if click fails
+ * @param {Element} element - element which should receve key presses
+ * @param {String} keys - keys to expect
+ * @returns {Promise} fulfilled after keys are received or rejected if
+ * an incorrect key sequence is received
*/
send_keys: function(element, keys) {
- return Promise.reject(new Error("unimplemented"));
+ if (this.in_automation) {
+ return Promise.reject(new Error('Not implemented'));
+ }
+
+ return new Promise(function(resolve, reject) {
+ var seen = "";
+
+ function remove() {
+ element.removeEventListener("keydown", onKeyDown);
+ }
+
+ function onKeyDown(event) {
+ if (event.key.length > 1) {
+ return;
+ }
+
+ seen += event.key;
+
+ if (keys.indexOf(seen) !== 0) {
+ reject(new Error("Unexpected key sequence: " + seen));
+ remove();
+ } else if (seen === keys) {
+ resolve();
+ remove();
+ }
+ }
+
+ element.addEventListener("keydown", onKeyDown);
+ });
},
/**
@@ -238,6 +295,17 @@
*/
action_sequence: function(actions) {
return Promise.reject(new Error("unimplemented"));
+ },
+
+ /**
+ * Generates a test report on the current page
+ *
+ * @param {String} message - the message to be contained in the report
+ * @returns {Promise} fulfilled after the report is generated, or
+ * rejected if the report generation fails
+ */
+ generate_test_report: function(message) {
+ return Promise.reject(new Error("unimplemented"));
}
};
})();
diff --git a/test/fixtures/wpt/resources/testharness.js b/test/fixtures/wpt/resources/testharness.js
index 18a6f70bea..bffdf022b3 100644
--- a/test/fixtures/wpt/resources/testharness.js
+++ b/test/fixtures/wpt/resources/testharness.js
@@ -513,7 +513,7 @@ policies and contribution forms [3].
return new DedicatedWorkerTestEnvironment();
}
- if (!('self' in global_scope)) {
+ if (!('location' in global_scope)) {
return new ShellTestEnvironment();
}
@@ -635,7 +635,7 @@ policies and contribution forms [3].
* which can make it a lot easier to test a very specific series of events,
* including ensuring that unexpected events are not fired at any point.
*/
- function EventWatcher(test, watchedNode, eventTypes)
+ function EventWatcher(test, watchedNode, eventTypes, timeoutPromise)
{
if (typeof eventTypes == 'string') {
eventTypes = [eventTypes];
@@ -712,6 +712,27 @@ policies and contribution forms [3].
recordedEvents = [];
}
return new Promise(function(resolve, reject) {
+ var timeout = test.step_func(function() {
+ // If the timeout fires after the events have been received
+ // or during a subsequent call to wait_for, ignore it.
+ if (!waitingFor || waitingFor.resolve !== resolve)
+ return;
+
+ // This should always fail, otherwise we should have
+ // resolved the promise.
+ assert_true(waitingFor.types.length == 0,
+ 'Timed out waiting for ' + waitingFor.types.join(', '));
+ var result = recordedEvents;
+ recordedEvents = null;
+ var resolveFunc = waitingFor.resolve;
+ waitingFor = null;
+ resolveFunc(result);
+ });
+
+ if (timeoutPromise) {
+ timeoutPromise().then(timeout);
+ }
+
waitingFor = {
types: types,
resolve: resolve,
@@ -1111,7 +1132,7 @@ policies and contribution forms [3].
assert(Math.abs(actual[i] - expected[i]) <= epsilon,
"assert_array_approx_equals", description,
"property ${i}, expected ${expected} +/- ${epsilon}, expected ${expected} but got ${actual}",
- {i:i, expected:expected[i], actual:actual[i]});
+ {i:i, expected:expected[i], actual:actual[i], epsilon:epsilon});
}
}
expose(assert_array_approx_equals, "assert_array_approx_equals");
@@ -1478,7 +1499,7 @@ policies and contribution forms [3].
}
this.name = name;
- this.phase = tests.is_aborted ?
+ this.phase = (tests.is_aborted || tests.phase === tests.phases.COMPLETE) ?
this.phases.COMPLETE : this.phases.INITIAL;
this.status = this.NOTRUN;
@@ -1486,11 +1507,9 @@ policies and contribution forms [3].
this.index = null;
this.properties = properties;
- var timeout = properties.timeout ? properties.timeout : settings.test_timeout;
- if (timeout !== null) {
- this.timeout_length = timeout * tests.timeout_multiplier;
- } else {
- this.timeout_length = null;
+ this.timeout_length = settings.test_timeout;
+ if (this.timeout_length !== null) {
+ this.timeout_length *= tests.timeout_multiplier;
}
this.message = null;
@@ -1503,6 +1522,13 @@ policies and contribution forms [3].
this._user_defined_cleanup_count = 0;
this._done_callbacks = [];
+ // Tests declared following harness completion are likely an indication
+ // of a programming error, but they cannot be reported
+ // deterministically.
+ if (tests.phase === tests.phases.COMPLETE) {
+ return;
+ }
+
tests.push(this);
}
@@ -1904,7 +1930,9 @@ policies and contribution forms [3].
*/
function RemoteContext(remote, message_target, message_filter) {
this.running = true;
+ this.started = false;
this.tests = new Array();
+ this.early_exception = null;
var this_obj = this;
// If remote context is cross origin assigning to onerror is not
@@ -1943,6 +1971,21 @@ policies and contribution forms [3].
}
RemoteContext.prototype.remote_error = function(error) {
+ if (error.preventDefault) {
+ error.preventDefault();
+ }
+
+ // Defer interpretation of errors until the testing protocol has
+ // started and the remote test's `allow_uncaught_exception` property
+ // is available.
+ if (!this.started) {
+ this.early_exception = error;
+ } else if (!this.allow_uncaught_exception) {
+ this.report_uncaught(error);
+ }
+ };
+
+ RemoteContext.prototype.report_uncaught = function(error) {
var message = error.message || String(error);
var filename = (error.filename ? " " + error.filename: "");
// FIXME: Display remote error states separately from main document
@@ -1950,9 +1993,14 @@ policies and contribution forms [3].
tests.set_status(tests.status.ERROR,
"Error in remote" + filename + ": " + message,
error.stack);
+ };
- if (error.preventDefault) {
- error.preventDefault();
+ RemoteContext.prototype.start = function(data) {
+ this.started = true;
+ this.allow_uncaught_exception = data.properties.allow_uncaught_exception;
+
+ if (this.early_exception && !this.allow_uncaught_exception) {
+ this.report_uncaught(this.early_exception);
}
};
@@ -2002,6 +2050,7 @@ policies and contribution forms [3].
};
RemoteContext.prototype.message_handlers = {
+ start: RemoteContext.prototype.start,
test_state: RemoteContext.prototype.test_state,
result: RemoteContext.prototype.test_done,
complete: RemoteContext.prototype.remote_done
@@ -2114,6 +2163,9 @@ policies and contribution forms [3].
}
} else if (p == "timeout_multiplier") {
this.timeout_multiplier = value;
+ if (this.timeout_length) {
+ this.timeout_length *= this.timeout_multiplier;
+ }
}
}
}
@@ -2338,6 +2390,42 @@ policies and contribution forms [3].
return duplicates;
};
+ function code_unit_str(char) {
+ return 'U+' + char.charCodeAt(0).toString(16);
+ }
+
+ function sanitize_unpaired_surrogates(str) {
+ return str.replace(/([\ud800-\udbff])(?![\udc00-\udfff])/g,
+ function(_, unpaired)
+ {
+ return code_unit_str(unpaired);
+ })
+ // This replacement is intentionally implemented without an
+ // ES2018 negative lookbehind assertion to support runtimes
+ // which do not yet implement that language feature.
+ .replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g,
+ function(_, previous, unpaired) {
+ if (/[\udc00-\udfff]/.test(previous)) {
+ previous = code_unit_str(previous);
+ }
+
+ return previous + code_unit_str(unpaired);
+ });
+ }
+
+ function sanitize_all_unpaired_surrogates(tests) {
+ forEach (tests,
+ function (test)
+ {
+ var sanitized = sanitize_unpaired_surrogates(test.name);
+
+ if (test.name !== sanitized) {
+ test.name = sanitized;
+ delete test._structured_clone;
+ }
+ });
+ }
+
Tests.prototype.notify_complete = function() {
var this_obj = this;
var duplicates;
@@ -2345,6 +2433,11 @@ policies and contribution forms [3].
if (this.status.status === null) {
duplicates = this.find_duplicates();
+ // Some transports adhere to UTF-8's restriction on unpaired
+ // surrogates. Sanitize the titles so that the results can be
+ // consistently sent via all transports.
+ sanitize_all_unpaired_surrogates(this.tests);
+
// Test names are presumed to be unique within test files--this
// allows consumers to use them for identification purposes.
// Duplicated names violate this expectation and should therefore
@@ -2536,6 +2629,9 @@ policies and contribution forms [3].
Output.prototype.resolve_log = function() {
var output_document;
+ if (this.output_node) {
+ return;
+ }
if (typeof this.output_document === "function") {
output_document = this.output_document.apply(undefined);
} else {
@@ -2546,7 +2642,7 @@ policies and contribution forms [3].
}
var node = output_document.getElementById("log");
if (!node) {
- if (!document.readyState == "loading") {
+ if (output_document.readyState === "loading") {
return;
}
node = output_document.createElementNS("http://www.w3.org/1999/xhtml", "div");
@@ -2583,11 +2679,11 @@ policies and contribution forms [3].
if (this.phase < this.STARTED) {
this.init();
}
- if (!this.enabled) {
+ if (!this.enabled || this.phase === this.COMPLETE) {
return;
}
+ this.resolve_log();
if (this.phase < this.HAVE_RESULTS) {
- this.resolve_log();
this.phase = this.HAVE_RESULTS;
}
var done_count = tests.tests.length - tests.num_pending;
diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json
index 7bd65d9023..d58a96e01c 100644
--- a/test/fixtures/wpt/versions.json
+++ b/test/fixtures/wpt/versions.json
@@ -12,7 +12,7 @@
"path": "url"
},
"resources": {
- "commit": "679a364421ce3704289df21e1ff985c14b360981",
+ "commit": "e1fddfbf801e7cce9cac5645e992194e4059ef56",
"path": "resources"
},
"interfaces": {