mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
test: update wpt url and resource
Refs: https://github.com/web-platform-tests/wpt/pull/26317 PR-URL: https://github.com/nodejs/node/pull/36032 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
1 parent
73ea670152
commit
d6d4721f3b
12 files changed
+437
-222
No files matched your search
Vendored
+3
-3
@@ -12,9 +12,9 @@ Last update:
|
||||
|
||||
- console: https://github.com/web-platform-tests/wpt/tree/3b1f72e99a/console
|
||||
- encoding: https://github.com/web-platform-tests/wpt/tree/1821fb5f77/encoding
|
||||
- url: https://github.com/web-platform-tests/wpt/tree/54c6d64be0/url
|
||||
- resources: https://github.com/web-platform-tests/wpt/tree/1d14e821b9/resources
|
||||
- interfaces: https://github.com/web-platform-tests/wpt/tree/15e47f779c/interfaces
|
||||
- url: https://github.com/web-platform-tests/wpt/tree/09d8830be1/url
|
||||
- resources: https://github.com/web-platform-tests/wpt/tree/001e50de41/resources
|
||||
- interfaces: https://github.com/web-platform-tests/wpt/tree/8719553b2d/interfaces
|
||||
- html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/2c5c3c4c27/html/webappapis/microtask-queuing
|
||||
- html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/264f12bc7b/html/webappapis/timers
|
||||
- hr-time: https://github.com/web-platform-tests/wpt/tree/a5d1774ecf/hr-time
|
||||
|
||||
+21
-5
@@ -436,7 +436,6 @@ interface HTMLIFrameElement : HTMLElement {
|
||||
[SameObject, PutForwards=value] readonly attribute DOMTokenList sandbox;
|
||||
[CEReactions] attribute DOMString allow;
|
||||
[CEReactions] attribute boolean allowFullscreen;
|
||||
[CEReactions] attribute boolean allowPaymentRequest;
|
||||
[CEReactions] attribute DOMString width;
|
||||
[CEReactions] attribute DOMString height;
|
||||
[CEReactions] attribute DOMString referrerPolicy;
|
||||
@@ -1564,16 +1563,18 @@ dictionary ElementDefinitionOptions {
|
||||
|
||||
[Exposed=Window]
|
||||
interface ElementInternals {
|
||||
// Form-associated custom elements
|
||||
// Shadow root access
|
||||
readonly attribute ShadowRoot? shadowRoot;
|
||||
|
||||
// Form-associated custom elements
|
||||
undefined setFormValue((File or USVString or FormData)? value,
|
||||
optional (File or USVString or FormData)? state);
|
||||
optional (File or USVString or FormData)? state);
|
||||
|
||||
readonly attribute HTMLFormElement? form;
|
||||
|
||||
undefined setValidity(optional ValidityStateFlags flags = {},
|
||||
optional DOMString message,
|
||||
optional HTMLElement anchor);
|
||||
optional DOMString message,
|
||||
optional HTMLElement anchor);
|
||||
readonly attribute boolean willValidate;
|
||||
readonly attribute ValidityState validity;
|
||||
readonly attribute DOMString validationMessage;
|
||||
@@ -1583,6 +1584,9 @@ interface ElementInternals {
|
||||
readonly attribute NodeList labels;
|
||||
};
|
||||
|
||||
// Accessibility semantics
|
||||
ElementInternals includes ARIAMixin;
|
||||
|
||||
dictionary ValidityStateFlags {
|
||||
boolean valueMissing = false;
|
||||
boolean typeMismatch = false;
|
||||
@@ -2353,6 +2357,18 @@ interface WorkerLocation {
|
||||
readonly attribute USVString hash;
|
||||
};
|
||||
|
||||
[Exposed=Worklet, SecureContext]
|
||||
interface WorkletGlobalScope {};
|
||||
|
||||
[Exposed=Window, SecureContext]
|
||||
interface Worklet {
|
||||
[NewObject] Promise<undefined> addModule(USVString moduleURL, optional WorkletOptions options = {});
|
||||
};
|
||||
|
||||
dictionary WorkletOptions {
|
||||
RequestCredentials credentials = "same-origin";
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface Storage {
|
||||
readonly attribute unsigned long length;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Whether the browser is Chromium-based with MojoJS enabled */
|
||||
export const isChromiumBased = 'MojoInterfaceInterceptor' in self;
|
||||
|
||||
/* Whether the browser is WebKit-based with internal test-only API enabled */
|
||||
export const isWebKitBased = !isChromiumBased && 'internals' in self;
|
||||
@@ -0,0 +1,2 @@
|
||||
Content-Type: text/javascript; charset=utf-8
|
||||
Cache-Control: max-age=3600
|
||||
+105
-4
@@ -9,6 +9,7 @@
|
||||
function Actions(defaultTickDuration=16) {
|
||||
this.sourceTypes = new Map([["key", KeySource],
|
||||
["pointer", PointerSource],
|
||||
["wheel", WheelSource],
|
||||
["none", GeneralSource]]);
|
||||
this.sources = new Map();
|
||||
this.sourceOrder = [];
|
||||
@@ -22,6 +23,7 @@
|
||||
this.createSource("none");
|
||||
this.tickIdx = 0;
|
||||
this.defaultTickDuration = defaultTickDuration;
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
Actions.prototype = {
|
||||
@@ -65,7 +67,17 @@
|
||||
} catch(e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
return test_driver.action_sequence(actions);
|
||||
return test_driver.action_sequence(actions, this.context);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the context for the actions
|
||||
*
|
||||
* @param {WindowProxy} context - Context in which to run the action sequence
|
||||
*/
|
||||
setContext: function(context) {
|
||||
this.context = context;
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -73,7 +85,7 @@
|
||||
* If no name is passed, a new source with the given type is
|
||||
* created.
|
||||
*
|
||||
* @param {String} type - Source type ('none', 'key', or 'pointer')
|
||||
* @param {String} type - Source type ('none', 'key', 'pointer', or 'wheel')
|
||||
* @param {String?} name - Name of the source
|
||||
* @returns {Source} Source object for that source.
|
||||
*/
|
||||
@@ -154,6 +166,32 @@
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a new wheel input source with the given name
|
||||
*
|
||||
* @param {String} type - Name of the wheel source
|
||||
* @param {Bool} set - Set source as the default wheel source
|
||||
* @returns {Actions}
|
||||
*/
|
||||
addWheel: function(name, set=true) {
|
||||
this.createSource("wheel", name);
|
||||
if (set) {
|
||||
this.setWheel(name);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the current default wheel source
|
||||
*
|
||||
* @param {String} name - Name of the wheel source
|
||||
* @returns {Actions}
|
||||
*/
|
||||
setWheel: function(name) {
|
||||
this.setSource("wheel", name);
|
||||
return this;
|
||||
},
|
||||
|
||||
createSource: function(type, name, parameters={}) {
|
||||
if (!this.sources.has(type)) {
|
||||
throw new Error(`${type} is not a valid action type`);
|
||||
@@ -196,8 +234,9 @@
|
||||
*
|
||||
* @param {Number?} duration - Minimum length of the tick in ms.
|
||||
* @param {String} sourceType - source type
|
||||
* @param {String?} sourceName - Named key or pointer source to use or null for the default
|
||||
* key or pointer source
|
||||
* @param {String?} sourceName - Named key, pointer or wheel source to use
|
||||
* or null for the default key, pointer or
|
||||
* wheel source
|
||||
* @returns {Actions}
|
||||
*/
|
||||
pause: function(duration=0, sourceType="none", {sourceName=null}={}) {
|
||||
@@ -280,6 +319,27 @@
|
||||
source.pointerMove(this, x, y, duration, origin);
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a scroll event for the current default wheel source
|
||||
*
|
||||
* @param {Number} x - mouse cursor x coordinate
|
||||
* @param {Number} y - mouse cursor y coordinate
|
||||
* @param {Number} deltaX - scroll delta value along the x-axis in pixels
|
||||
* @param {Number} deltaY - scroll delta value along the y-axis in pixels
|
||||
* @param {String|Element} origin - Origin of the coordinate system.
|
||||
* Either "viewport" or an Element
|
||||
* @param {Number?} duration - Time in ms for the scroll
|
||||
* @param {String?} sourceName - Named wheel source to use or null for the
|
||||
* default wheel source
|
||||
* @returns {Actions}
|
||||
*/
|
||||
scroll: function(x, y, deltaX, deltaY,
|
||||
{origin="viewport", duration, sourceName=null}={}) {
|
||||
let source = this.getSource("wheel", sourceName);
|
||||
source.scroll(this, x, y, deltaX, deltaY, duration, origin);
|
||||
return this;
|
||||
},
|
||||
};
|
||||
|
||||
function GeneralSource() {
|
||||
@@ -417,5 +477,46 @@
|
||||
},
|
||||
};
|
||||
|
||||
function WheelSource() {
|
||||
this.actions = new Map();
|
||||
}
|
||||
|
||||
WheelSource.prototype = {
|
||||
serialize: function(tickCount) {
|
||||
if (!this.actions.size) {
|
||||
return undefined;
|
||||
}
|
||||
let actions = [];
|
||||
let data = {"type": "wheel", "actions": actions};
|
||||
for (let i=0; i<tickCount; i++) {
|
||||
if (this.actions.has(i)) {
|
||||
actions.push(this.actions.get(i));
|
||||
} else {
|
||||
actions.push({"type": "pause"});
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
scroll: function(actions, x, y, deltaX, deltaY, duration, origin) {
|
||||
let tick = actions.tickIdx;
|
||||
if (this.actions.has(tick)) {
|
||||
tick = actions.addTick().tickIdx;
|
||||
}
|
||||
this.actions.set(tick, {type: "scroll", x, y, deltaX, deltaY, origin});
|
||||
if (duration) {
|
||||
this.actions.get(tick).duration = duration;
|
||||
}
|
||||
},
|
||||
|
||||
addPause: function(actions, duration) {
|
||||
let tick = actions.tickIdx;
|
||||
if (this.actions.has(tick)) {
|
||||
tick = actions.addTick().tickIdx;
|
||||
}
|
||||
this.actions.set(tick, {type: "pause", duration: duration});
|
||||
},
|
||||
};
|
||||
|
||||
test_driver.Actions = Actions;
|
||||
})();
|
||||
+128
-193
@@ -1,6 +1,7 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
var idCounter = 0;
|
||||
let testharness_context = null;
|
||||
|
||||
function getInViewCenterPoint(rect) {
|
||||
var left = Math.max(0, rect.left);
|
||||
@@ -15,7 +16,8 @@
|
||||
}
|
||||
|
||||
function getPointerInteractablePaintTree(element) {
|
||||
if (!window.document.contains(element)) {
|
||||
let elementDocument = element.ownerDocument;
|
||||
if (!elementDocument.contains(element)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -27,10 +29,10 @@
|
||||
|
||||
var centerPoint = getInViewCenterPoint(rectangles[0]);
|
||||
|
||||
if ("elementsFromPoint" in document) {
|
||||
return document.elementsFromPoint(centerPoint[0], centerPoint[1]);
|
||||
} else if ("msElementsFromPoint" in document) {
|
||||
var rv = document.msElementsFromPoint(centerPoint[0], centerPoint[1]);
|
||||
if ("elementsFromPoint" in elementDocument) {
|
||||
return elementDocument.elementsFromPoint(centerPoint[0], centerPoint[1]);
|
||||
} else if ("msElementsFromPoint" in elementDocument) {
|
||||
var rv = elementDocument.msElementsFromPoint(centerPoint[0], centerPoint[1]);
|
||||
return Array.prototype.slice.call(rv ? rv : []);
|
||||
} else {
|
||||
throw new Error("document.elementsFromPoint unsupported");
|
||||
@@ -47,6 +49,31 @@
|
||||
* @namespace
|
||||
*/
|
||||
window.test_driver = {
|
||||
/**
|
||||
* Set the context in which testharness.js is loaded
|
||||
*
|
||||
* @param {WindowProxy} context - the window containing testharness.js
|
||||
**/
|
||||
set_test_context: function(context) {
|
||||
if (window.test_driver_internal.set_test_context) {
|
||||
window.test_driver_internal.set_test_context(context);
|
||||
}
|
||||
testharness_context = context;
|
||||
},
|
||||
|
||||
/**
|
||||
* postMessage to the context containing testharness.js
|
||||
*
|
||||
* @param {Object} msg - the data to POST
|
||||
**/
|
||||
message_test: function(msg) {
|
||||
let target = testharness_context;
|
||||
if (testharness_context === null) {
|
||||
target = window;
|
||||
}
|
||||
target.postMessage(msg, "*");
|
||||
},
|
||||
|
||||
/**
|
||||
* Trigger user interaction in order to grant additional privileges to
|
||||
* a provided function.
|
||||
@@ -56,30 +83,35 @@
|
||||
* @param {String} intent - a description of the action which much be
|
||||
* triggered by user interaction
|
||||
* @param {Function} action - code requiring escalated privileges
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled following user interaction and
|
||||
* execution of the provided `action` function;
|
||||
* rejected if interaction fails or the provided
|
||||
* function throws an error
|
||||
*/
|
||||
bless: function(intent, action) {
|
||||
var button = document.createElement("button");
|
||||
bless: function(intent, action, context=null) {
|
||||
let contextDocument = context ? context.document : document;
|
||||
var button = contextDocument.createElement("button");
|
||||
button.innerHTML = "This test requires user interaction.<br />" +
|
||||
"Please click here to allow " + intent + ".";
|
||||
button.id = "wpt-test-driver-bless-" + (idCounter += 1);
|
||||
const elem = document.body || document.documentElement;
|
||||
const elem = contextDocument.body || contextDocument.documentElement;
|
||||
elem.appendChild(button);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
button.addEventListener("click", resolve);
|
||||
let wait_click = new Promise(resolve => button.addEventListener("click", resolve));
|
||||
|
||||
test_driver.click(button).catch(reject);
|
||||
}).then(function() {
|
||||
return test_driver.click(button)
|
||||
.then(wait_click)
|
||||
.then(function() {
|
||||
button.remove();
|
||||
|
||||
if (typeof action === "function") {
|
||||
return action();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -95,14 +127,6 @@
|
||||
* the cases the WebDriver command errors
|
||||
*/
|
||||
click: function(element) {
|
||||
if (window.top !== window) {
|
||||
return Promise.reject(new Error("can only click in top-level window"));
|
||||
}
|
||||
|
||||
if (!window.document.contains(element)) {
|
||||
return Promise.reject(new Error("element in different document or shadow tree"));
|
||||
}
|
||||
|
||||
if (!inView(element)) {
|
||||
element.scrollIntoView({behavior: "instant",
|
||||
block: "end",
|
||||
@@ -135,14 +159,6 @@
|
||||
* the cases the WebDriver command errors
|
||||
*/
|
||||
send_keys: function(element, keys) {
|
||||
if (window.top !== window) {
|
||||
return Promise.reject(new Error("can only send keys in top-level window"));
|
||||
}
|
||||
|
||||
if (!window.document.contains(element)) {
|
||||
return Promise.reject(new Error("element in different document or shadow tree"));
|
||||
}
|
||||
|
||||
if (!inView(element)) {
|
||||
element.scrollIntoView({behavior: "instant",
|
||||
block: "end",
|
||||
@@ -166,34 +182,42 @@
|
||||
* https://github.com/WICG/page-lifecycle/blob/master/README.md|Lifecycle API
|
||||
* for Web Pages}
|
||||
*
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the freeze request is sent, or rejected
|
||||
* in case the WebDriver command errors
|
||||
*/
|
||||
freeze: function() {
|
||||
freeze: function(context=null) {
|
||||
return window.test_driver_internal.freeze();
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a sequence of actions
|
||||
*
|
||||
* This function sends a sequence of actions to the top level window
|
||||
* This function sends a sequence of actions
|
||||
* to perform. It is modeled after the behaviour of {@link
|
||||
* https://w3c.github.io/webdriver/#actions|WebDriver Actions Command}
|
||||
*
|
||||
* @param {Array} actions - an array of actions. The format is the same as the actions
|
||||
property of the WebDriver command {@link
|
||||
https://w3c.github.io/webdriver/#perform-actions|Perform
|
||||
Actions} command. Each element is an object representing an
|
||||
input source and each input source itself has an actions
|
||||
property detailing the behaviour of that source at each timestep
|
||||
(or tick). Authors are not expected to construct the actions
|
||||
sequence by hand, but to use the builder api provided in
|
||||
testdriver-actions.js
|
||||
* property of the WebDriver command {@link
|
||||
* https://w3c.github.io/webdriver/#perform-actions|Perform
|
||||
* Actions} command. Each element is an object representing an
|
||||
* input source and each input source itself has an actions
|
||||
* property detailing the behaviour of that source at each timestep
|
||||
* (or tick). Authors are not expected to construct the actions
|
||||
* sequence by hand, but to use the builder api provided in
|
||||
* testdriver-actions.js
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fufiled after the actions are performed, or rejected in
|
||||
* the cases the WebDriver command errors
|
||||
*/
|
||||
action_sequence: function(actions) {
|
||||
return window.test_driver_internal.action_sequence(actions);
|
||||
action_sequence: function(actions, context=null) {
|
||||
return window.test_driver_internal.action_sequence(actions, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -203,11 +227,15 @@
|
||||
* by ReportingObserver) for testing purposes, as described in
|
||||
* {@link https://w3c.github.io/reporting/#generate-test-report-command}
|
||||
*
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @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);
|
||||
generate_test_report: function(message, context=null) {
|
||||
return window.test_driver_internal.generate_test_report(message, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -221,6 +249,9 @@
|
||||
* object
|
||||
* @param {String} state - the state of the permission
|
||||
* @param {boolean} one_realm - Optional. Whether the permission applies to only one realm
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* The above params are used to create a [PermissionSetParameters]{@link
|
||||
* https://w3c.github.io/permissions/#dictdef-permissionsetparameters} object
|
||||
@@ -228,13 +259,13 @@
|
||||
* @returns {Promise} fulfilled after the permission is set, or rejected if setting the
|
||||
* permission fails
|
||||
*/
|
||||
set_permission: function(descriptor, state, one_realm) {
|
||||
set_permission: function(descriptor, state, one_realm, context=null) {
|
||||
let permission_params = {
|
||||
descriptor,
|
||||
state,
|
||||
oneRealm: one_realm,
|
||||
};
|
||||
return window.test_driver_internal.set_permission(permission_params);
|
||||
return window.test_driver_internal.set_permission(permission_params, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -247,12 +278,16 @@
|
||||
* @param {Object} config - an [Authenticator Configuration]{@link
|
||||
* https://w3c.github.io/webauthn/#authenticator-configuration}
|
||||
* object
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the authenticator is added, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors. Returns the ID of the authenticator
|
||||
*/
|
||||
add_virtual_authenticator: function(config) {
|
||||
return window.test_driver_internal.add_virtual_authenticator(config);
|
||||
add_virtual_authenticator: function(config, context=null) {
|
||||
return window.test_driver_internal.add_virtual_authenticator(config, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -264,13 +299,16 @@
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator to be
|
||||
* removed.
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the authenticator is removed, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors
|
||||
*/
|
||||
remove_virtual_authenticator: function(authenticator_id) {
|
||||
return window.test_driver_internal.remove_virtual_authenticator(authenticator_id);
|
||||
remove_virtual_authenticator: function(authenticator_id, context=null) {
|
||||
return window.test_driver_internal.remove_virtual_authenticator(authenticator_id, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -282,13 +320,16 @@
|
||||
* @param {Object} credential - A [Credential Parameters]{@link
|
||||
* https://w3c.github.io/webauthn/#credential-parameters}
|
||||
* object
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credential is added, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors
|
||||
*/
|
||||
add_credential: function(authenticator_id, credential) {
|
||||
return window.test_driver_internal.add_credential(authenticator_id, credential);
|
||||
add_credential: function(authenticator_id, credential, context=null) {
|
||||
return window.test_driver_internal.add_credential(authenticator_id, credential, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -300,6 +341,9 @@
|
||||
* https://w3c.github.io/webauthn/#sctn-automation-get-credentials
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credentials are returned, or
|
||||
* rejected in the cases the WebDriver command
|
||||
@@ -307,8 +351,8 @@
|
||||
* Parameters]{@link
|
||||
* https://w3c.github.io/webauthn/#credential-parameters}
|
||||
*/
|
||||
get_credentials: function(authenticator_id) {
|
||||
return window.test_driver_internal.get_credentials(authenticator_id);
|
||||
get_credentials: function(authenticator_id, context=null) {
|
||||
return window.test_driver_internal.get_credentials(authenticator_id, context=null);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -318,13 +362,16 @@
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
* @param {String} credential_id - the ID of the credential
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credential is removed, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors.
|
||||
*/
|
||||
remove_credential: function(authenticator_id, credential_id) {
|
||||
return window.test_driver_internal.remove_credential(authenticator_id, credential_id);
|
||||
remove_credential: function(authenticator_id, credential_id, context=null) {
|
||||
return window.test_driver_internal.remove_credential(authenticator_id, credential_id, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -333,13 +380,16 @@
|
||||
* https://w3c.github.io/webauthn/#sctn-automation-remove-all-credentials
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credentials are removed, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors.
|
||||
*/
|
||||
remove_all_credentials: function(authenticator_id) {
|
||||
return window.test_driver_internal.remove_all_credentials(authenticator_id);
|
||||
remove_all_credentials: function(authenticator_id, context=null) {
|
||||
return window.test_driver_internal.remove_all_credentials(authenticator_id, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -351,9 +401,12 @@
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
* @param {boolean} uv - the User Verified flag
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*/
|
||||
set_user_verified: function(authenticator_id, uv) {
|
||||
return window.test_driver_internal.set_user_verified(authenticator_id, uv);
|
||||
set_user_verified: function(authenticator_id, uv, context=null) {
|
||||
return window.test_driver_internal.set_user_verified(authenticator_id, uv, context);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -370,16 +423,19 @@
|
||||
* May be "*" to indicate all origins.
|
||||
* @param {String} state - The storage access setting.
|
||||
* Must be either "allowed" or "blocked".
|
||||
* @param {WindowProxy} context - Browsing context in which
|
||||
* to run the call, or null for the current
|
||||
* browsing context.
|
||||
*
|
||||
* @returns {Promise} Fulfilled after the storage access rule has been
|
||||
* set, or rejected if setting the rule fails.
|
||||
*/
|
||||
set_storage_access: function(origin, embedding_origin, state) {
|
||||
set_storage_access: function(origin, embedding_origin, state, context=null) {
|
||||
if (state !== "allowed" && state !== "blocked") {
|
||||
throw new Error("storage access status must be 'allowed' or 'blocked'");
|
||||
}
|
||||
const blocked = state === "blocked";
|
||||
return window.test_driver_internal.set_storage_access(origin, embedding_origin, blocked);
|
||||
return window.test_driver_internal.set_storage_access(origin, embedding_origin, blocked, context);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -392,13 +448,6 @@
|
||||
*/
|
||||
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
|
||||
*/
|
||||
click: function(element, coords) {
|
||||
if (this.in_automation) {
|
||||
return Promise.reject(new Error('Not implemented'));
|
||||
@@ -409,14 +458,6 @@
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Waits for an element to receive a series of key presses
|
||||
*
|
||||
* @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) {
|
||||
if (this.in_automation) {
|
||||
return Promise.reject(new Error('Not implemented'));
|
||||
@@ -449,158 +490,52 @@
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Freeze the current page
|
||||
*
|
||||
* @returns {Promise} fulfilled after freeze request is sent, otherwise
|
||||
* it gets rejected
|
||||
*/
|
||||
freeze: function() {
|
||||
freeze: function(context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a sequence of pointer actions
|
||||
*
|
||||
* @returns {Promise} fufilled after actions are sent, rejected if any actions
|
||||
* fail
|
||||
*/
|
||||
action_sequence: function(actions) {
|
||||
action_sequence: function(actions, context=null) {
|
||||
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) {
|
||||
generate_test_report: function(message, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets the state of a permission
|
||||
*
|
||||
* This function simulates a user setting a permission into a particular state as described
|
||||
* in {@link https://w3c.github.io/permissions/#set-permission-command}
|
||||
*
|
||||
* @param {Object} permission_params - a [PermissionSetParameters]{@lint
|
||||
* https://w3c.github.io/permissions/#dictdef-permissionsetparameters}
|
||||
* object
|
||||
* @returns {Promise} fulfilled after the permission is set, or rejected if setting the
|
||||
* permission fails
|
||||
*/
|
||||
set_permission: function(permission_params) {
|
||||
set_permission: function(permission_params, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a virtual authenticator
|
||||
*
|
||||
* @param {Object} config - the authenticator configuration
|
||||
* @returns {Promise} fulfilled after the authenticator is added, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors.
|
||||
*/
|
||||
add_virtual_authenticator: function(config) {
|
||||
add_virtual_authenticator: function(config, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a virtual authenticator
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator to be
|
||||
* removed.
|
||||
*
|
||||
* @returns {Promise} fulfilled after the authenticator is removed, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors
|
||||
*/
|
||||
remove_virtual_authenticator: function(authenticator_id) {
|
||||
remove_virtual_authenticator: function(authenticator_id, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a credential to a virtual authenticator
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
* @param {Object} credential - A [Credential Parameters]{@link
|
||||
* https://w3c.github.io/webauthn/#credential-parameters}
|
||||
* object
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credential is added, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors
|
||||
*
|
||||
*/
|
||||
add_credential: function(authenticator_id, credential) {
|
||||
add_credential: function(authenticator_id, credential, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all the credentials stored in an authenticator
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credentials are returned, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors. Returns an array of [Credential
|
||||
* Parameters]{@link
|
||||
* https://w3c.github.io/webauthn/#credential-parameters}
|
||||
*
|
||||
*/
|
||||
get_credentials: function(authenticator_id) {
|
||||
get_credentials: function(authenticator_id, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a credential stored in an authenticator
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
* @param {String} credential_id - the ID of the credential
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credential is removed, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors.
|
||||
*
|
||||
*/
|
||||
remove_credential: function(authenticator_id, credential_id) {
|
||||
remove_credential: function(authenticator_id, credential_id, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all the credentials stored in a virtual authenticator
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
*
|
||||
* @returns {Promise} fulfilled after the credentials are removed, or
|
||||
* rejected in the cases the WebDriver command
|
||||
* errors.
|
||||
*
|
||||
*/
|
||||
remove_all_credentials: function(authenticator_id) {
|
||||
remove_all_credentials: function(authenticator_id, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the User Verified flag on an authenticator
|
||||
*
|
||||
* @param {String} authenticator_id - the ID of the authenticator
|
||||
* @param {boolean} uv - the User Verified flag
|
||||
*
|
||||
*/
|
||||
set_user_verified: function(authenticator_id, uv) {
|
||||
set_user_verified: function(authenticator_id, uv, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the storage access policy for a third-party origin when loaded
|
||||
* in the current first party context
|
||||
*/
|
||||
set_storage_access: function(origin, embedding_origin, blocked) {
|
||||
set_storage_access: function(origin, embedding_origin, blocked, context=null) {
|
||||
return Promise.reject(new Error("unimplemented"));
|
||||
},
|
||||
};
|
||||
|
||||
+80
-13
@@ -520,6 +520,43 @@ policies and contribution forms [3].
|
||||
Object.prototype.toString.call(worker) == '[object ServiceWorker]';
|
||||
}
|
||||
|
||||
var seen_func_name = Object.create(null);
|
||||
|
||||
function get_test_name(func, name)
|
||||
{
|
||||
if (name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if (func) {
|
||||
var func_code = func.toString();
|
||||
|
||||
// Try and match with brackets, but fallback to matching without
|
||||
var arrow = func_code.match(/^\(\)\s*=>\s*(?:{(.*)}\s*|(.*))$/);
|
||||
|
||||
// Check for JS line separators
|
||||
if (arrow !== null && !/[\u000A\u000D\u2028\u2029]/.test(func_code)) {
|
||||
var trimmed = (arrow[1] !== undefined ? arrow[1] : arrow[2]).trim();
|
||||
// drop trailing ; if there's no earlier ones
|
||||
trimmed = trimmed.replace(/^([^;]*)(;\s*)+$/, "$1");
|
||||
|
||||
if (trimmed) {
|
||||
let name = trimmed;
|
||||
if (seen_func_name[trimmed]) {
|
||||
// This subtest name already exists, so add a suffix.
|
||||
name += " " + seen_func_name[trimmed];
|
||||
} else {
|
||||
seen_func_name[trimmed] = 0;
|
||||
}
|
||||
seen_func_name[trimmed] += 1;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return test_environment.next_default_test_name();
|
||||
}
|
||||
|
||||
/*
|
||||
* API functions
|
||||
*/
|
||||
@@ -530,17 +567,18 @@ policies and contribution forms [3].
|
||||
tests.status.message = '`test` invoked after `promise_setup`';
|
||||
tests.complete();
|
||||
}
|
||||
var test_name = name ? name : test_environment.next_default_test_name();
|
||||
var test_name = get_test_name(func, name);
|
||||
var test_obj = new Test(test_name, properties);
|
||||
var value = test_obj.step(func, test_obj, test_obj);
|
||||
|
||||
if (value !== undefined) {
|
||||
var msg = "Test named \"" + test_name +
|
||||
"\" inappropriately returned a value";
|
||||
var msg = 'Test named "' + test_name +
|
||||
'" passed a function to `test` that returned a value.';
|
||||
|
||||
try {
|
||||
if (value && value.hasOwnProperty("then")) {
|
||||
msg += ", consider using `promise_test` instead";
|
||||
if (value && typeof value.then === 'function') {
|
||||
msg += ' Consider using `promise_test` instead when ' +
|
||||
'using Promises or async/await.';
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
@@ -565,10 +603,33 @@ policies and contribution forms [3].
|
||||
name = func;
|
||||
func = null;
|
||||
}
|
||||
var test_name = name ? name : test_environment.next_default_test_name();
|
||||
var test_name = get_test_name(func, name);
|
||||
var test_obj = new Test(test_name, properties);
|
||||
if (func) {
|
||||
test_obj.step(func, test_obj, test_obj);
|
||||
var value = test_obj.step(func, test_obj, test_obj);
|
||||
|
||||
// Test authors sometimes return values to async_test, expecting us
|
||||
// to handle the value somehow. Make doing so a harness error to be
|
||||
// clear this is invalid, and point authors to promise_test if it
|
||||
// may be appropriate.
|
||||
//
|
||||
// Note that we only perform this check on the initial function
|
||||
// passed to async_test, not on any later steps - we haven't seen a
|
||||
// consistent problem with those (and it's harder to check).
|
||||
if (value !== undefined) {
|
||||
var msg = 'Test named "' + test_name +
|
||||
'" passed a function to `async_test` that returned a value.';
|
||||
|
||||
try {
|
||||
if (value && typeof value.then === 'function') {
|
||||
msg += ' Consider using `promise_test` instead when ' +
|
||||
'using Promises or async/await.';
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
tests.set_status(tests.status.ERROR, msg);
|
||||
tests.complete();
|
||||
}
|
||||
}
|
||||
return test_obj;
|
||||
}
|
||||
@@ -579,7 +640,7 @@ policies and contribution forms [3].
|
||||
name = func;
|
||||
func = null;
|
||||
}
|
||||
var test_name = name ? name : test_environment.next_default_test_name();
|
||||
var test_name = get_test_name(func, name);
|
||||
var test = new Test(test_name, properties);
|
||||
test._is_promise_test = true;
|
||||
|
||||
@@ -1323,10 +1384,16 @@ policies and contribution forms [3].
|
||||
"expected a number but got a ${type_actual}",
|
||||
{type_actual:typeof actual});
|
||||
|
||||
assert(Math.abs(actual - expected) <= epsilon,
|
||||
"assert_approx_equals", description,
|
||||
"expected ${expected} +/- ${epsilon} but got ${actual}",
|
||||
{expected:expected, actual:actual, epsilon:epsilon});
|
||||
// The epsilon math below does not place nice with NaN and Infinity
|
||||
// But in this case Infinity = Infinity and NaN = NaN
|
||||
if (isFinite(actual) || isFinite(expected)) {
|
||||
assert(Math.abs(actual - expected) <= epsilon,
|
||||
"assert_approx_equals", description,
|
||||
"expected ${expected} +/- ${epsilon} but got ${actual}",
|
||||
{expected:expected, actual:actual, epsilon:epsilon});
|
||||
} else {
|
||||
assert_equals(actual, expected);
|
||||
}
|
||||
}
|
||||
expose(assert_approx_equals, "assert_approx_equals");
|
||||
|
||||
@@ -3773,7 +3840,7 @@ policies and contribution forms [3].
|
||||
function get_title()
|
||||
{
|
||||
if ('document' in global_scope) {
|
||||
//Don't use document.title to work around an Opera bug in XHTML documents
|
||||
//Don't use document.title to work around an Opera/Presto bug in XHTML documents
|
||||
var title = document.getElementsByTagName("title")[0];
|
||||
if (title && title.firstChild && title.firstChild.data) {
|
||||
return title.firstChild.data;
|
||||
|
||||
Vendored
+4
@@ -44,6 +44,10 @@ expected to fail.
|
||||
Tests in `/encoding` and `/html/infrastructure/urls/resolving-urls/query-encoding/` cover the
|
||||
encoding argument to the URL parser.
|
||||
|
||||
There's also limited coverage in `resources/percent-encoding.json` for percent-encode after encoding
|
||||
with _percentEncodeSet_ set to special-query percent-encode set and _spaceAsPlus_ set to false.
|
||||
(Improvements to expand coverage here are welcome.)
|
||||
|
||||
## Specification
|
||||
|
||||
The tests in this directory assert conformance with [the URL Standard][URL].
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
promise_test(() => fetch("resources/percent-encoding.json").then(res => res.json()).then(runTests), "Loading data…");
|
||||
|
||||
function runTests(testUnits) {
|
||||
for (const testUnit of testUnits) {
|
||||
// Ignore comments
|
||||
if (typeof testUnit === "string") {
|
||||
continue;
|
||||
}
|
||||
for (const encoding of Object.keys(testUnit.output)) {
|
||||
async_test(t => {
|
||||
const frame = document.body.appendChild(document.createElement("iframe"));
|
||||
t.add_cleanup(() => frame.remove());
|
||||
frame.onload = t.step_func_done(() => {
|
||||
const output = frame.contentDocument.querySelector("a");
|
||||
// Test that the fragment is always UTF-8 encoded
|
||||
assert_equals(output.hash, `#${testUnit.output["utf-8"]}`, "fragment");
|
||||
assert_equals(output.search, `?${testUnit.output[encoding]}`, "query");
|
||||
});
|
||||
frame.src = `resources/percent-encoding.py?encoding=${encoding}&value=${toBase64(testUnit.input)}`;
|
||||
}, `Input ${testUnit.input} with encoding ${encoding}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use base64 to avoid relying on the URL parser to get UTF-8 percent-encoding correctly. This does
|
||||
// not use btoa directly as that only works with code points in the range U+0000 to U+00FF,
|
||||
// inclusive.
|
||||
function toBase64(input) {
|
||||
const bytes = new TextEncoder().encode(input);
|
||||
const byteString = Array.from(bytes, byte => String.fromCharCode(byte)).join("");
|
||||
const encoded = self.btoa(byteString);
|
||||
return encoded;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
[
|
||||
"Tests for percent-encoding.",
|
||||
{
|
||||
"input": "\u2020",
|
||||
"output": {
|
||||
"big5": "%26%238224%3B",
|
||||
"euc-kr": "%A2%D3",
|
||||
"utf-8": "%E2%80%A0",
|
||||
"windows-1252": "%86"
|
||||
}
|
||||
},
|
||||
"This uses a trailing A to prevent the URL parser from trimming the C0 control.",
|
||||
{
|
||||
"input": "\u000EA",
|
||||
"output": {
|
||||
"big5": "%0EA",
|
||||
"iso-2022-jp": "%26%2365533%3BA",
|
||||
"utf-8": "%0EA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": "\u203E\u005C",
|
||||
"output": {
|
||||
"iso-2022-jp": "%1B(J~%1B(B\\",
|
||||
"utf-8": "%E2%80%BE\\"
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": "\uE5E5",
|
||||
"output": {
|
||||
"gb18030": "%26%2358853%3B",
|
||||
"utf-8": "%EE%97%A5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": "\u2212",
|
||||
"output": {
|
||||
"shift_jis": "%81|",
|
||||
"utf-8": "%E2%88%92"
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": "á|",
|
||||
"output": {
|
||||
"utf-8": "%C3%A1|"
|
||||
}
|
||||
}
|
||||
]
|
||||
Vendored
+4
-4
@@ -8,15 +8,15 @@
|
||||
"path": "encoding"
|
||||
},
|
||||
"url": {
|
||||
"commit": "54c6d64be071c60baaad8c4da0365b962ffbe77c",
|
||||
"commit": "09d8830be15da7e3a44f32a934609c25357d6ef3",
|
||||
"path": "url"
|
||||
},
|
||||
"resources": {
|
||||
"commit": "1d14e821b9586f250e6a31d550504e3d16a05ae7",
|
||||
"commit": "001e50de41dc35820774b27e31f77a165f4c0b9b",
|
||||
"path": "resources"
|
||||
},
|
||||
"interfaces": {
|
||||
"commit": "15e47f779cf61555669b0f67e2c49b9c830b9019",
|
||||
"commit": "8719553b2dd8f0f39d38253ccac2ee9ab4d6c87b",
|
||||
"path": "interfaces"
|
||||
},
|
||||
"html/webappapis/microtask-queuing": {
|
||||
@@ -39,4 +39,4 @@
|
||||
"commit": "7caa3de7471cf19b78ee9efa313c7341a462b5e3",
|
||||
"path": "dom/abort"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
"requires": ["small-icu"],
|
||||
"skip": "TODO: port from .window.js"
|
||||
},
|
||||
"percent-encoding.window.js": {
|
||||
"requires": ["small-icu"],
|
||||
"skip": "TODO: port from .window.js"
|
||||
},
|
||||
"historical.any.js": {
|
||||
"requires": ["small-icu"]
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user