Update web-platform-tests to revision e15b5ebba7465e09bcda2962f6758cddcdcfa248

This commit is contained in:
WPT Sync Bot 2018-10-09 21:32:32 -04:00
parent 68e55ead42
commit 3eaee747ed
214 changed files with 4692 additions and 245 deletions

View file

@ -0,0 +1,391 @@
(function() {
let sourceNameIdx = 0;
/**
* Builder for creating a sequence of actions
*/
function Actions() {
this.sourceTypes = new Map([["key", KeySource],
["pointer", PointerSource],
["general", GeneralSource]]);
this.sources = new Map();
this.sourceOrder = [];
for (let sourceType of this.sourceTypes.keys()) {
this.sources.set(sourceType, new Map());
}
this.currentSources = new Map();
for (let sourceType of this.sourceTypes.keys()) {
this.currentSources.set(sourceType, null);
}
this.createSource("general");
this.tickIdx = 0;
}
Actions.prototype = {
/**
* Generate the action sequence suitable for passing to
* test_driver.action_sequence
*
* @returns {Array} Array of WebDriver-compatible actions sequences
*/
serialize: function() {
let actions = [];
for (let [sourceType, sourceName] of this.sourceOrder) {
let source = this.sources.get(sourceType).get(sourceName);
let serialized = source.serialize(this.tickIdx + 1);
if (serialized) {
serialized.id = sourceName;
actions.push(serialized);
}
}
return actions;
},
/**
* Generate and send the action sequence
*
* @returns {Promise} fulfilled after the sequence is executed,
* rejected if any actions fail.
*/
send: function() {
let actions;
try {
actions = this.serialize();
} catch(e) {
return Promise.reject(e);
}
return test_driver.action_sequence(actions);
},
/**
* Get the action source with a particular source type and name.
* 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?} name - Name of the source
* @returns {Source} Source object for that source.
*/
getSource: function(type, name) {
if (!this.sources.has(type)) {
throw new Error(`${type} is not a valid action type`);
}
if (name === null || name === undefined) {
name = this.currentSources.get(type);
}
if (name === null || name === undefined) {
return this.createSource(type, null);
}
return this.sources.get(type).get(name);
},
setSource: function(type, name) {
if (!this.sources.has(type)) {
throw new Error(`${type} is not a valid action type`);
}
if (!this.sources.get(type).has(name)) {
throw new Error(`${name} is not a valid source for ${type}`);
}
this.currentSources.set(type, name);
return this;
},
/**
* Add a new key input source with the given name
*
* @param {String} name - Name of the key source
* @param {Bool} set - Set source as the default key source
* @returns {Actions}
*/
addKeyboard: function(name, set=true) {
this.createSource("key", name, true);
if (set) {
this.setKeyboard(name);
}
return this;
},
/**
* Set the current default key source
*
* @param {String} name - Name of the key source
* @returns {Actions}
*/
setKeyboard: function(name) {
this.setSource("key", name);
return this;
},
/**
* Add a new pointer input source with the given name
*
* @param {String} type - Name of the key source
* @param {String} pointerType - Type of pointing device
* @param {Bool} set - Set source as the default key source
* @returns {Actions}
*/
addPointer: function(name, pointerType="mouse", set=true) {
this.createSource("pointer", name, true, {pointerType: pointerType});
if (set) {
this.setPointer(name);
}
return this;
},
/**
* Set the current default pointer source
*
* @param {String} name - Name of the pointer source
* @returns {Actions}
*/
setPointer: function(name) {
this.setSource("pointer", name);
return this;
},
createSource: function(type, name, parameters={}) {
if (!this.sources.has(type)) {
throw new Error(`${type} is not a valid action type`);
}
let sourceNames = new Set();
for (let [_, name] of this.sourceOrder) {
sourceNames.add(name);
}
if (!name) {
do {
name = "" + sourceNameIdx++;
} while (sourceNames.has(name))
} else {
if (sourceNames.has(name)) {
throw new Error(`Alreay have a source of type ${type} named ${name}.`);
}
}
this.sources.get(type).set(name, new (this.sourceTypes.get(type))(parameters));
this.currentSources.set(type, name);
this.sourceOrder.push([type, name]);
return this.sources.get(type).get(name);
},
/**
* Insert a new actions tick
*
* @param {Number?} duration - Minimum length of the tick in ms.
* @returns {Actions}
*/
addTick: function(duration) {
this.tickIdx += 1;
if (duration) {
this.pause(duration);
}
return this;
},
/**
* Add a pause to the current tick
*
* @param {Number?} duration - Minimum length of the tick in ms.
* @returns {Actions}
*/
pause: function(duration) {
this.getSource("general").addPause(this, duration);
return this;
},
/**
* Create a keyDown event for the current default key source
*
* @param {String} key - Key to press
* @param {String?} sourceName - Named key source to use or null for the default key source
* @returns {Actions}
*/
keyDown: function(key, {sourceName=null}={}) {
let source = this.getSource("key", sourceName);
source.keyDown(this, key);
return this;
},
/**
* Create a keyDown event for the current default key source
*
* @param {String} key - Key to release
* @param {String?} sourceName - Named key source to use or null for the default key source
* @returns {Actions}
*/
keyUp: function(key, {sourceName=null}={}) {
let source = this.getSource("key", sourceName);
source.keyUp(this, key);
return this;
},
/**
* Create a pointerDown event for the current default pointer source
*
* @param {String} button - Button to press
* @param {String?} sourceName - Named pointer source to use or null for the default
* pointer source
* @returns {Actions}
*/
pointerDown: function({button=0, sourceName=null}={}) {
let source = this.getSource("pointer", sourceName);
source.pointerDown(this, button);
return this;
},
/**
* Create a pointerUp event for the current default pointer source
*
* @param {String} button - Button to release
* @param {String?} sourceName - Named pointer source to use or null for the default pointer
* source
* @returns {Actions}
*/
pointerUp: function({button=0, sourceName=null}={}) {
let source = this.getSource("pointer", sourceName);
source.pointerUp(this, button);
return this;
},
/**
* Create a move event for the current default pointer source
*
* @param {Number} x - Destination x coordinate
* @param {Number} y - Destination y coordinate
* @param {String|Element} origin - Origin of the coordinate system.
* Either "pointer", "viewport" or an Element
* @param {Number?} duration - Time in ms for the move
* @param {String?} sourceName - Named pointer source to use or null for the default pointer
* source
* @returns {Actions}
*/
pointerMove: function(x, y,
{origin="viewport", duration, sourceName=null}={}) {
let source = this.getSource("pointer", sourceName);
source.pointerMove(this, x, y, duration, origin);
return this;
},
};
function GeneralSource() {
this.actions = new Map();
}
GeneralSource.prototype = {
serialize: function(tickCount) {
if (!this.actions.size) {
return undefined;
}
let actions = [];
let data = {"type": "none", "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;
},
addPause: function(actions, duration) {
let tick = actions.tickIdx;
if (this.actions.has(tick)) {
throw new Error(`Already have a pause action for the current tick`);
}
this.actions.set(tick, {type: "pause", duration: duration});
},
};
function KeySource() {
this.actions = new Map();
}
KeySource.prototype = {
serialize: function(tickCount) {
if (!this.actions.size) {
return undefined;
}
let actions = [];
let data = {"type": "key", "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;
},
keyDown: function(actions, key) {
let tick = actions.tickIdx;
if (this.actions.has(tick)) {
tick = actions.addTick().tickIdx;
}
this.actions.set(tick, {type: "keyDown", value: key});
},
keyUp: function(actions, key) {
let tick = actions.tickIdx;
if (this.actions.has(tick)) {
tick = actions.addTick().tickIdx;
}
this.actions.set(tick, {type: "keyUp", value: key});
},
};
function PointerSource(parameters={pointerType: "mouse"}) {
let pointerType = parameters.pointerType || "mouse";
if (!["mouse", "pen", "touch"].includes(pointerType)) {
throw new Error(`Invalid pointerType ${pointerType}`);
}
this.type = pointerType;
this.actions = new Map();
}
PointerSource.prototype = {
serialize: function(tickCount) {
if (!this.actions.size) {
return undefined;
}
let actions = [];
let data = {"type": "pointer", "actions": actions, "parameters": {"pointerType": this.type}};
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;
},
pointerDown: function(actions, button) {
let tick = actions.tickIdx;
if (this.actions.has(tick)) {
tick = actions.addTick().tickIdx;
}
this.actions.set(tick, {type: "pointerDown", button});
},
pointerUp: function(actions, button) {
let tick = actions.tickIdx;
if (this.actions.has(tick)) {
tick = actions.addTick().tickIdx;
}
this.actions.set(tick, {type: "pointerUp", button});
},
pointerMove: function(actions, x, y, duration, origin) {
let tick = actions.tickIdx;
if (this.actions.has(tick)) {
tick = actions.addTick().tickIdx;
}
this.actions.set(tick, {type: "pointerMove", x, y, origin});
if (duration) {
this.actions.get(tick).duration = duration;
}
},
};
test_driver.Actions = Actions;
})();

View file

@ -171,6 +171,29 @@
*/
freeze: function() {
return window.test_driver_internal.freeze();
},
/**
* Send a sequence of actions
*
* This function sends a sequence of actions to the top level window
* 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
* @returns {Promise} fufiled after the actions are performed, or rejected in
* the cases the WebDriver command errors
*/
action_sequence(actions) {
return window.test_driver_internal.action_sequence(actions);
}
};
@ -205,6 +228,16 @@
*/
freeze: function() {
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) {
return Promise.reject(new Error("unimplemented"));
}
};
})();