diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /layout/generic/test/test_selection_changes_with_middle_mouse_button.html | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/generic/test/test_selection_changes_with_middle_mouse_button.html')
-rw-r--r-- | layout/generic/test/test_selection_changes_with_middle_mouse_button.html | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/layout/generic/test/test_selection_changes_with_middle_mouse_button.html b/layout/generic/test/test_selection_changes_with_middle_mouse_button.html new file mode 100644 index 0000000000..5499b6a825 --- /dev/null +++ b/layout/generic/test/test_selection_changes_with_middle_mouse_button.html @@ -0,0 +1,335 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test for selection changes with middle mouse button</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <style> + span, td { + white-space: nowrap; + } + </style> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none;"> + +</div> + +<textarea id="textarea" cols="1" rows="1">copied to clipboard</textarea> + +<div id="container"> +<span id="span1">first span.</span> +<span id="span2">second span.</span><br> +<a id="link" href="#top">link.</a> +<table> +<tr><td id="td1">first td.</td></tr> +<tr><td id="td2">second td.</td></tr> +</table> +</div> + +<pre id="test"> + +<script class="testbody" type="application/javascript"> +SimpleTest.waitForExplicitFinish(); + +const kIsMac = navigator.platform.includes("Mac"); +const selection = getSelection(); + +async function doTests(aEnableMiddlePaste, aEditable, aDescription) { + await SpecialPowers.pushPrefEnv({"set": [ + ["middlemouse.paste", aEnableMiddlePaste], + ["middlemouse.contentLoadURL", false], + ["general.autoScroll", false], + ["general.autoscroll.prevent_to_collapse_selection_by_middle_mouse_down", false], + ]}); + + if (aEditable) { + document.getElementById("container").setAttribute("contenteditable", "true"); + } else { + document.getElementById("container").removeAttribute("contenteditable"); + } + + let pasteEvents = []; + function pasteEventHandler(event) { + pasteEvents.push(event); + event.preventDefault(); + } + document.getElementById("container").addEventListener("paste", pasteEventHandler, true); + + // We need to behave as same as Chromium as far as possible. + // - middle mouse button down should be collapse selection at the point. + // - middle mouse button down can expand only with mouse button down with Shift key. + // - middle mouse button shouldn't select table cells. + + function doTest(aMouseDown, aMouseUp, + aExpectedSelectionAnchor, aExpectedSelectionFocus, aExpectedPastEventTarget, + aAdditionalDescription) { + pasteEvents = []; + synthesizeMouseAtCenter(aMouseDown.target, + { + button: 1, + type: "mousedown", + shiftKey: aMouseDown.shiftKey, + ctrlKey: aMouseDown.ctrlKey && !kIsMac, + metaKey: aMouseDown.ctrlKey && kIsMac, + }); + if (aExpectedSelectionAnchor === aExpectedSelectionFocus) { + ok(selection.isCollapsed, + aDescription + aAdditionalDescription + "Selection should be collapsed at mousedown"); + is(selection.focusNode, aExpectedSelectionFocus, + aDescription + aAdditionalDescription + "Selection should be collapsed in the node at mousedown"); + } else { + is(selection.anchorNode, aExpectedSelectionAnchor, + aDescription + aAdditionalDescription + "Anchor node of Selection should be previous anchor node"); + is(selection.focusNode, aExpectedSelectionFocus, + aDescription + aAdditionalDescription + "Focus node of Selection should be the node at mousedown"); + } + is(pasteEvents.length, 0, + aDescription + aAdditionalDescription + "paste event shouldn't be fired when middle mouse button down"); + + if (aMouseDown.target != aMouseUp.target) { + synthesizeMouseAtCenter(aMouseUp.target, {type: "mousemove"}); + } + synthesizeMouseAtCenter(aMouseUp.target, + { + button: 1, + type: "mouseup", + shiftKey: aMouseUp.shiftKey, + ctrlKey: aMouseUp.ctrlKey && !kIsMac, + metaKey: aMouseUp.ctrlKey && kIsMac, + }); + is(selection.anchorNode, aExpectedSelectionAnchor, + aDescription + aAdditionalDescription + "Anchor node of Selection shouldn't be modified at mouseup"); + is(selection.focusNode, aExpectedSelectionFocus, + aDescription + aAdditionalDescription + "Focus node of Selection shouldn't be modified at mouseup"); + if (aEnableMiddlePaste) { + if (aExpectedPastEventTarget === null) { + is(pasteEvents.length, 0, + aDescription + aAdditionalDescription + "paste event shouldn't be fired even when middle mouse button up"); + } else { + is(pasteEvents.length, 1, + aDescription + aAdditionalDescription + "paste event should be fired only once at mouse up"); + is(pasteEvents[0]?.target, aExpectedPastEventTarget, + aDescription + aAdditionalDescription + "paste event should be fired on start of selection"); + } + } else { + is(pasteEvents.length, 0, + aDescription + aAdditionalDescription + "paste event shouldn't be fired when middle mouse button up when middle mouse paste is disabled"); + } + } + + let span1 = document.getElementById("span1"); + let span2 = document.getElementById("span2"); + let link = document.getElementById("link"); + + selection.removeAllRanges(); + doTest({target: span1}, {target: span1}, + span1.firstChild, span1.firstChild, span1, + "Clicking span1 when there is no selection: "); + doTest({target: span2}, {target: span2}, + span2.firstChild, span2.firstChild, span2, + "Clicking span2 when selection is collapsed in span1: "); + doTest({target: span1}, {target: span2}, + span1.firstChild, span1.firstChild, span1, + "Dragging from span1 to span2: "); + doTest({target: span2}, {target: span1}, + span2.firstChild, span2.firstChild, span2, + "Dragging from span2 to span1: "); + doTest({target: span1, shiftKey: true}, {target: span1, shiftKey: true}, + span2.firstChild, span1.firstChild, span1, + "Expanding selection with Shift key from span2 to span1: "); + selection.collapse(span1.firstChild, 3); + if (aEditable) { + // Collapse link into editable link. + doTest({target: link, shiftKey: true}, {target: link, shiftKey: true}, + link.firstChild, link.firstChild, + link /* TODO: Perhaps, the "paste" event target should be the link */, + "Clicking an editable link with middle-button with Shift key when selection is collapsed in span1: "); + } else { + // Don't extend selection into a link. + link.onauxclick = event => event.preventDefault(); + doTest({target: link, shiftKey: true}, {target: link, shiftKey: true}, + span1.firstChild, span1.firstChild, + null /* due to the call of preventDefault */, + "Clicking a link with middle-button with Shift key when selection is collapsed in span1: "); + link.onauxclick = null; + } + // "paste" event should be fired in the "start" of selection. + selection.collapse(span1.firstChild, 3); + doTest({target: span2, shiftKey: true}, {target: span2, shiftKey: true}, + span1.firstChild, span2.firstChild, span1, + "Expanding selection with Shift key from span1 to span2: "); + // XXX This case is different from Chrome for Linux. + // In this case, Chrome does not collapse Selection at mousedown, + // but collapse at click. So, if mouseup occurs different element, + // Selection isn't modified. + selection.selectAllChildren(span1); + doTest({target: span1}, {target: span1}, + span1.firstChild, span1.firstChild, span1, + "Clicking span1 when span1 is selected: "); + + let td1 = document.getElementById("td1"); + let td2 = document.getElementById("td2"); + + selection.removeAllRanges(); + doTest({target: td1}, {target: td1}, + td1.firstChild, td1.firstChild, td1, + "Clicking td1 when there is no selection: "); + if (aEditable) { + // XXX In this case, we don't allow to expand selection with Shift key + // click across table cell boundary. + doTest({target: td2, shiftKey: true}, {target: td2, shiftKey: true}, + td1.firstChild, td1.firstChild, td1, + "Expanding selection with Shift key from td1 to td2: "); + } else { + doTest({target: td2, shiftKey: true}, {target: td2, shiftKey: true}, + td1.firstChild, td2.firstChild, td1, + "Expanding selection with Shift key from td1 to td2: "); + } + // Shouldn't select per table cell when the button is middle mouse button. + doTest({target: td1, ctrlKey: true}, {target: td1, ctrlKey: true}, + td1.firstChild, td1.firstChild, td1, + "Click td1 with Control key: "); + + document.getElementById("container").removeEventListener("paste", pasteEventHandler, true); +} + +async function runTestPreventingToCollapseSelectionByPrefs() { + await SpecialPowers.pushPrefEnv({"set": [ + ["middlemouse.contentLoadURL", false], + ["general.autoscroll.prevent_to_collapse_selection_by_middle_mouse_down", true], + ]}); + + // If middle click paste is disabled and autoscroll is enabled, we should + // allow users to prevent to collapse selection by middle mouse down. + await SpecialPowers.pushPrefEnv({"set": [ + ["middlemouse.paste", false], + ["general.autoScroll", true], + ]}); + + const container = document.getElementById("container"); + container.removeAttribute("contenteditable"); + container.getBoundingClientRect(); + + const span1 = container.querySelector("span#span1"); + const span2 = container.querySelector("span#span2"); + function checkSelectAllChildrenOfSpan2(description) { + is( + getSelection().focusNode, + span2, + `Selection shouldn't be collapsed by ${description} (focusNode)` + ); + is( + getSelection().focusOffset, + span2.childNodes.length, + `Selection shouldn't be collapsed by ${description} (focusOffset)` + ); + is( + getSelection().anchorNode, + span2, + `Selection shouldn't be collapsed by ${description} (anchorNode)` + ); + is( + getSelection().anchorOffset, + 0, + `Selection shouldn't be collapsed by ${description} (anchorOffset)` + ); + } + + function checkSelectionCollapsedInSpan1(description) { + ok( + getSelection().isCollapsed, + `Selection should be collapsed into the clicked text node ${description} (isCollapsed)` + ); + is( + getSelection().focusNode, + span1.firstChild, + `Selection should be collapsed into the clicked text node ${description} (focusNode)` + ); + is( + getSelection().anchorNode, + span1.firstChild, + `Selection should be collapsed into the clicked text node ${description} (anchorNode)` + ); + } + getSelection().selectAllChildren(span2); + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mousedown", button: 1 }); + checkSelectAllChildrenOfSpan2("middle mousedown if the pref is enabled and middle click paste is disabled and autoscroll are enabled"); + + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mouseup", button: 1 }); + checkSelectAllChildrenOfSpan2("middle mouseup if the pref is enabled and middle click paste is disabled and autoscroll are enabled"); + + container.setAttribute("contenteditable", "true"); + container.getBoundingClientRect(); + getSelection().selectAllChildren(span2); + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mousedown", button: 1 }); + checkSelectionCollapsedInSpan1("by middle mousedown if it's editable content"); + + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mouseup", button: 1 }); + checkSelectionCollapsedInSpan1("after middle mouseup if it's editable content"); + + container.removeAttribute("contenteditable"); + container.getBoundingClientRect(); + await SpecialPowers.pushPrefEnv({"set": [ + ["middlemouse.paste", false], + ["general.autoScroll", false], + ]}); + + getSelection().selectAllChildren(span2); + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mousedown", button: 1 }); + checkSelectionCollapsedInSpan1("by middle mousedown if the pref is enabled but autoscroll are disabled"); + + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mouseup", button: 1 }); + checkSelectionCollapsedInSpan1("after middle mousedown if the pref is enabled but autoscroll are disabled"); + + await SpecialPowers.pushPrefEnv({"set": [ + ["middlemouse.paste", true], + ["general.autoScroll", true], + ]}); + + getSelection().selectAllChildren(span2); + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mousedown", button: 1 }); + checkSelectionCollapsedInSpan1("by middle mousedown if the pref is enabled but middle mouse paste is enabled"); + + synthesizeMouseAtCenter(document.getElementById("span1"), { type: "mouseup", button: 1 }); + checkSelectionCollapsedInSpan1("after middle mousedown if the pref is enabled but middle mouse paste is enabled"); +} + +async function runAllTests() { + let textarea = document.getElementById("textarea"); + textarea.focus(); + await new Promise((resolve, reject) => { + SimpleTest.waitForClipboard(textarea.value, + () => { + synthesizeKey("a", {accelKey: true}); + synthesizeKey("c", {accelKey: true}); + }, + () => { + ok(true, `Succeeded to copy "${textarea.value}" to clipboard`); + textarea.style.display = "none"; + resolve(); + }, + () => { + ok(false, `Failed to copy "${textarea.value}" to clipboard`); + reject(); + }); + }); + + await doTests(true, false, "Testing with the middle paste enabled: "); + await doTests(false, false, "Testing with the middle paste disabled: "); + + await doTests(true, true, "Testing in editable content with the middle paste enabled: "); + await doTests(false, true, "Testing in editable content with the middle paste disabled: "); + + await runTestPreventingToCollapseSelectionByPrefs(); + + SimpleTest.finish(); +} + +SimpleTest.waitForFocus(runAllTests); +</script> +</pre> +</body> +</html> |