Bug 1563206 - Test top key combinations that affect gutenberg; r=ato,remote-protocol-reviewers,jdescottes

Differential Revision: https://phabricator.services.mozilla.com/D47032

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Maja Frydrychowicz 2019-10-18 21:01:44 +00:00
parent dd9ea7239d
commit dd650b37c4
7 changed files with 567 additions and 127 deletions

View File

@ -32,7 +32,7 @@ under _remote/test/browser_:
% ./mach mochitest remote/test/browser/browser_cdp.js
The functional tests will appear under the `M` (for _mochitest_)
category in the `bc` (_browser-chrome_) jobs on Treeherder.
category in the `remote` jobs on Treeherder.
As the functional tests will sporadically pop up new Firefox
application windows, a helpful tip is to run them in [headless

View File

@ -7,6 +7,7 @@
var EXPORTED_SYMBOLS = ["Input"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Domain } = ChromeUtils.import(
"chrome://remote/content/domains/Domain.jsm"
);
@ -26,11 +27,16 @@ class Input extends Domain {
* - modifiers
* - text (not supported)
* - type
* - unmodifiedTest (not supported)
* - unmodifiedText (not supported)
* - windowsVirtualKeyCode
* - nativeVirtualKeyCode (not supported)
* - keyIdentifier (not supported)
* - isSystemKey (not supported)
*/
async dispatchKeyEvent(options) {
// missing code, text, unmodifiedText, autorepeat, location, iskeypad
const { key, modifiers, type, windowsVirtualKeyCode } = options;
const { alt, ctrl, meta, shift } = Input.Modifier;
let domType;
if (type == "keyDown" || type == "rawKeyDown") {
@ -62,24 +68,23 @@ class Input extends Domain {
} else {
// Non printable keys should be prefixed with `KEY_`
const eventUtilsKey = key.length == 1 ? key : "KEY_" + key;
EventUtils.synthesizeKey(
eventUtilsKey,
{
keyCode: windowsVirtualKeyCode,
type: domType,
altKey: !!(modifiers & 1),
ctrlKey: !!(modifiers & 2),
metaKey: !!(modifiers & 4),
shiftKey: !!(modifiers & 8),
},
browserWindow
);
const eventInfo = {
keyCode: windowsVirtualKeyCode,
type: domType,
altKey: !!(modifiers & alt),
ctrlKey: !!(modifiers & ctrl),
metaKey: !!(modifiers & meta),
shiftKey: !!(modifiers & shift),
};
EventUtils.synthesizeKey(eventUtilsKey, eventInfo, browserWindow);
}
await this.executeInChild("waitForContentEvent", eventId);
}
async dispatchMouseEvent({ type, button, x, y, modifiers, clickCount }) {
const { alt, ctrl, meta, shift } = Input.Modifier;
if (type == "mousePressed") {
type = "mousedown";
} else if (type == "mouseReleased") {
@ -93,34 +98,18 @@ class Input extends Domain {
if (type === "mousedown" && button === "right") {
type = "contextmenu";
}
if (button == undefined || button == "none" || button == "left") {
button = 0;
} else if (button == "middle") {
button = 1;
} else if (button == "right") {
button = 2;
} else if (button == "back") {
button = 3;
} else if (button == "forward") {
button = 4;
} else {
throw new Error(`Mouse button is not supported: ${button}`);
}
// Gutenberg test packages/e2e-tests/specs/blocks/list.test.js:
// "can be created by converting multiple paragraphs"
// Works better with EventUtils, in order to make the Shift+Click to work
const buttonID = Input.Button[button] || Input.Button.left;
const { browser } = this.session.target;
const currentWindow = browser.ownerGlobal;
const EventUtils = this._getEventUtils(currentWindow);
EventUtils.synthesizeMouse(browser, x, y, {
type,
button,
button: buttonID,
clickCount: clickCount || 1,
altKey: !!(modifiers & 1),
ctrlKey: !!(modifiers & 2),
metaKey: !!(modifiers & 4),
shiftKey: !!(modifiers & 8),
altKey: !!(modifiers & alt),
ctrlKey: !!(modifiers & ctrl),
metaKey: !!(modifiers & meta),
shiftKey: !!(modifiers & shift),
});
}
@ -143,3 +132,18 @@ class Input extends Domain {
return this._eventUtils;
}
}
Input.Button = {
left: 0,
middle: 1,
right: 2,
back: 3,
forward: 4,
};
Input.Modifier = {
alt: 1,
ctrl: 2,
meta: 4,
shift: 8,
};

View File

@ -5,6 +5,7 @@ prefs = remote.enabled=true
support-files =
chrome-remote-interface.js
doc_input_dispatchKeyEvent_race.html
doc_input_events.html
doc_network_requestWillBeSent.html
file_network_requestWillBeSent.js
head.js

View File

@ -3,51 +3,42 @@
"use strict";
// Basic test for dispatch key event API with input type text
const { Input: I } = ChromeUtils.import(
"chrome://remote/content/domains/parent/Input.jsm"
);
const { alt, ctrl, meta, shift } = I.Modifier;
// Map of key codes used in this test.
const KEYCODES = {
a: 65,
Backspace: 8,
h: 72,
H: 72,
AltLeft: 18,
ArrowLeft: 37,
ArrowRight: 39,
a: KeyboardEvent.DOM_VK_A,
A: KeyboardEvent.DOM_VK_A,
b: KeyboardEvent.DOM_VK_B,
B: KeyboardEvent.DOM_VK_B,
c: KeyboardEvent.DOM_VK_C,
C: KeyboardEvent.DOM_VK_C,
h: KeyboardEvent.DOM_VK_H,
H: KeyboardEvent.DOM_VK_H,
Alt: KeyboardEvent.DOM_VK_ALT,
ArrowLeft: KeyboardEvent.DOM_VK_LEFT,
ArrowRight: KeyboardEvent.DOM_VK_RIGHT,
ArrowDown: KeyboardEvent.DOM_VK_DOWN,
Backspace: KeyboardEvent.DOM_VK_BACK_SPACE,
Control: KeyboardEvent.DOM_VK_CONTROL,
Meta: KeyboardEvent.DM_VK_META,
Shift: KeyboardEvent.DOM_VK_SHIFT,
Tab: KeyboardEvent.DOM_VK_TAB,
};
// Modifier for move forward shortcut is CTRL+RightArrow on Linux/Windows, ALT+RightArrow
// on Mac.
const isMac = Services.appinfo.OS === "Darwin";
const ALT_MODIFIER = 1;
const CTRL_MODIFIER = 2;
const ARROW_MODIFIER = isMac ? ALT_MODIFIER : CTRL_MODIFIER;
add_task(async function() {
// The selectionchange event was flagged behind dom.select_events.textcontrols.enabled,
// which is only true on Nightly and Local builds. Force the pref to true so that
// the test passes on all channels. See Bug 1309628 for more details.
info("Enable selectionchange events on input elements");
await new Promise(resolve => {
const options = {
set: [["dom.select_events.textcontrols.enabled", true]],
};
SpecialPowers.pushPrefEnv(options, resolve);
});
const { client, tab } = await setupForURL(toDataURL("<input>"));
is(gBrowser.selectedTab, tab, "Selected tab is the target tab");
const PAGE_URL =
"http://example.com/browser/remote/test/browser/doc_input_events.html";
add_task(async function testTypingPrintableCharacters() {
const { client } = await setupForInput(toDataURL("<input>"));
const { Input } = client;
info("Focus the input on the page");
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
const input = content.document.querySelector("input");
input.focus();
is(input, content.document.activeElement, "Input should be focused");
});
await checkInputContent("", 0);
info("Write 'h'");
await sendTextKey(Input, "h");
await checkInputContent("h", 1);
@ -64,8 +55,16 @@ add_task(async function() {
});
await checkInputContent("hH", 3);
await teardown(client);
});
add_task(async function testArrowKeys() {
const { client } = await setupForInput(toDataURL("<input>"));
const { Input } = client;
await sendText(Input, "hH");
info("Send Left");
await sendArrowKey(Input, "ArrowLeft");
await sendRawKey(Input, "ArrowLeft");
await checkInputContent("hH", 2);
info("Write 'a'");
@ -73,44 +72,303 @@ add_task(async function() {
await checkInputContent("hHa", 3);
info("Send Left");
await sendArrowKey(Input, "ArrowLeft");
await sendRawKey(Input, "ArrowLeft");
await checkInputContent("hHa", 2);
info("Send Left");
await sendArrowKey(Input, "ArrowLeft");
await sendRawKey(Input, "ArrowLeft");
await checkInputContent("hHa", 1);
info("Write 'a'");
await sendTextKey(Input, "a");
await checkInputContent("haHa", 2);
info("Send ALT/CTRL + Right");
await sendArrowKey(Input, "ArrowRight", ARROW_MODIFIER);
info("Send ALT/CONTROL + Right");
let modCode = isMac ? alt : ctrl;
let modKey = isMac ? "Alt" : "Control";
await dispatchKeyEvent(Input, modKey, "rawKeyDown", modCode);
await dispatchKeyEvent(Input, "ArrowRight", "rawKeyDown", modCode);
await dispatchKeyEvent(Input, "ArrowRight", "keyUp");
await dispatchKeyEvent(Input, modKey, "keyUp");
await checkInputContent("haHa", 5);
info("Delete every character in the input");
await sendBackspace(Input, "haHa");
await sendBackspace(Input, "haH");
await sendBackspace(Input, "ha");
await sendBackspace(Input, "h");
await sendBackspace(Input, "");
await client.close();
ok(true, "The client is closed");
BrowserTestUtils.removeTab(tab);
await RemoteAgent.close();
await teardown(client);
});
async function sendTextKey(Input, key) {
await dispatchKeyEvent(Input, key, "keyDown");
await dispatchKeyEvent(Input, key, "keyUp");
add_task(async function testBackspace() {
const { client } = await setupForInput(toDataURL("<input>"));
const { Input } = client;
await sendText(Input, "haHa");
info("Delete every character in the input");
await checkBackspace(Input, "haHa");
await checkBackspace(Input, "haH");
await checkBackspace(Input, "ha");
await checkBackspace(Input, "h");
await checkBackspace(Input, "");
await teardown(client);
});
add_task(async function testShiftSelect() {
const { client } = await setupForInput(toDataURL("<input>"));
const { Input } = client;
await resetInput("word 2 word3");
info("Send Shift + Left (select one char to the left)");
await dispatchKeyEvent(Input, "Shift", "rawKeyDown", shift);
await sendRawKey(Input, "ArrowLeft", shift);
await sendRawKey(Input, "ArrowLeft", shift);
await sendRawKey(Input, "ArrowLeft", shift);
info("(deleteContentBackward)");
await checkBackspace(Input, "word 2 wo");
await dispatchKeyEvent(Input, "Shift", "keyUp");
await resetInput("word 2 wo");
info("Send Shift + Left (select one char to the left)");
await dispatchKeyEvent(Input, "Shift", "rawKeyDown", shift);
await sendRawKey(Input, "ArrowLeft", shift);
await sendRawKey(Input, "ArrowLeft", shift);
await sendTextKey(Input, "H");
await checkInputContent("word 2 H", 8);
await dispatchKeyEvent(Input, "Shift", "keyUp");
await teardown(client);
});
add_task(async function testSelectWord() {
const { client } = await setupForInput(toDataURL("<input>"));
const { Input } = client;
await resetInput("word 2 word3");
info("Send Shift + Ctrl/Alt + Left (select one word to the left)");
const { primary, primaryKey } = keyForPlatform();
const combined = shift | primary;
await dispatchKeyEvent(Input, "Shift", "rawKeyDown", shift);
await dispatchKeyEvent(Input, primaryKey, "rawKeyDown", combined);
await sendRawKey(Input, "ArrowLeft", combined);
await sendRawKey(Input, "ArrowLeft", combined);
await dispatchKeyEvent(Input, "Shift", "keyUp", primary);
await dispatchKeyEvent(Input, primaryKey, "keyUp");
info("(deleteContentBackward)");
await checkBackspace(Input, "word ");
await teardown(client);
});
add_task(async function testSelectDelete() {
const { client } = await setupForInput(toDataURL("<input>"));
const { Input } = client;
await resetInput("word 2 word3");
info("Send Ctrl/Alt + Backspace (deleteWordBackward)");
const { primary, primaryKey } = keyForPlatform();
await dispatchKeyEvent(Input, primaryKey, "rawKeyDown", primary);
if (Services.appinfo.OS === "WINNT") {
await checkBackspace(Input, "word 2 ", primary);
}
await dispatchKeyEvent(Input, primaryKey, "keyUp");
await resetInput("word 2 ");
await sendText(Input, "word4");
await sendRawKey(Input, "ArrowLeft");
await sendRawKey(Input, "ArrowLeft");
await checkInputContent("word 2 word4", 10);
if (isMac) {
info("Send Meta + Backspace (deleteSoftLineBackward)");
await dispatchKeyEvent(Input, "Meta", "rawKeyDown", meta);
await sendRawKey(Input, "Backspace", meta);
const { value, caret } = await getInputContent();
await dispatchKeyEvent(Input, "Meta", "keyUp");
todo_is(value, "d4", "Meta + Backspace should delete line backward");
todo_is(caret, 0, "Check position after Meta + Backspace");
}
await teardown(client);
});
add_task(async function testShiftEvents() {
const { client } = await setupForInput(PAGE_URL);
const { Input } = client;
await resetEvents();
await withModifier(Input, "Shift", "shift", "A");
await checkInputContent("A", 1);
let events = await getEvents();
checkEvent(events[0], "keydown", "Shift", "shift", true);
checkEvent(events[1], "keydown", "A", "shift", true);
checkEvent(events[2], "keypress", "A", "shift", true);
checkProperties({ data: "A", inputType: "insertText" }, events[3]);
checkEvent(events[4], "keyup", "A", "shift", true);
checkEvent(events[5], "keyup", "Shift", "shift", false);
await resetEvents();
await withModifier(Input, "Shift", "shift", "Enter");
events = await getEvents();
checkEvent(events[2], "keypress", "Enter", "shift", true);
await resetEvents();
await withModifier(Input, "Shift", "shift", "Tab");
events = await getEvents();
checkEvent(events[1], "keydown", "Tab", "shift", true);
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
const input = content.document.querySelector("input");
isnot(input, content.document.activeElement, "input should lose focus");
});
await teardown(client);
});
add_task(async function testAltEvents() {
const { client } = await setupForInput(PAGE_URL);
const { Input } = client;
await withModifier(Input, "Alt", "alt", "a");
if (isMac) {
await checkInputContent("a", 1);
} else {
await checkInputContent("", 0);
}
let events = await getEvents();
checkEvent(events[1], "keydown", "a", "alt", true);
checkEvent(events[events.length - 1], "keyup", "Alt", "alt", false);
await teardown(client);
});
add_task(async function testControlEvents() {
const { client } = await setupForInput(PAGE_URL);
const { Input } = client;
await withModifier(Input, "Control", "ctrl", "`");
let events = await getEvents();
// no keypress or input event
checkEvent(events[1], "keydown", "`", "ctrl", true);
checkEvent(events[events.length - 1], "keyup", "Control", "ctrl", false);
await teardown(client);
});
add_task(async function testMetaEvents() {
if (!isMac) {
return;
}
const { client } = await setupForInput(PAGE_URL);
const { Input } = client;
await withModifier(Input, "Meta", "meta", "a");
let events = await getEvents();
// no keypress or input event
checkEvent(events[1], "keydown", "a", "meta", true);
checkEvent(events[events.length - 1], "keyup", "Meta", "meta", false);
await teardown(client);
});
add_task(async function testCtrlShiftArrows() {
const { client } = await setupForURL(
toDataURL('<select multiple size="3"><option>a<option>b<option>c</select>')
);
const { Input } = client;
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
const select = content.document.querySelector("select");
select.selectedIndex = 0;
select.focus();
});
const combined = shift | ctrl;
await dispatchKeyEvent(Input, "Control", "rawKeyDown", shift);
await dispatchKeyEvent(Input, "Shift", "rawKeyDown", combined);
await sendRawKey(Input, "ArrowDown", combined);
await dispatchKeyEvent(Input, "Control", "keyUp", shift);
await dispatchKeyEvent(Input, "Shift", "keyUp");
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
const select = content.document.querySelector("select");
ok(select[0].selected, "First option should be selected");
ok(select[1].selected, "Second option should be selected");
ok(!select[2].selected, "Third option should not be selected");
});
await teardown(client);
});
add_task(async function testShiftClick() {
const { client } = await setupForURL(PAGE_URL);
const { Input } = client;
await resetEvents();
await dispatchKeyEvent(Input, "Shift", "rawKeyDown", shift);
info("Click the 'pointers' div.");
await Input.dispatchMouseEvent({
type: "mousePressed",
x: 80,
y: 180,
modifiers: shift,
});
await Input.dispatchMouseEvent({
type: "mouseReleased",
x: 80,
y: 180,
modifiers: shift,
});
await dispatchKeyEvent(Input, "Shift", "keyUp", shift);
let events = await getEvents();
checkProperties({ type: "click", shiftKey: true, button: 0 }, events[2]);
await teardown(client);
});
function keyForPlatform() {
// TODO add cases for other key-combinations as the need arises
let primary = ctrl;
let primaryKey = "Control";
if (isMac) {
primary = alt;
primaryKey = "Alt";
}
return { primary, primaryKey };
}
async function sendArrowKey(Input, arrowKey, modifiers = 0) {
await dispatchKeyEvent(Input, arrowKey, "rawKeyDown", modifiers);
await dispatchKeyEvent(Input, arrowKey, "keyUp", modifiers);
async function setupForInput(url) {
const { client, tab } = await setupForURL(url);
info("Focus the input on the page");
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
const input = content.document.querySelector("input");
input.focus();
is(input, content.document.activeElement, "Input should be focused");
});
await checkInputContent("", 0);
return { client, tab };
}
async function sendTextKey(Input, key, modifiers = 0) {
await dispatchKeyEvent(Input, key, "keyDown", modifiers);
await dispatchKeyEvent(Input, key, "keyUp", modifiers);
}
async function sendText(Input, text) {
for (const sym of text) {
await sendTextKey(Input, sym);
}
}
async function sendRawKey(Input, key, modifiers = 0) {
await dispatchKeyEvent(Input, key, "rawKeyDown", modifiers);
await dispatchKeyEvent(Input, key, "keyUp", modifiers);
}
async function checkBackspace(Input, expected, modifiers = 0) {
info("Send Backspace");
await sendRawKey(Input, "Backspace", modifiers);
await checkInputContent(expected, expected.length);
}
async function withModifier(Input, modKey, mod, key) {
await dispatchKeyEvent(Input, modKey, "rawKeyDown", I.Modifier[mod]);
await dispatchKeyEvent(Input, key, "keyDown", I.Modifier[mod]);
await dispatchKeyEvent(Input, key, "keyUp", I.Modifier[mod]);
await dispatchKeyEvent(Input, modKey, "keyUp");
}
function dispatchKeyEvent(Input, key, type, modifiers = 0) {
@ -123,32 +381,53 @@ function dispatchKeyEvent(Input, key, type, modifiers = 0) {
});
}
function getInputContent() {
return ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
const input = content.document.querySelector("input");
return { value: input.value, caret: input.selectionStart };
});
}
async function checkInputContent(expectedValue, expectedCaret) {
const { value, caret } = await ContentTask.spawn(
gBrowser.selectedBrowser,
null,
function() {
const input = content.document.querySelector("input");
return { value: input.value, caret: input.selectionStart };
}
);
is(
value,
expectedValue,
`The input value is correct ("${value}"="${expectedValue}")`
);
is(
caret,
expectedCaret,
`The input caret has the correct index ("${caret}"="${expectedCaret}")`
);
const { value, caret } = await getInputContent();
is(value, expectedValue, "Check input content");
is(caret, expectedCaret, "Check position of input caret");
}
async function sendBackspace(Input, expected) {
info("Send Backspace");
await dispatchKeyEvent(Input, "Backspace", "rawKeyDown");
await dispatchKeyEvent(Input, "Backspace", "keyUp");
await checkInputContent(expected, expected.length);
// assuming doc_input_events.html
async function getEvents() {
const events = await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
return content.eval("allEvents");
});
info(`Events: ${JSON.stringify(events)}`);
return events;
}
// assuming doc_input_events.html
async function resetEvents() {
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
content.eval("resetEvents()");
const events = content.eval("allEvents");
is(events.length, 0, "List of events should be empty");
});
}
function resetInput(value = "") {
return ContentTask.spawn(gBrowser.selectedBrowser, value, function(arg) {
const input = content.document.querySelector("input");
input.value = arg;
input.focus();
});
}
function checkEvent(event, type, key, property, expectedValue) {
let expected = { type, key };
expected[property] = expectedValue;
checkProperties(expected, event, "Event");
}
function checkProperties(expectedObj, targetObj, message = "Compare objects") {
for (const prop in expectedObj) {
is(targetObj[prop], expectedObj[prop], message + `: check ${prop}`);
}
}

