tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_resizers_resizing_elements.html (14177B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test for resizers of some elements</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <script src="/tests/SimpleTest/EventUtils.js"></script>
      7  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
      8  <style>
      9  #target {
     10    background-color: green;
     11  }
     12  </style>
     13 </head>
     14 <body>
     15 <p id="display"></p>
     16 <div id="content" contenteditable style="width: 200px; height: 200px;"></div>
     17 <div id="clickaway" style="width: 10px; height: 10px"></div>
     18 <img src="green.png"><!-- for ensuring to load the image at first test of <img> case -->
     19 <pre id="test">
     20 <script type="application/javascript">
     21 "use strict";
     22 
     23 SimpleTest.waitForExplicitFinish();
     24 SimpleTest.waitForFocus(async () => {
     25  document.execCommand("enableObjectResizing", false, true);
     26  ok(document.queryCommandState("enableObjectResizing"),
     27     "Object resizer should be enabled by the call of execCommand");
     28  // Disable inline-table-editing UI for this test.
     29  document.execCommand("enableInlineTableEditing", false, false);
     30 
     31  let outOfEditor = document.getElementById("clickaway");
     32 
     33  function cancel(e) { e.stopPropagation(); }
     34  let content = document.getElementById("content");
     35  content.addEventListener("mousedown", cancel);
     36  content.addEventListener("mousemove", cancel);
     37  content.addEventListener("mouseup", cancel);
     38 
     39  async function waitForSelectionChange() {
     40    return new Promise(resolve => {
     41      document.addEventListener("selectionchange", () => {
     42        resolve();
     43      }, {once: true});
     44    });
     45  }
     46 
     47  async function doTest(aDescription, aPreserveRatio, aInnerHTML) {
     48    let description = aDescription;
     49    if (document.queryCommandState("enableAbsolutePositionEditing")) {
     50      description += " (absolute position editor is enabled)";
     51    }
     52    description += ": ";
     53    content.innerHTML = aInnerHTML;
     54    let target = document.getElementById("target");
     55 
     56    /**
     57     * This function is a generic resizer test.
     58     * We have 8 resizers that we'd like to test, and each can be moved in 8 different directions.
     59     * In specifying baseX, W can be considered to be the width of the image, and for baseY, H
     60     * can be considered to be the height of the image. deltaX and deltaY are regular pixel values
     61     * which can be positive or negative.
     62     * TODO: Should test canceling "beforeinput" events case.
     63     */
     64    const W = 1;
     65    const H = 1;
     66    async function testResizer(baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY) {
     67      ok(true, description + "testResizer(" + [baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY].join(", ") + ")");
     68 
     69      // Reset the dimensions of the target.
     70      target.style.width = "150px";
     71      target.style.height = "150px";
     72      let rect = target.getBoundingClientRect();
     73      is(rect.width, 150, description + "Sanity check the width");
     74      is(rect.height, 150, description + "Sanity check the height");
     75 
     76      // Click on the target to show the resizers
     77      ok(true, "waiting selectionchange to select the target element");
     78      let promiseSelectionChangeEvent = waitForSelectionChange();
     79      synthesizeMouseAtCenter(target, {});
     80      await promiseSelectionChangeEvent;
     81 
     82      // Determine which resizer we're dealing with.
     83      let basePosX = rect.width * baseX;
     84      let basePosY = rect.height * baseY;
     85 
     86      let inputEventExpected = true;
     87      function onInput(aEvent) {
     88        if (!inputEventExpected) {
     89          ok(false, `"${aEvent.type}" event shouldn't be fired after stopping resizing`);
     90          return;
     91        }
     92        ok(aEvent instanceof InputEvent,
     93           `"${aEvent.type}" event should be dispatched with InputEvent interface`);
     94        is(aEvent.cancelable, false,
     95           `"${aEvent.type}" event should be never cancelable`);
     96        is(aEvent.bubbles, true,
     97           `"${aEvent.type}" event should always bubble`);
     98        is(aEvent.inputType, "",
     99           `inputType of "${aEvent.type}" event should be empty string when an element is resized`);
    100        is(aEvent.data, null,
    101           `data of "${aEvent.type}" event should be null ${aDescription}`);
    102        is(aEvent.dataTransfer, null,
    103           `data of "${aEvent.type}" event should be null ${aDescription}`);
    104        let targetRanges = aEvent.getTargetRanges();
    105        if (aEvent.type === "beforeinput") {
    106          let selection = document.getSelection();
    107          is(targetRanges.length, selection.rangeCount,
    108             `getTargetRanges() of "beforeinput" event for position changing of absolute position should return selection ranges ${aDescription}`);
    109          if (targetRanges.length === selection.rangeCount) {
    110            for (let i = 0; i < selection.rangeCount; i++) {
    111              let range = selection.getRangeAt(i);
    112              is(targetRanges[i].startContainer, range.startContainer,
    113                 `startContainer of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`);
    114              is(targetRanges[i].startOffset, range.startOffset,
    115                 `startOffset of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`);
    116              is(targetRanges[i].endContainer, range.endContainer,
    117                 `endContainer of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`);
    118              is(targetRanges[i].endOffset, range.endOffset,
    119                 `endOffset of getTargetRanges()[${i}] of "beforeinput" event for position changing of absolute position does not match ${aDescription}`);
    120            }
    121          }
    122        } else {
    123          is(targetRanges.length, 0,
    124             `getTargetRanges() of "${aEvent.type}" event for position changing of absolute position should return empty array ${aDescription}`);
    125        }
    126      }
    127 
    128      content.addEventListener("beforeinput", onInput);
    129      content.addEventListener("input", onInput);
    130 
    131      // Click on the correct resizer
    132      synthesizeMouse(target, basePosX, basePosY, {type: "mousedown"});
    133      // Drag it delta pixels to the right and bottom (or maybe left and top!)
    134      synthesizeMouse(target, basePosX + deltaX, basePosY + deltaY, {type: "mousemove"});
    135      // Release the mouse button
    136      synthesizeMouse(target, basePosX + deltaX, basePosY + deltaY, {type: "mouseup"});
    137 
    138      inputEventExpected = false;
    139 
    140      // Move the mouse delta more pixels to the same direction to make sure that the
    141      // resize operation has stopped.
    142      synthesizeMouse(target, basePosX + deltaX * 2, basePosY + deltaY * 2, {type: "mousemove"});
    143 
    144      // Click outside of the editor to hide the resizers
    145      ok(true, "waiting selectionchange to select outside the target element");
    146      let promiseSelectionExitEvent = waitForSelectionChange();
    147      synthesizeMouseAtCenter(outOfEditor, {});
    148      await promiseSelectionExitEvent;
    149 
    150      // Get the new dimensions for the target
    151      // XXX I don't know why we need 2px margin to check this on Android.
    152      //     Fortunately, this test checks whether objects are resizable
    153      //     actually.  So, bigger difference is okay.
    154      let newRect = target.getBoundingClientRect();
    155      isfuzzy(newRect.width, rect.width + expectedDeltaX, 2, description + "The width should be increased by " + expectedDeltaX + " pixels");
    156      isfuzzy(newRect.height, rect.height + expectedDeltaY, 2, description + "The height should be increased by " + expectedDeltaY + "pixels");
    157 
    158      content.removeEventListener("beforeinput", onInput);
    159      content.removeEventListener("input", onInput);
    160    }
    161 
    162    // Account for changes in the resizing behavior when we're trying to preserve
    163    // the aspect ration of image.
    164    // ignoredGrowth means we don't change the size of a dimension because otherwise
    165    // the aspect ratio would change undesirably.
    166    // needlessGrowth means that we change the size of a dimension perpendecular to
    167    // the mouse movement axis in order to preserve the aspect ratio.
    168    // reversedGrowth means that we change the size of a dimension in the opposite
    169    // direction to the mouse movement in order to maintain the aspect ratio.
    170    const ignoredGrowth = aPreserveRatio ? 0 : 1;
    171    const needlessGrowth = aPreserveRatio ? 1 : 0;
    172    const reversedGrowth = aPreserveRatio ? -1 : 1;
    173 
    174    /* eslint-disable no-multi-spaces */
    175 
    176    // top resizer
    177    await testResizer(W / 2,   0, -10, -10,   0,  10);
    178    await testResizer(W / 2,   0, -10,   0,   0,   0);
    179    await testResizer(W / 2,   0, -10,  10,   0, -10);
    180    await testResizer(W / 2,   0,   0, -10,   0,  10);
    181    await testResizer(W / 2,   0,   0,   0,   0,   0);
    182    await testResizer(W / 2,   0,   0,  10,   0, -10);
    183    await testResizer(W / 2,   0,  10, -10,   0,  10);
    184    await testResizer(W / 2,   0,  10,   0,   0,   0);
    185    await testResizer(W / 2,   0,  10,  10,   0, -10);
    186 
    187    // top right resizer
    188    await testResizer(  W,   0, -10, -10, -10 * reversedGrowth, 10);
    189    await testResizer(  W,   0, -10,   0, -10 * ignoredGrowth,   0);
    190    await testResizer(  W,   0, -10,  10, -10, -10);
    191    await testResizer(  W,   0,   0, -10,  10 * needlessGrowth,  10);
    192    await testResizer(  W,   0,   0,   0,   0,   0);
    193    await testResizer(  W,   0,   0,  10,   0, -10 * ignoredGrowth);
    194    await testResizer(  W,   0,  10, -10,  10,  10);
    195    await testResizer(  W,   0,  10,   0,  10,  10 * needlessGrowth);
    196    await testResizer(  W,   0,  10,  10,  10, -10 * reversedGrowth);
    197 
    198    // right resizer
    199    await testResizer(  W, H / 2, -10, -10, -10,   0);
    200    await testResizer(  W, H / 2, -10,   0, -10,   0);
    201    await testResizer(  W, H / 2, -10,  10, -10,   0);
    202    await testResizer(  W, H / 2,   0, -10,   0,   0);
    203    await testResizer(  W, H / 2,   0,   0,   0,   0);
    204    await testResizer(  W, H / 2,   0,  10,   0,   0);
    205    await testResizer(  W, H / 2,  10, -10,  10,   0);
    206    await testResizer(  W, H / 2,  10,   0,  10,   0);
    207    await testResizer(  W, H / 2,  10,  10,  10,   0);
    208 
    209    // bottom right resizer
    210    await testResizer(  W,   H, -10, -10, -10, -10);
    211    await testResizer(  W,   H, -10,   0, -10 * ignoredGrowth,   0);
    212    await testResizer(  W,   H, -10,  10, -10 * reversedGrowth,  10);
    213    await testResizer(  W,   H,   0, -10,   0, -10 * ignoredGrowth);
    214    await testResizer(  W,   H,   0,   0,   0,   0);
    215    await testResizer(  W,   H,   0,  10,  10 * needlessGrowth,  10);
    216    await testResizer(  W,   H,  10, -10,  10, -10 * reversedGrowth);
    217    await testResizer(  W,   H,  10,   0,  10,  10 * needlessGrowth);
    218    await testResizer(  W,   H,  10,  10,  10,  10);
    219 
    220    // bottom resizer
    221    await testResizer(W / 2,   H, -10, -10,   0, -10);
    222    await testResizer(W / 2,   H, -10,   0,   0,   0);
    223    await testResizer(W / 2,   H, -10,  10,   0,  10);
    224    await testResizer(W / 2,   H,   0, -10,   0, -10);
    225    await testResizer(W / 2,   H,   0,   0,   0,   0);
    226    await testResizer(W / 2,   H,   0,  10,   0,  10);
    227    await testResizer(W / 2,   H,  10, -10,   0, -10);
    228    await testResizer(W / 2,   H,  10,   0,   0,   0);
    229    await testResizer(W / 2,   H,  10,  10,   0,  10);
    230 
    231    // bottom left resizer
    232    await testResizer(  0,   H, -10, -10,  10, -10 * reversedGrowth);
    233    await testResizer(  0,   H, -10,   0,  10,  10 * needlessGrowth);
    234    await testResizer(  0,   H, -10,  10,  10,  10);
    235    await testResizer(  0,   H,   0, -10,   0, -10 * ignoredGrowth);
    236    await testResizer(  0,   H,   0,   0,   0,   0);
    237    await testResizer(  0,   H,   0,  10,  10 * needlessGrowth,  10);
    238    await testResizer(  0,   H,  10, -10, -10, -10);
    239    await testResizer(  0,   H,  10,   0, -10 * ignoredGrowth,   0);
    240    await testResizer(  0,   H,  10,  10, -10 * reversedGrowth,  10);
    241 
    242    // left resizer
    243    await testResizer(  0, H / 2, -10, -10,  10,   0);
    244    await testResizer(  0, H / 2, -10,   0,  10,   0);
    245    await testResizer(  0, H / 2, -10,  10,  10,   0);
    246    await testResizer(  0, H / 2,   0, -10,   0,   0);
    247    await testResizer(  0, H / 2,   0,   0,   0,   0);
    248    await testResizer(  0, H / 2,   0,  10,   0,   0);
    249    await testResizer(  0, H / 2,  10, -10, -10,   0);
    250    await testResizer(  0, H / 2,  10,   0, -10,   0);
    251    await testResizer(  0, H / 2,  10,  10, -10,   0);
    252 
    253    // top left resizer
    254    await testResizer(  0,   0, -10, -10,  10,  10);
    255    await testResizer(  0,   0, -10,   0,  10,  10 * needlessGrowth);
    256    await testResizer(  0,   0, -10,  10,  10, -10 * reversedGrowth);
    257    await testResizer(  0,   0,   0, -10,  10 * needlessGrowth,  10);
    258    await testResizer(  0,   0,   0,   0,   0,   0);
    259    await testResizer(  0,   0,   0,  10,   0, -10 * ignoredGrowth);
    260    await testResizer(  0,   0,  10, -10, -10 * reversedGrowth,  10);
    261    await testResizer(  0,   0,  10,   0, -10 * ignoredGrowth,   0);
    262    await testResizer(  0,   0,  10,  10, -10, -10);
    263 
    264    /* eslint-enable no-multi-spaces */
    265  }
    266 
    267  const kTests = [
    268    { description: "Resizers for <img>",
    269      innerHTML: "<img id=\"target\" src=\"green.png\">",
    270      mayPreserveRatio: true,
    271      isAbsolutePosition: false,
    272    },
    273    { description: "Resizers for <table>",
    274      innerHTML: "<table id=\"target\" border><tr><td>cell</td><td>cell</td></tr></table>",
    275      mayPreserveRatio: false,
    276      isAbsolutePosition: false,
    277    },
    278    { description: "Resizers for absolute positioned <div>",
    279      innerHTML: "<div id=\"target\" style=\"position: absolute; top: 50px; left: 50px;\">positioned</div>",
    280      mayPreserveRatio: false,
    281      isAbsolutePosition: true,
    282    },
    283  ];
    284 
    285  // Resizers for absolute positioned element and table element are available
    286  // only when enableAbsolutePositionEditing or enableInlineTableEditing is
    287  // enabled for each.  So, let's enable them during testing resizers for
    288  // absolute positioned elements or table elements.
    289  for (const kTest of kTests) {
    290    document.execCommand("enableAbsolutePositionEditing", false, kTest.isAbsolutePosition);
    291    await doTest(kTest.description, kTest.mayPreserveRatio, kTest.innerHTML);
    292  }
    293  content.innerHTML = "";
    294  SimpleTest.finish();
    295 });
    296 </script>
    297 </pre>
    298 </body>
    299 </html>