Bug 1337133 - Fix creation of pointer InputState; r?ato
Previously, the pointer input state was always being created
with an undefined subtype, which should actually be mouse, pen
or touch.
MozReview-Commit-ID: JcarsRRecQl
--- a/testing/marionette/action.js
+++ b/testing/marionette/action.js
@@ -431,32 +431,41 @@ class InputState {
}
toString() {
return `[object ${this.constructor.name}InputState]`;
}
/**
* @param {?} obj
- * Object with property |type|, representing an action sequence or an
- * action item.
+ * Object with property |type| and optionally |parameters| or |pointerType|,
+ * representing an action sequence or an action item.
*
* @return {action.InputState}
* An |action.InputState| object for the type of the |actionSequence|.
*
* @throws {InvalidArgumentError}
* If |actionSequence.type| is not valid.
*/
static fromJson(obj) {
let type = obj.type;
if (!(type in ACTIONS)) {
throw new InvalidArgumentError(`Unknown action type: ${type}`);
}
let name = type == "none" ? "Null" : capitalize(type);
- return new action.InputState[name]();
+ if (name == "Pointer") {
+ if (!obj.pointerType && (!obj.parameters || !obj.parameters.pointerType)) {
+ throw new InvalidArgumentError(
+ error.pprint`Expected obj to have pointerType, got: ${obj}`);
+ }
+ let pointerType = obj.pointerType || obj.parameters.pointerType;
+ return new action.InputState[name](pointerType);
+ } else {
+ return new action.InputState[name]();
+ }
}
}
/** Possible kinds of |InputState| for supported input sources. */
action.InputState = {};
/**
* Input state associated with a keyboard-type device.
@@ -541,22 +550,26 @@ action.InputState.Null = class Null exte
}
};
/**
* Input state associated with a pointer-type input device.
*
* @param {string} subtype
* Kind of pointing device: mouse, pen, touch.
+ *
+ * @throws {InvalidArgumentError}
+ * If subtype is undefined or an invalid pointer type.
*/
action.InputState.Pointer = class Pointer extends InputState {
constructor(subtype) {
super();
this.pressed = new Set();
- this.subtype = subtype;
+ assert.defined(subtype, error.pprint`Expected subtype to be defined, got: ${subtype}`);
+ this.subtype = action.PointerType.get(subtype);
this.x = 0;
this.y = 0;
}
};
/**
* Repesents an action for dispatch. Used in |action.Chain| and |action.Sequence|.
*
@@ -799,24 +812,29 @@ action.PointerParameters = class {
* Input source ID.
* @param {action.PointerParams} pointerParams
* Input source pointer parameters.
* @param {action.Action} act
* Action to be updated.
*
* @throws {InvalidArgumentError}
* If |id| is already mapped to an |action.InputState| that is
- * not compatible with |act.subtype|.
+ * not compatible with |act.type| or |pointerParams.pointerType|.
*/
action.processPointerAction = function processPointerAction(id, pointerParams, act) {
- let subtype = act.subtype;
- if (action.inputStateMap.has(id) && action.inputStateMap.get(id).subtype !== subtype) {
+ if (action.inputStateMap.has(id) && action.inputStateMap.get(id).type !== act.type) {
+ throw new InvalidArgumentError(
+ `Expected 'id' ${id} to be mapped to InputState whose type is ` +
+ `${action.inputStateMap.get(id).type}, got: ${act.type}`);
+ }
+ let pointerType = pointerParams.pointerType;
+ if (action.inputStateMap.has(id) && action.inputStateMap.get(id).subtype !== pointerType) {
throw new InvalidArgumentError(
`Expected 'id' ${id} to be mapped to InputState whose subtype is ` +
- `${action.inputStateMap.get(id).subtype}, got: ${subtype}`);
+ `${action.inputStateMap.get(id).subtype}, got: ${pointerType}`);
}
act.pointerType = pointerParams.pointerType;
};
/** Collect properties associated with KeyboardEvent */
action.Key = class {
constructor(rawKey) {
this.key = NORMALIZED_KEY_LOOKUP[rawKey] || rawKey;
--- a/testing/marionette/test_action.js
+++ b/testing/marionette/test_action.js
@@ -376,40 +376,58 @@ add_test(function test_processInputSourc
run_next_test();
});
add_test(function test_processPointerActionInputStateMap() {
let actionItem = {type: "pointerDown"};
let id = "1";
let parameters = {pointerType: "mouse"};
let a = new action.Action(id, "pointer", actionItem.type);
- let wrongInputState = new action.InputState.Pointer("pause", true);
+ let wrongInputState = new action.InputState.Key();
+ action.inputStateMap.set(id, wrongInputState);
+ checkErrors(
+ /to be mapped to InputState whose type is/, action.processPointerAction,
+ [id, parameters, a],
+ `type "pointer" with ${wrongInputState.type} in inputState`);
+ action.inputStateMap.clear();
+
+ wrongInputState = new action.InputState.Pointer("pen");
action.inputStateMap.set(id, wrongInputState);
checkErrors(
/to be mapped to InputState whose subtype is/, action.processPointerAction,
[id, parameters, a],
- `$subtype ${actionItem.type} with ${wrongInputState.subtype} in inputState`);
+ `subtype ${parameters.pointerType} with ${wrongInputState.subtype} in inputState`);
action.inputStateMap.clear();
- let rightInputState = new action.InputState.Pointer("pointerDown", false);
+
+ let rightInputState = new action.InputState.Pointer("mouse");
action.inputStateMap.set(id, rightInputState);
action.processPointerAction(id, parameters, a);
action.inputStateMap.clear();
run_next_test();
});
add_test(function test_createInputState() {
for (let kind in action.InputState) {
- let state = new action.InputState[kind]();
+ let state;
+ if (kind == "Pointer") {
+ state = new action.InputState[kind]("mouse");
+ } else {
+ state = new action.InputState[kind]();
+ }
ok(state);
if (kind === "Null") {
equal(state.type, "none");
} else {
equal(state.type, kind.toLowerCase());
}
}
+ Assert.throws(() => new action.InputState.Pointer(), InvalidArgumentError,
+ "Missing InputState.Pointer constructor arg");
+ Assert.throws(() => new action.InputState.Pointer("foo"), InvalidArgumentError,
+ "Invalid InputState.Pointer constructor arg");
run_next_test();
});
add_test(function test_extractActionChainValidation() {
for (let actions of [-1, "a", undefined, null]) {
let message = `actions: ${getTypeString(actions)}`;
Assert.throws(() => action.Chain.fromJson(actions),
InvalidArgumentError, message);