View File

@ -4,7 +4,7 @@
"use strict";
add_task(async function testDispatchMouseEvent() {
const { client, tab } = await setupForURL(toDataURL("<div>foo</div>"));
const { client } = await setupForURL(toDataURL("<div>foo</div>"));
const { Input } = client;
@ -52,10 +52,5 @@ add_task(async function testDispatchMouseEvent() {
return this.clickPromise;
});
await client.close();
ok(true, "The client is closed");
BrowserTestUtils.removeTab(tab);
await RemoteAgent.close();
await teardown(client);
});

View File

@ -0,0 +1,148 @@
<!doctype html>
<meta charset=utf-8>
<html>
<head>
<title>Input Events</title>
<style>
div { padding:0px; margin: 0px; }
#trackPointer { position: fixed; }
#resultContainer { width: 600px; height: 60px; }
.area { width: 100px; height: 50px; background-color: #ccc; }
.block { width: 5px; height: 5px; border: solid 1px red; }
#dragArea { position: relative; }
#dragTarget { position: absolute; top:22px; left:47px;}
</style>
<script>
"use strict";
var allEvents = [];
function makeParagraph(message) {
let paragraph = document.createElement("p");
paragraph.textContent = message;
return paragraph;
}
function displayMessage(message) {
let eventNode = document.getElementById("events");
eventNode.innerHTML = ""
eventNode.appendChild(makeParagraph(message));
}
function appendMessage(message) {
document.getElementById("events").appendChild(makeParagraph(message));
}
/**
* Escape |key| if it's in a surrogate-half character range.
*
* Example: given "\ud83d" return "U+d83d".
*
* Otherwise JSON.stringify will convert it to U+FFFD (REPLACEMENT CHARACTER)
* when returning a value from executeScript, for example.
*/
function escapeSurrogateHalf(key) {
if (typeof key !== "undefined" && key.length === 1) {
var charCode = key.charCodeAt(0);
var highSurrogate = charCode >= 0xD800 && charCode <= 0xDBFF;
var surrogate = highSurrogate || (charCode >= 0xDC00 && charCode <= 0xDFFF);
if (surrogate) {
key = "U+" + charCode.toString(16);
}
}
return key;
}
function recordKeyboardEvent(event) {
var key = escapeSurrogateHalf(event.key);
allEvents.push({
"code": event.code,
"key": key,
"which": event.which,
"location": event.location,
"alt": event.altKey,
"ctrl": event.ctrlKey,
"meta": event.metaKey,
"shift": event.shiftKey,
"repeat": event.repeat,
"type": event.type
});
appendMessage(event.type + " " +
"code: " + event.code + ", " +
"key: " + key + ", " +
"which: " + event.which + ", " +
"keyCode: " + event.keyCode);
}
function recordInputEvent(event) {
allEvents.push({
"data": event.data,
"inputType": event.inputType,
"isComposing": event.isComposing,
});
appendMessage("InputEvent " +
"data: " + event.data + ", " +
"inputType: " + event.inputType + ", " +
"isComposing: " + event.isComposing);
}
function recordPointerEvent(event) {
if (event.type === "contextmenu") {
event.preventDefault();
}
allEvents.push({
"type": event.type,
"button": event.button,
"buttons": event.buttons,
"pageX": event.pageX,
"pageY": event.pageY,
"ctrlKey": event.ctrlKey,
"metaKey": event.metaKey,
"altKey": event.altKey,
"shiftKey": event.shiftKey,
"target": event.target.id
});
appendMessage(event.type + " " +
"pageX: " + event.pageX + ", " +
"pageY: " + event.pageY + ", " +
"button: " + event.button + ", " +
"buttons: " + event.buttons + ", " +
"ctrlKey: " + event.ctrlKey + ", " +
"altKey: " + event.altKey + ", " +
"metaKey: " + event.metaKey + ", " +
"shiftKey: " + event.shiftKey + ", " +
"target id: " + event.target.id);
}
function resetEvents() {
allEvents.length = 0;
displayMessage("");
}
document.addEventListener("DOMContentLoaded", function() {
let keyReporter = document.getElementById("keys");
keyReporter.addEventListener("keyup", recordKeyboardEvent);
keyReporter.addEventListener("keypress", recordKeyboardEvent);
keyReporter.addEventListener("keydown", recordKeyboardEvent);
keyReporter.addEventListener("input", recordInputEvent);
let mouseReporter = document.getElementById("pointers");
mouseReporter.addEventListener("click", recordPointerEvent);
mouseReporter.addEventListener("dblclick", recordPointerEvent);
mouseReporter.addEventListener("mousedown", recordPointerEvent);
mouseReporter.addEventListener("mouseup", recordPointerEvent);
mouseReporter.addEventListener("contextmenu", recordPointerEvent);
});
</script>
</head>
<body>
<div id="trackPointer" class="block"></div>
<div>
<h2>KeyReporter</h2>
<input type="text" id="keys" size="80">
</div>
<div>
<h2>ClickReporter</h2>
<div id="pointers" class="area">
</div>
</div>
<div id="resultContainer">
<h2>Events</h2>
<div id="events"></div>
</div>
</body>
</html>

View File

@ -116,6 +116,7 @@ async function setup() {
*/
async function setupForURL(url) {
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
is(gBrowser.selectedTab, tab, "Selected tab is the target tab");
await RemoteAgent.listen(Services.io.newURI("http://localhost:9222"));
const CDP = await getCDP();
@ -157,3 +158,15 @@ function getContentProperty(prop) {
_prop => content[_prop]
);
}
/**
* Close tabs, client, remote agent.
*/
async function teardown(client) {
await client.close();
ok(true, "The client is closed");
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
await RemoteAgent.close();
}