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 /editor/libeditor/tests/test_resizers_resizing_elements.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 '')
-rw-r--r-- | editor/libeditor/tests/test_resizers_resizing_elements.html | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/editor/libeditor/tests/test_resizers_resizing_elements.html b/editor/libeditor/tests/test_resizers_resizing_elements.html new file mode 100644 index 0000000000..f30b6bb269 --- /dev/null +++ b/editor/libeditor/tests/test_resizers_resizing_elements.html @@ -0,0 +1,299 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for resizers of some elements</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + #target { + background-color: green; + } + </style> +</head> +<body> +<p id="display"></p> +<div id="content" contenteditable style="width: 200px; height: 200px;"></div> +<div id="clickaway" style="width: 10px; height: 10px"></div> +<img src="green.png"><!-- for ensuring to load the image at first test of <img> case --> +<pre id="test"> +<script type="application/javascript"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(async () => { + document.execCommand("enableObjectResizing", false, true); + ok(document.queryCommandState("enableObjectResizing"), + "Object resizer should be enabled by the call of execCommand"); + // Disable inline-table-editing UI for this test. + document.execCommand("enableInlineTableEditing", false, false); + + let outOfEditor = document.getElementById("clickaway"); + + function cancel(e) { e.stopPropagation(); } + let content = document.getElementById("content"); + content.addEventListener("mousedown", cancel); + content.addEventListener("mousemove", cancel); + content.addEventListener("mouseup", cancel); + + async function waitForSelectionChange() { + return new Promise(resolve => { + document.addEventListener("selectionchange", () => { + resolve(); + }, {once: true}); + }); + } + + async function doTest(aDescription, aPreserveRatio, aInnerHTML) { + let description = aDescription; + if (document.queryCommandState("enableAbsolutePositionEditing")) { + description += " (absolute position editor is enabled)"; + } + description += ": "; + content.innerHTML = aInnerHTML; + let target = document.getElementById("target"); + + /** + * This function is a generic resizer test. + * We have 8 resizers that we'd like to test, and each can be moved in 8 different directions. + * In specifying baseX, W can be considered to be the width of the image, and for baseY, H + * can be considered to be the height of the image. deltaX and deltaY are regular pixel values + * which can be positive or negative. + * TODO: Should test canceling "beforeinput" events case. + */ + const W = 1; + const H = 1; + async function testResizer(baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY) { + ok(true, description + "testResizer(" + [baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY].join(", ") + ")"); + + // Reset the dimensions of the target. + target.style.width = "150px"; + target.style.height = "150px"; + let rect = target.getBoundingClientRect(); + is(rect.width, 150, description + "Sanity check the width"); + is(rect.height, 150, description + "Sanity check the height"); + + // Click on the target to show the resizers + ok(true, "waiting selectionchange to select the target element"); + let promiseSelectionChangeEvent = waitForSelectionChange(); + synthesizeMouseAtCenter(target, {}); + await promiseSelectionChangeEvent; + + // Determine which resizer we're dealing with. + let basePosX = rect.width * baseX; + let basePosY = rect.height * baseY; + + let inputEventExpected = true; + function onInput(aEvent) { + if (!inputEventExpected) { + ok(false, `"${aEvent.type}" event shouldn't be fired after stopping resizing`); + return; + } + ok(aEvent instanceof InputEvent, + `"${aEvent.type}" event should be dispatched with InputEvent interface`); + is(aEvent.cancelable, false, + `"${aEvent.type}" event should be never cancelable`); + is(aEvent.bubbles, true, + `"${aEvent.type}" event should always bubble`); + is(aEvent.inputType, "", + `inputType of "${aEvent.type}" event should be empty string when an element is resized`); + is(aEvent.data, null, + `data of "${aEvent.type}" event should be null ${aDescription}`); + is(aEvent.dataTransfer, null, + `data of "${aEvent.type}" event should be null ${aDescription}`); + let targetRanges = aEvent.getTargetRanges(); + if (aEvent.type === "beforeinput") { + let selection = document.getSelection(); + is(targetRanges.length, selection.rangeCount, + `getTargetRanges() of "beforeinput" event for position changing of absolute position should return selection ranges ${aDescription}`); + if (targetRanges.length === selection.rangeCount) { + for (let i = 0; i < selection.rangeCount; i++) { + let range = selection.getRangeAt(i); + is(targetRanges[i].startContainer, range.startContainer, + `startContainer of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`); + is(targetRanges[i].startOffset, range.startOffset, + `startOffset of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`); + is(targetRanges[i].endContainer, range.endContainer, + `endContainer of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`); + is(targetRanges[i].endOffset, range.endOffset, + `endOffset of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`); + } + } + } else { + is(targetRanges.length, 0, + `getTargetRanges() of "${aEvent.type}" event for position changing of absolute position should return empty array ${aDescription}`); + } + } + + content.addEventListener("beforeinput", onInput); + content.addEventListener("input", onInput); + + // Click on the correct resizer + synthesizeMouse(target, basePosX, basePosY, {type: "mousedown"}); + // Drag it delta pixels to the right and bottom (or maybe left and top!) + synthesizeMouse(target, basePosX + deltaX, basePosY + deltaY, {type: "mousemove"}); + // Release the mouse button + synthesizeMouse(target, basePosX + deltaX, basePosY + deltaY, {type: "mouseup"}); + + inputEventExpected = false; + + // Move the mouse delta more pixels to the same direction to make sure that the + // resize operation has stopped. + synthesizeMouse(target, basePosX + deltaX * 2, basePosY + deltaY * 2, {type: "mousemove"}); + + // Click outside of the editor to hide the resizers + ok(true, "waiting selectionchange to select outside the target element"); + let promiseSelectionExitEvent = waitForSelectionChange(); + synthesizeMouseAtCenter(outOfEditor, {}); + await promiseSelectionExitEvent; + + // Get the new dimensions for the target + // XXX I don't know why we need 2px margin to check this on Android. + // Fortunately, this test checks whether objects are resizable + // actually. So, bigger difference is okay. + let newRect = target.getBoundingClientRect(); + isfuzzy(newRect.width, rect.width + expectedDeltaX, 2, description + "The width should be increased by " + expectedDeltaX + " pixels"); + isfuzzy(newRect.height, rect.height + expectedDeltaY, 2, description + "The height should be increased by " + expectedDeltaY + "pixels"); + + content.removeEventListener("beforeinput", onInput); + content.removeEventListener("input", onInput); + } + + // Account for changes in the resizing behavior when we're trying to preserve + // the aspect ration of image. + // ignoredGrowth means we don't change the size of a dimension because otherwise + // the aspect ratio would change undesirably. + // needlessGrowth means that we change the size of a dimension perpendecular to + // the mouse movement axis in order to preserve the aspect ratio. + // reversedGrowth means that we change the size of a dimension in the opposite + // direction to the mouse movement in order to maintain the aspect ratio. + const ignoredGrowth = aPreserveRatio ? 0 : 1; + const needlessGrowth = aPreserveRatio ? 1 : 0; + const reversedGrowth = aPreserveRatio ? -1 : 1; + + /* eslint-disable no-multi-spaces */ + + // top resizer + await testResizer(W / 2, 0, -10, -10, 0, 10); + await testResizer(W / 2, 0, -10, 0, 0, 0); + await testResizer(W / 2, 0, -10, 10, 0, -10); + await testResizer(W / 2, 0, 0, -10, 0, 10); + await testResizer(W / 2, 0, 0, 0, 0, 0); + await testResizer(W / 2, 0, 0, 10, 0, -10); + await testResizer(W / 2, 0, 10, -10, 0, 10); + await testResizer(W / 2, 0, 10, 0, 0, 0); + await testResizer(W / 2, 0, 10, 10, 0, -10); + + // top right resizer + await testResizer( W, 0, -10, -10, -10 * reversedGrowth, 10); + await testResizer( W, 0, -10, 0, -10 * ignoredGrowth, 0); + await testResizer( W, 0, -10, 10, -10, -10); + await testResizer( W, 0, 0, -10, 10 * needlessGrowth, 10); + await testResizer( W, 0, 0, 0, 0, 0); + await testResizer( W, 0, 0, 10, 0, -10 * ignoredGrowth); + await testResizer( W, 0, 10, -10, 10, 10); + await testResizer( W, 0, 10, 0, 10, 10 * needlessGrowth); + await testResizer( W, 0, 10, 10, 10, -10 * reversedGrowth); + + // right resizer + await testResizer( W, H / 2, -10, -10, -10, 0); + await testResizer( W, H / 2, -10, 0, -10, 0); + await testResizer( W, H / 2, -10, 10, -10, 0); + await testResizer( W, H / 2, 0, -10, 0, 0); + await testResizer( W, H / 2, 0, 0, 0, 0); + await testResizer( W, H / 2, 0, 10, 0, 0); + await testResizer( W, H / 2, 10, -10, 10, 0); + await testResizer( W, H / 2, 10, 0, 10, 0); + await testResizer( W, H / 2, 10, 10, 10, 0); + + // bottom right resizer + await testResizer( W, H, -10, -10, -10, -10); + await testResizer( W, H, -10, 0, -10 * ignoredGrowth, 0); + await testResizer( W, H, -10, 10, -10 * reversedGrowth, 10); + await testResizer( W, H, 0, -10, 0, -10 * ignoredGrowth); + await testResizer( W, H, 0, 0, 0, 0); + await testResizer( W, H, 0, 10, 10 * needlessGrowth, 10); + await testResizer( W, H, 10, -10, 10, -10 * reversedGrowth); + await testResizer( W, H, 10, 0, 10, 10 * needlessGrowth); + await testResizer( W, H, 10, 10, 10, 10); + + // bottom resizer + await testResizer(W / 2, H, -10, -10, 0, -10); + await testResizer(W / 2, H, -10, 0, 0, 0); + await testResizer(W / 2, H, -10, 10, 0, 10); + await testResizer(W / 2, H, 0, -10, 0, -10); + await testResizer(W / 2, H, 0, 0, 0, 0); + await testResizer(W / 2, H, 0, 10, 0, 10); + await testResizer(W / 2, H, 10, -10, 0, -10); + await testResizer(W / 2, H, 10, 0, 0, 0); + await testResizer(W / 2, H, 10, 10, 0, 10); + + // bottom left resizer + await testResizer( 0, H, -10, -10, 10, -10 * reversedGrowth); + await testResizer( 0, H, -10, 0, 10, 10 * needlessGrowth); + await testResizer( 0, H, -10, 10, 10, 10); + await testResizer( 0, H, 0, -10, 0, -10 * ignoredGrowth); + await testResizer( 0, H, 0, 0, 0, 0); + await testResizer( 0, H, 0, 10, 10 * needlessGrowth, 10); + await testResizer( 0, H, 10, -10, -10, -10); + await testResizer( 0, H, 10, 0, -10 * ignoredGrowth, 0); + await testResizer( 0, H, 10, 10, -10 * reversedGrowth, 10); + + // left resizer + await testResizer( 0, H / 2, -10, -10, 10, 0); + await testResizer( 0, H / 2, -10, 0, 10, 0); + await testResizer( 0, H / 2, -10, 10, 10, 0); + await testResizer( 0, H / 2, 0, -10, 0, 0); + await testResizer( 0, H / 2, 0, 0, 0, 0); + await testResizer( 0, H / 2, 0, 10, 0, 0); + await testResizer( 0, H / 2, 10, -10, -10, 0); + await testResizer( 0, H / 2, 10, 0, -10, 0); + await testResizer( 0, H / 2, 10, 10, -10, 0); + + // top left resizer + await testResizer( 0, 0, -10, -10, 10, 10); + await testResizer( 0, 0, -10, 0, 10, 10 * needlessGrowth); + await testResizer( 0, 0, -10, 10, 10, -10 * reversedGrowth); + await testResizer( 0, 0, 0, -10, 10 * needlessGrowth, 10); + await testResizer( 0, 0, 0, 0, 0, 0); + await testResizer( 0, 0, 0, 10, 0, -10 * ignoredGrowth); + await testResizer( 0, 0, 10, -10, -10 * reversedGrowth, 10); + await testResizer( 0, 0, 10, 0, -10 * ignoredGrowth, 0); + await testResizer( 0, 0, 10, 10, -10, -10); + + /* eslint-enable no-multi-spaces */ + } + + const kTests = [ + { description: "Resizers for <img>", + innerHTML: "<img id=\"target\" src=\"green.png\">", + mayPreserveRatio: true, + isAbsolutePosition: false, + }, + { description: "Resizers for <table>", + innerHTML: "<table id=\"target\" border><tr><td>cell</td><td>cell</td></tr></table>", + mayPreserveRatio: false, + isAbsolutePosition: false, + }, + { description: "Resizers for absolute positioned <div>", + innerHTML: "<div id=\"target\" style=\"position: absolute; top: 50px; left: 50px;\">positioned</div>", + mayPreserveRatio: false, + isAbsolutePosition: true, + }, + ]; + + // Resizers for absolute positioned element and table element are available + // only when enableAbsolutePositionEditing or enableInlineTableEditing is + // enabled for each. So, let's enable them during testing resizers for + // absolute positioned elements or table elements. + for (const kTest of kTests) { + document.execCommand("enableAbsolutePositionEditing", false, kTest.isAbsolutePosition); + await doTest(kTest.description, kTest.mayPreserveRatio, kTest.innerHTML); + } + content.innerHTML = ""; + SimpleTest.finish(); +}); +</script> +</pre> +</body> +</html> |