92 lines
3.2 KiB
JavaScript
92 lines
3.2 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
// Here we test that the `dispatchKeyEvent` API resolves after all the synchronous event
|
|
// handlers from the content page have been flushed.
|
|
//
|
|
// Say the content page has an event handler such as:
|
|
//
|
|
// el.addEventListener("keyup", () => {
|
|
// doSomeVeryLongProcessing(); // <- takes a long time but is synchronous!
|
|
// window.myVariable = "newValue";
|
|
// });
|
|
//
|
|
// And imagine this is tested via:
|
|
//
|
|
// await Input.dispatchKeyEvent(...);
|
|
// const myVariable = await Runtime.evaluate({ expression: "window.myVariable" });
|
|
// equals(myVariable, "newValue");
|
|
//
|
|
// In order for this to work, we need to be sure that `await Input.dispatchKeyEvent`
|
|
// resolves only after the content page flushed the event handlers (and
|
|
// `window.myVariable = "newValue"` was executed).
|
|
//
|
|
// This can be racy because Input.dispatchKeyEvent and window.myVariable = "newValue" run
|
|
// in different processes.
|
|
|
|
const PAGE_URL =
|
|
"https://example.com/browser/remote/cdp/test/browser/input/doc_dispatchKeyEvent_race.html";
|
|
|
|
add_task(async function ({ client }) {
|
|
await loadURL(PAGE_URL);
|
|
|
|
const { Input, Runtime } = client;
|
|
|
|
// Need an enabled Runtime domain to run evaluate.
|
|
info("Enable the Runtime domain");
|
|
await Runtime.enable();
|
|
const { context } = await Runtime.executionContextCreated();
|
|
|
|
info("Focus the input on the page");
|
|
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () {
|
|
const input = content.document.querySelector("input");
|
|
input.focus();
|
|
is(input, content.document.activeElement, "Input should be focused");
|
|
});
|
|
|
|
// See doc_input_dispatchKeyEvent_race.html
|
|
// The page listens to `input` events to update a property on window.
|
|
// We will check that the value is updated as soon dispatchKeyEvent has resolved.
|
|
await checkWindowTestValue("initial-value", context.id, Runtime);
|
|
|
|
info("Write 'hhhhhh' ('h' times 6)");
|
|
for (let i = 0; i < 6; i++) {
|
|
await dispatchKeyEvent(Input, "h", 72, "keyDown");
|
|
await dispatchKeyEvent(Input, "h", 72, "keyUp");
|
|
}
|
|
await checkWindowTestValue("hhhhhh", context.id, Runtime);
|
|
|
|
info("Write 'aaaaaa' with 6 consecutive keydown and one keyup");
|
|
await Promise.all([
|
|
dispatchKeyEvent(Input, "a", 65, "keyDown"),
|
|
dispatchKeyEvent(Input, "a", 65, "keyDown"),
|
|
dispatchKeyEvent(Input, "a", 65, "keyDown"),
|
|
dispatchKeyEvent(Input, "a", 65, "keyDown"),
|
|
dispatchKeyEvent(Input, "a", 65, "keyDown"),
|
|
dispatchKeyEvent(Input, "a", 65, "keyDown"),
|
|
]);
|
|
await dispatchKeyEvent(Input, "a", 65, "keyUp");
|
|
await checkWindowTestValue("hhhhhhaaaaaa", context.id, Runtime);
|
|
});
|
|
|
|
function dispatchKeyEvent(Input, key, keyCode, type, modifiers = 0) {
|
|
info(`Send ${type} for key ${key}`);
|
|
return Input.dispatchKeyEvent({
|
|
type,
|
|
modifiers,
|
|
windowsVirtualKeyCode: keyCode,
|
|
key,
|
|
});
|
|
}
|
|
|
|
async function checkWindowTestValue(expected, contextId, Runtime) {
|
|
info("Retrieve the value of `window.testValue` in the test page");
|
|
const { result } = await Runtime.evaluate({
|
|
contextId,
|
|
expression: "window.testValue",
|
|
});
|
|
|
|
is(result.value, expected, "Content window test value is correct");
|
|
}
|