summaryrefslogtreecommitdiffstats
path: root/dom/events/test
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/test')
-rw-r--r--dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js163
-rw-r--r--dom/events/test/mochitest.toml3
-rw-r--r--dom/events/test/pointerevents/mochitest_support_external.js2
-rw-r--r--dom/events/test/pointerevents/test_bug1315862.html4
-rw-r--r--dom/events/test/test_accesskey.html2
-rw-r--r--dom/events/test/test_bug226361.xhtml9
-rw-r--r--dom/events/test/test_bug238987.html2
-rw-r--r--dom/events/test/test_bug336682.js2
-rw-r--r--dom/events/test/test_bug448602.html21
-rw-r--r--dom/events/test/test_mouse_events_after_touchend.html232
-rw-r--r--dom/events/test/test_use_split_keypress_event_model_on_old_Confluence.html2
-rw-r--r--dom/events/test/test_use_split_keypress_event_model_on_old_Office_Online_Server.html2
12 files changed, 407 insertions, 37 deletions
diff --git a/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js
index f504e499c9..97066cd2eb 100644
--- a/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js
+++ b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js
@@ -238,16 +238,10 @@ add_task(async function test_context_menu_suppression_image() {
await pasteButtonIsShown;
info("Test read from same-origin frame before paste contextmenu is closed");
- const clipboarCacheEnabled = SpecialPowers.getBoolPref(
- "widget.clipboard.use-cached-data.enabled",
- false
- );
// If the cached data is used, it uses type order in cached transferable.
SimpleTest.isDeeply(
await readTypes(browser.browsingContext.children[0]),
- clipboarCacheEnabled
- ? ["text/plain", "text/html", "image/png"]
- : ["text/html", "text/plain", "image/png"],
+ ["text/html", "text/plain", "image/png"],
"read from same-origin should just be resolved without showing paste contextmenu shown"
);
@@ -262,3 +256,158 @@ add_task(async function test_context_menu_suppression_image() {
);
});
});
+
+function testPasteContextMenuSuppressionPasteEvent(
+ aTriggerPasteFun,
+ aSuppress,
+ aMsg
+) {
+ add_task(async function test_context_menu_suppression_paste_event() {
+ await BrowserTestUtils.withNewTab(
+ kContentFileUrl,
+ async function (browser) {
+ info(`Write data by in cross-origin frame`);
+ const clipboardText = "X" + Math.random();
+ await SpecialPowers.spawn(
+ browser.browsingContext.children[1],
+ [clipboardText],
+ async text => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.writeText("${text}");`);
+ }
+ );
+
+ info("Test read should show contextmenu");
+ let pasteButtonIsShown = waitForPasteContextMenu();
+ let readTextRequest = readText(browser);
+ await pasteButtonIsShown;
+
+ info("Click paste button, request should be resolved");
+ await promiseClickPasteButton();
+ is(await readTextRequest, clipboardText, "Request should be resolved");
+
+ info("Test read in paste event handler");
+ readTextRequest = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`
+ (() => {
+ return new Promise(resolve => {
+ document.addEventListener("paste", function(e) {
+ e.preventDefault();
+ resolve(navigator.clipboard.readText());
+ }, { once: true });
+ });
+ })();
+ `);
+ });
+
+ if (aSuppress) {
+ let listener = function (e) {
+ if (e.target.getAttribute("id") == kPasteMenuPopupId) {
+ ok(!aSuppress, "paste contextmenu should not be shown");
+ }
+ };
+ document.addEventListener("popupshown", listener);
+ info(`Trigger paste event by ${aMsg}`);
+ // trigger paste event
+ await aTriggerPasteFun(browser);
+ is(
+ await readTextRequest,
+ clipboardText,
+ "Request should be resolved"
+ );
+ document.removeEventListener("popupshown", listener);
+ } else {
+ let pasteButtonIsShown = waitForPasteContextMenu();
+ info(
+ `Trigger paste event by ${aMsg}, read should still show contextmenu`
+ );
+ // trigger paste event
+ await aTriggerPasteFun(browser);
+ await pasteButtonIsShown;
+
+ info("Click paste button, request should be resolved");
+ await promiseClickPasteButton();
+ is(
+ await readTextRequest,
+ clipboardText,
+ "Request should be resolved"
+ );
+ }
+
+ info("Test read should still show contextmenu");
+ pasteButtonIsShown = waitForPasteContextMenu();
+ readTextRequest = readText(browser);
+ await pasteButtonIsShown;
+
+ info("Click paste button, request should be resolved");
+ await promiseClickPasteButton();
+ is(await readTextRequest, clipboardText, "Request should be resolved");
+ }
+ );
+ });
+}
+
+// If platform supports selection clipboard, the middle click paste the content
+// from selection clipboard instead, in such case, we don't suppress the
+// contextmenu when access global clipboard via async clipboard API.
+if (
+ !Services.clipboard.isClipboardTypeSupported(
+ Services.clipboard.kSelectionClipboard
+ )
+) {
+ testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["middlemouse.paste", true]],
+ });
+
+ await SpecialPowers.spawn(browser, [], async () => {
+ EventUtils.synthesizeMouse(
+ content.document.documentElement,
+ 1,
+ 1,
+ { button: 1 },
+ content.window
+ );
+ });
+ },
+ true,
+ "middle click"
+ );
+}
+
+testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await EventUtils.synthesizeAndWaitKey(
+ "v",
+ kIsMac ? { accelKey: true } : { ctrlKey: true }
+ );
+ },
+ true,
+ "keyboard shortcut"
+);
+
+testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await SpecialPowers.spawn(browser, [], async () => {
+ return SpecialPowers.doCommand(content.window, "cmd_paste");
+ });
+ },
+ true,
+ "paste command"
+);
+
+testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await SpecialPowers.spawn(browser, [], async () => {
+ let div = content.document.createElement("div");
+ div.setAttribute("contenteditable", "true");
+ content.document.documentElement.appendChild(div);
+ div.focus();
+ return SpecialPowers.doCommand(content.window, "cmd_pasteNoFormatting");
+ });
+ },
+ false,
+ "pasteNoFormatting command"
+);
diff --git a/dom/events/test/mochitest.toml b/dom/events/test/mochitest.toml
index b6b9e58368..53675a8f49 100644
--- a/dom/events/test/mochitest.toml
+++ b/dom/events/test/mochitest.toml
@@ -472,6 +472,9 @@ skip-if = [
"http2",
]
+["test_mouse_events_after_touchend.html"]
+skip-if = ["os == 'mac'"] # Bug 1881864
+
["test_mouse_over_at_removing_down_target.html"]
["test_moving_and_expanding_selection_per_page.html"]
diff --git a/dom/events/test/pointerevents/mochitest_support_external.js b/dom/events/test/pointerevents/mochitest_support_external.js
index 7f22166fdd..7a758a8c5f 100644
--- a/dom/events/test/pointerevents/mochitest_support_external.js
+++ b/dom/events/test/pointerevents/mochitest_support_external.js
@@ -2,6 +2,8 @@
// to tests on auto MochiTest system with minimum changes.
// Author: Maksim Lebedev <alessarik@gmail.com>
+/* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */
+
// Function allows to prepare our tests after load document
addEventListener(
"load",
diff --git a/dom/events/test/pointerevents/test_bug1315862.html b/dom/events/test/pointerevents/test_bug1315862.html
index 92d61a518f..657947c156 100644
--- a/dom/events/test/pointerevents/test_bug1315862.html
+++ b/dom/events/test/pointerevents/test_bug1315862.html
@@ -36,10 +36,10 @@ function runTests() {
let target = iframe.contentDocument.body.firstChild;
allPointerEvents.forEach((event, idx, arr) => {
- SpecialPowers.addSystemEventListener(target, event, () => {
+ SpecialPowers.wrap(target).addEventListener(event, () => {
ok(false, "Shouldn't dispatch " + event + " in the system group");
receivePointerEvents = true;
- });
+ }, { mozSystemGroup: true });
});
target.addEventListener("pointerdown", (e) => {
target.setPointerCapture(e.pointerId);
diff --git a/dom/events/test/test_accesskey.html b/dom/events/test/test_accesskey.html
index cdfff54a28..4d382f2270 100644
--- a/dom/events/test/test_accesskey.html
+++ b/dom/events/test/test_accesskey.html
@@ -143,7 +143,7 @@ add_task(async function modifyAccessKey() {
add_task(async function file_picker() {
const file = document.getElementById("file");
const MockFilePicker = SpecialPowers.MockFilePicker;
- MockFilePicker.init(window);
+ MockFilePicker.init(SpecialPowers.wrap(window).browsingContext);
MockFilePicker.returnValue = MockFilePicker.returnCancel;
let clicked = false;
diff --git a/dom/events/test/test_bug226361.xhtml b/dom/events/test/test_bug226361.xhtml
index 143a485757..c2c19ee2a7 100644
--- a/dom/events/test/test_bug226361.xhtml
+++ b/dom/events/test/test_bug226361.xhtml
@@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=226361
</p>
<div id="content" style="display: none">
-
+
</div>
<pre id="test">
<script type="application/javascript">
@@ -43,8 +43,11 @@ function tab_to(id) {
}
function tab_iframe() {
- doc = document;
- tab_to('iframe');
+ let canTabMoveFocusToRootElement = !SpecialPowers.getBoolPref("dom.disable_tab_focus_to_root_element");
+ if (canTabMoveFocusToRootElement) {
+ doc = document;
+ tab_to('iframe');
+ }
// inside iframe
doc = document.getElementById('iframe').contentDocument
diff --git a/dom/events/test/test_bug238987.html b/dom/events/test/test_bug238987.html
index b2712a25d0..34f870eeac 100644
--- a/dom/events/test/test_bug238987.html
+++ b/dom/events/test/test_bug238987.html
@@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
var shouldStop = false;
var activateShift = false;
- var expectedResult = "i1,i2,i3,i4,i5,i6,i7,i8,number,i9,i10,i11,i12";
+ var expectedResult = "i1,i2,i3,i4,i5,i7,i8,number,i9,i10,i11,i12";
var forwardFocusArray = expectedResult.split(",");
var backwardFocusArray = expectedResult.split(",");
var forwardBlurArray = expectedResult.split(",");
diff --git a/dom/events/test/test_bug336682.js b/dom/events/test/test_bug336682.js
index e673f1eb99..11bd7d46bb 100644
--- a/dom/events/test/test_bug336682.js
+++ b/dom/events/test/test_bug336682.js
@@ -4,6 +4,8 @@
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
+/* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */
+
var gState = 0;
/**
* After all the on/offline handlers run,
diff --git a/dom/events/test/test_bug448602.html b/dom/events/test/test_bug448602.html
index 18b4cb2d2f..452a361a52 100644
--- a/dom/events/test/test_bug448602.html
+++ b/dom/events/test/test_bug448602.html
@@ -174,28 +174,7 @@ function runTests() {
is(SpecialPowers.unwrap(infos[0].listenerObject), l,
"Should have the right listener object (4)");
- // Event target chain tests
l3 = document.getElementById("testlevel3");
- var textnode = l3.firstChild;
- var chain = els.getEventTargetChainFor(textnode, true);
- ok(chain.length > 3, "Too short event target chain.");
- ok(SpecialPowers.compare(chain[0], textnode), "Wrong chain item (1)");
- ok(SpecialPowers.compare(chain[1], l3), "Wrong chain item (2)");
- ok(SpecialPowers.compare(chain[2], l2), "Wrong chain item (3)");
- ok(SpecialPowers.compare(chain[3], root), "Wrong chain item (4)");
-
- var hasDocumentInChain = false;
- var hasWindowInChain = false;
- for (var i = 0; i < chain.length; ++i) {
- if (SpecialPowers.compare(chain[i], document)) {
- hasDocumentInChain = true;
- } else if (SpecialPowers.compare(chain[i], window)) {
- hasWindowInChain = true;
- }
- }
-
- ok(hasDocumentInChain, "Should have document in event target chain!");
- ok(hasWindowInChain, "Should have window in event target chain!");
try {
els.getListenerInfoFor(null);
diff --git a/dom/events/test/test_mouse_events_after_touchend.html b/dom/events/test/test_mouse_events_after_touchend.html
new file mode 100644
index 0000000000..146c37e489
--- /dev/null
+++ b/dom/events/test/test_mouse_events_after_touchend.html
@@ -0,0 +1,232 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Tests for mouse events after touchend</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<script src="/tests/SimpleTest/paint_listener.js"></script>
+<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
+<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<style>
+#parent, #child {
+ width: 300px;
+ height: 64px;
+ padding: 16px;
+}
+#parent {
+ background-color: black;
+}
+#child {
+ background-color: gray;
+}
+</style>
+<script>
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("Required for waiting to prevent double tap at second tap");
+SimpleTest.waitForFocus(async () => {
+ function stringifyEvent(event) {
+ return `{ type: ${event.type}, target: ${
+ event.target.id || event.target.nodeName
+ }${
+ event.detail !== undefined ? `, detail: ${event.detail}` : ""
+ }${
+ event.button !== undefined ? `, button: ${event.button}` : ""
+ }${
+ event.buttons !== undefined ? `, buttons: ${event.buttons}` : ""
+ } }`;
+ }
+ function stringifyEvents(arrayOfEvents) {
+ if (!arrayOfEvents.length) {
+ return "[]";
+ }
+ let ret = "";
+ for (const event of arrayOfEvents) {
+ if (ret === "") {
+ ret = "[ ";
+ } else {
+ ret += ", ";
+ }
+ ret += stringifyEvent(event);
+ }
+ return ret + " ]";
+ }
+
+ let events = [];
+ for (const type of ["mousemove",
+ "mousedown",
+ "mouseup",
+ "click",
+ "dblclick",
+ "contextmenu",
+ "touchend"]) {
+ if (type == "touchend") {
+ addEventListener(type, event => {
+ info(`Received: ${stringifyEvent(event)}`);
+ events.push({type, target: event.target});
+ }, {capture: true});
+ } else {
+ addEventListener(type, event => {
+ info(`Received: ${stringifyEvent(event)}`);
+ events.push({
+ type: event.type,
+ target: event.target,
+ detail: event.detail,
+ button: event.button,
+ buttons: event.buttons,
+ });
+ }, {capture: true});
+ }
+ }
+
+ function shiftEventsBefore(arrayOfEvents, aType) {
+ const index = arrayOfEvents.findIndex(event => event.type == aType);
+ if (index <= 0) {
+ return [];
+ }
+ let ret = [];
+ for (let i = 0; i < index; i++) {
+ ret.push(arrayOfEvents.shift());
+ }
+ return ret;
+ }
+
+ const parent = document.getElementById("parent");
+ const child = document.getElementById("child");
+
+ function promiseEvent(aType) {
+ return new Promise(resolve =>
+ addEventListener(aType, resolve, {once: true})
+ );
+ }
+
+ async function promiseFlushingAPZGestureState() {
+ await promiseApzFlushedRepaints();
+ // Wait for a while to avoid that the next tap will be treated as 2nd tap of
+ // a double tap.
+ return new Promise(
+ resolve => setTimeout(
+ resolve,
+ // NOTE: x1.0 is not enough to avoid intermittent failures.
+ SpecialPowers.getIntPref("apz.max_tap_time") * 1.2
+ )
+ );
+ }
+
+ await waitUntilApzStable();
+ for (const prefValue of [true, false]) {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["test.events.async.enabled", prefValue],
+ ["ui.click_hold_context_menus.delay", 15000], // disable long tap
+ ]
+ });
+ const desc = `(test.events.async.enabled=${prefValue})`;
+
+ await (async function test_single_tap() {
+ await promiseFlushingAPZGestureState();
+ info("test_single_tap: testing...");
+ events = [];
+ const waitForClick = promiseEvent("click");
+ synthesizeTouch(child, 5, 5);
+ await waitForClick;
+ is(
+ stringifyEvents(events),
+ stringifyEvents([
+ { type: "touchend", target: child },
+ { type: "mousemove", target: child, detail: 0, button: 0, buttons: 0 },
+ { type: "mousedown", target: child, detail: 1, button: 0, buttons: 1 },
+ { type: "mouseup", target: child, detail: 1, button: 0, buttons: 0 },
+ { type: "click", target: child, detail: 1, button: 0, buttons: 0 },
+ ]),
+ `Single tap should cause a click ${desc}`
+ );
+ })();
+
+ await (async function test_single_tap_with_consuming_touchstart() {
+ await promiseFlushingAPZGestureState();
+ info("test_single_tap_with_consuming_touchstart: testing...");
+ events = [];
+ const waitForTouchEnd = promiseEvent("touchend");
+ child.addEventListener("touchstart", event => {
+ event.preventDefault();
+ }, {once: true});
+ synthesizeTouch(child, 5, 5);
+ await waitForTouchEnd;
+ const result = stringifyEvents(events);
+ const expected = stringifyEvents([{ type: "touchend", target: child }]);
+ // If testing this with APZ, the result is really unstable. Let's allow to
+ // fail for now.
+ (prefValue && result != expected ? todo_is : is)(
+ result,
+ expected,
+ `Single tap should not cause mouse events if touchstart is consumed ${desc}`
+ );
+ })();
+
+
+ await (async function test_single_tap_with_consuming_touchend() {
+ await promiseFlushingAPZGestureState();
+ info("test_single_tap_with_consuming_touchend: testing...");
+ events = [];
+ const waitForTouchEnd = promiseEvent("touchend");
+ child.addEventListener("touchend", event => {
+ event.preventDefault();
+ }, {once: true});
+ synthesizeTouch(child, 5, 5);
+ await waitForTouchEnd;
+ is(
+ stringifyEvents(shiftEventsBefore(events)),
+ stringifyEvents([]),
+ `test_single_tap_with_consuming_touchstart() shouldn't cause mouse events after touchend`
+ )
+ is(
+ stringifyEvents(events),
+ stringifyEvents([
+ { type: "touchend", target: child },
+ ]),
+ `Single tap should not cause mouse events if touchend is consumed ${desc}`
+ );
+ })();
+
+ await (async function test_multi_touch() {
+ await promiseFlushingAPZGestureState();
+ events = [];
+ info("test_multi_touch: testing...");
+ const waitForTouchEnd = new Promise(resolve => {
+ let count = 0;
+ function onTouchEnd(event) {
+ if (++count == 2) {
+ removeEventListener("touchend", onTouchEnd, {capture: true});
+ requestAnimationFrame(() => requestAnimationFrame(resolve));
+ }
+ }
+ addEventListener("touchend", onTouchEnd, {capture: true});
+ });
+ synthesizeTouch(child, [5, 25], 5);
+ await waitForTouchEnd;
+ is(
+ stringifyEvents(shiftEventsBefore(events)),
+ stringifyEvents([]),
+ `test_single_tap_with_consuming_touchend() shouldn't cause mouse events after touchend`
+ )
+ is(
+ stringifyEvents(events),
+ stringifyEvents([
+ { type: "touchend", target: child },
+ { type: "touchend", target: child },
+ ]),
+ `Multiple touch should not cause mouse events ${desc}`
+ );
+ })();
+ }
+ SimpleTest.finish();
+});
+</script>
+</head>
+<body><div id="parent"><div id="child"></div></div></body>
+</html>
diff --git a/dom/events/test/test_use_split_keypress_event_model_on_old_Confluence.html b/dom/events/test/test_use_split_keypress_event_model_on_old_Confluence.html
index 3898584b0a..43d8081606 100644
--- a/dom/events/test/test_use_split_keypress_event_model_on_old_Confluence.html
+++ b/dom/events/test/test_use_split_keypress_event_model_on_old_Confluence.html
@@ -39,7 +39,7 @@ SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(async function doTests() {
let iframe = document.getElementById("iframe");
let waitForCheckKeyPressEventModelEvent = new Promise(resolve => {
- SpecialPowers.addSystemEventListener(iframe.contentDocument, "CheckKeyPressEventModel", resolve, {once: true});
+ SpecialPowers.wrap(iframe.contentDocument).addEventListener("CheckKeyPressEventModel", resolve, {mozSystemGroup: true, once: true});
});
iframe.contentDocument.body.setAttribute("contenteditable", "true");
await waitForCheckKeyPressEventModelEvent;
diff --git a/dom/events/test/test_use_split_keypress_event_model_on_old_Office_Online_Server.html b/dom/events/test/test_use_split_keypress_event_model_on_old_Office_Online_Server.html
index 68f52be41d..02047fef90 100644
--- a/dom/events/test/test_use_split_keypress_event_model_on_old_Office_Online_Server.html
+++ b/dom/events/test/test_use_split_keypress_event_model_on_old_Office_Online_Server.html
@@ -23,7 +23,7 @@ function srcdocLoaded() {
waitForCheckKeyPressEventModelEvent = new Promise(resolve => {
dump(document.querySelector("iframe").contentDocument.location + "\n");
var doc = document.querySelector("iframe").contentDocument;
- SpecialPowers.addSystemEventListener(doc, "CheckKeyPressEventModel", resolve, {once: true});
+ SpecialPowers.wrap(doc).addEventListener("CheckKeyPressEventModel", resolve, {mozSystemGroup: true, once: true});
doc.getElementById("WACViewPanel_EditingElement").contentEditable = "true";
});
}