tor-browser

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

test_moving_and_expanding_selection_per_page.html (18871B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <title>Test for expanding selection per page</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 </head>
      9 <body>
     10 
     11 <pre id="test">
     12 <script class="testbody" type="text/javascript">
     13 SimpleTest.waitForExplicitFinish();
     14 addLoadEvent(() => {
     15  open("window_empty_document.html", "_blank", "width=500,height=500");
     16 });
     17 
     18 async function doTests(aWindow) {
     19  // On macOS, there is no shortcut keys to extend selection per page.
     20  // Therefore, we need to use nsISelectionController.pageMove() instead.
     21  const kUseKeyboardEvent = !navigator.platform.includes("Mac");
     22  let selectionController = SpecialPowers.wrap(aWindow)
     23                                         .docShell
     24                                         .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
     25                                         .getInterface(SpecialPowers.Ci.nsISelectionDisplay)
     26                                         .QueryInterface(SpecialPowers.Ci.nsISelectionController);
     27  // On Windows, per-page selection to start or end expands selection to same
     28  // column of first or last line.  On the other platforms, it expands selection
     29  // to start or end of first or last line.
     30  const kSelectToStartOrEnd = !navigator.platform.includes("Win");
     31 
     32  await SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]});
     33  await SimpleTest.promiseFocus(aWindow);
     34 
     35  function getNodeDescription(aNode) {
     36    function getElementDescription(aElement) {
     37      if (aElement.getAttribute("id") !== null) {
     38        return `${aElement.tagName.toLowerCase()}#${aElement.getAttribute("id")}`;
     39      }
     40      if (aElement.tagName === "BR") {
     41        return `${getElementDescription(aElement.previousSibling)} + br`;
     42      }
     43      return aElement.tagName.toLowerCase();
     44    }
     45    switch (aNode.nodeType) {
     46      case aNode.TEXT_NODE:
     47        return `text node in ${getElementDescription(aNode.parentElement)}`;
     48      case aNode.ELEMENT_NODE:
     49        return getElementDescription(aNode);
     50      default:
     51        return "unknown node";
     52    }
     53  }
     54 
     55  function doTest(aExpandSelection) {
     56    // Note that when neither editor has focus nor in caret mode, key navigation
     57    // does not call nsISelectionController::PageMove().  Therefore, in such
     58    // cases, you need to call doPageDown() and doPageUp() with setting true
     59    // to aUseSelectionController.
     60    function doPageDown(aUseSelectionController) {
     61      if (kUseKeyboardEvent && !aUseSelectionController) {
     62        synthesizeKey("KEY_PageDown", {shiftKey: aExpandSelection}, aWindow);
     63      } else {
     64        selectionController.pageMove(true, aExpandSelection);
     65      }
     66    }
     67 
     68    function doPageUp(aUseSelectionController) {
     69      if (kUseKeyboardEvent && !aUseSelectionController) {
     70        synthesizeKey("KEY_PageUp", {shiftKey: aExpandSelection}, aWindow);
     71      } else {
     72        selectionController.pageMove(false, aExpandSelection);
     73      }
     74    }
     75 
     76    let doc = aWindow.document;
     77    let body = doc.body;
     78    let selection = doc.getSelection();
     79    let container;
     80 
     81    body.innerHTML = '<span id="s1">first line</span><br>' +
     82                     '<span id="s2">second line</span><br>' +
     83                     '<span id="s3">last line</span>';
     84    container = doc.documentElement;
     85 
     86    let description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in non-scrollable body: `;
     87    is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
     88    selection.collapse(doc.getElementById("s1").firstChild, 3);
     89    doPageDown(!aExpandSelection);
     90    is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
     91    let range = selection.getRangeAt(0);
     92    if (aExpandSelection) {
     93      is(range.startContainer, doc.getElementById("s1").firstChild,
     94         `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
     95      is(range.startOffset, 3,
     96         `${description} selection should be expanded from the first line's 3rd insertion point`);
     97    } else {
     98      ok(range.collapsed, `${description} selection should be collapsed`);
     99    }
    100    is(range.endContainer, doc.getElementById("s3").firstChild,
    101       `${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
    102    if (kSelectToStartOrEnd) {
    103      is(range.endOffset, range.endContainer.length,
    104         `${description} selection should be expanded to end of the last line`);
    105    } else {
    106      isfuzzy(range.endOffset, 3, 2,
    107              `${description} selection should be expanded to around the last line's 3rd insertion point`);
    108    }
    109 
    110    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in non-scrollable body: `;
    111    selection.collapse(doc.getElementById("s3").firstChild, 3);
    112    doPageUp(!aExpandSelection);
    113    is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
    114    range = selection.getRangeAt(0);
    115    is(range.startContainer, doc.getElementById("s1").firstChild,
    116       `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
    117    if (kSelectToStartOrEnd) {
    118      is(range.startOffset, 0,
    119         `${description} selection should be expanded to start of the first line`);
    120    } else {
    121      isfuzzy(range.startOffset, 3, 2,
    122              `${description} selection should be expanded to around the first line's 3rd insertion point`);
    123    }
    124    if (aExpandSelection) {
    125      is(range.endContainer, doc.getElementById("s3").firstChild,
    126         `${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
    127      is(range.endOffset, 3,
    128         `${description} selection should be expanded from the last line's 3rd insertion point`);
    129    } else {
    130      ok(range.collapsed, `${description} selection should be collapsed`);
    131    }
    132 
    133    body.innerHTML = '<span id="s1">first line in the body</span>' +
    134                       '<div id="d1" style="height: 2em; line-height: 1em; overflow: auto;">' +
    135                         '<span id="s2">first line</span><br>' +
    136                         '<span id="s3">second line</span><br>' +
    137                         '<span id="s4">third line</span><br>' +
    138                         '<span id="s5">last line</span>' +
    139                       "</div>" +
    140                     '<span id="s6">last line in the body</span>';
    141    container = doc.getElementById("d1");
    142 
    143    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable area in the body: `;
    144    is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
    145    selection.collapse(doc.getElementById("s2").firstChild, 3);
    146    doPageDown(!aExpandSelection);
    147    isnot(container.scrollTop, 0, description + "should be scrolled down");
    148    range = selection.getRangeAt(0);
    149    if (aExpandSelection) {
    150      is(range.startContainer, doc.getElementById("s2").firstChild,
    151         `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
    152      is(range.startOffset, 3,
    153         `${description} selection should be expanded from the first line's 3rd insertion point`);
    154    } else {
    155      ok(range.collapsed, `${description} selection should be collapsed`);
    156    }
    157    is(range.endContainer, doc.getElementById("s4").firstChild,
    158       `${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
    159    isfuzzy(range.endOffset, 3, 2,
    160            `${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
    161 
    162    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable area in the body: `;
    163    selection.collapse(doc.getElementById("s4").firstChild, 3);
    164    let previousScrollTop = container.scrollTop;
    165    doPageUp(!aExpandSelection);
    166    ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
    167    range = selection.getRangeAt(0);
    168    is(range.startContainer, doc.getElementById("s2").firstChild,
    169       `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
    170    isfuzzy(range.startOffset, 3, 2,
    171            `${description} selection should be expanded to around the first line's 3rd insertion point`);
    172    if (aExpandSelection) {
    173      is(range.endContainer, doc.getElementById("s4").firstChild,
    174         `${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
    175      is(range.endOffset, 3,
    176         `${description} selection should be expanded from the 3rd line's 3rd insertion point`);
    177    } else {
    178      ok(range.collapsed, `${description} selection should be collapsed`);
    179    }
    180 
    181    body.innerHTML = '<span id="s1">first line in the body</span>' +
    182                       '<div id="d1" contenteditable style="height: 2em; line-height: 1em; overflow: auto;">' +
    183                         '<span id="s2">first line</span><br>' +
    184                         '<span id="s3">second line</span><br>' +
    185                         '<span id="s4">third line</span><br>' +
    186                         '<span id="s5">last line</span>' +
    187                       "</div>" +
    188                     '<span id="s6">last line in the body</span>';
    189    container = doc.getElementById("d1");
    190 
    191    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable editable div in the body: `;
    192    is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
    193    selection.collapse(doc.getElementById("s2").firstChild, 3);
    194    doPageDown();
    195    isnot(container.scrollTop, 0, description + "should be scrolled down");
    196    range = selection.getRangeAt(0);
    197    if (aExpandSelection) {
    198      is(range.startContainer, doc.getElementById("s2").firstChild,
    199         `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
    200      is(range.startOffset, 3,
    201         `${description} selection should be expanded from the first line's 3rd insertion point`);
    202    } else {
    203      ok(range.collapsed, `${description} selection should be collapsed`);
    204    }
    205    is(range.endContainer, doc.getElementById("s4").firstChild,
    206       `${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
    207    isfuzzy(range.endOffset, 3, 2,
    208            `${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
    209 
    210    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable editable div in the body: `;
    211    selection.collapse(doc.getElementById("s4").firstChild, 3);
    212    previousScrollTop = container.scrollTop;
    213    doPageUp();
    214    ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
    215    range = selection.getRangeAt(0);
    216    is(range.startContainer, doc.getElementById("s2").firstChild,
    217       `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
    218    isfuzzy(range.startOffset, 3, 2,
    219            `${description} selection should be expanded to around the first line's 3rd insertion point`);
    220    if (aExpandSelection) {
    221      is(range.endContainer, doc.getElementById("s4").firstChild,
    222         `${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
    223      is(range.endOffset, 3,
    224         `${description} selection should be expanded from the 3rd line's 3rd insertion point`);
    225    } else {
    226      ok(range.collapsed, `${description} selection should be collapsed`);
    227    }
    228 
    229    body.innerHTML = '<span id="s1">first line in the body</span>' +
    230                       '<div id="d1" contenteditable>' +
    231                         '<span id="s2">first line</span><br>' +
    232                         '<span id="s3">second line</span><br>' +
    233                         '<span id="s4">third line</span><br>' +
    234                         '<span id="s5">last line</span>' +
    235                       "</div>" +
    236                     '<span id="s6">last line in the body</span>';
    237    container = doc.getElementById("d1");
    238 
    239    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in non-scrollable editable div in the body: `;
    240    is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
    241    selection.collapse(doc.getElementById("s2").firstChild, 3);
    242    doPageDown();
    243    is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
    244    range = selection.getRangeAt(0);
    245    if (aExpandSelection) {
    246      is(range.startContainer, doc.getElementById("s2").firstChild,
    247         `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
    248      is(range.startOffset, 3,
    249         `${description} selection should be expanded from the first line's 3rd insertion point`);
    250    } else {
    251      ok(range.collapsed, `${description} selection should be collapsed`);
    252    }
    253    is(range.endContainer, doc.getElementById("s5").firstChild,
    254       `${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
    255    if (kSelectToStartOrEnd) {
    256      is(range.endOffset, range.endContainer.length,
    257         `${description} selection should be expanded to end of the last line`);
    258    } else {
    259      isfuzzy(range.endOffset, 3, 2,
    260              `${description} selection should be expanded to around the last line's 3rd insertion point`);
    261    }
    262 
    263    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in non-scrollable editable div in the body: `;
    264    selection.collapse(doc.getElementById("s5").firstChild, 3);
    265    doPageUp();
    266    is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
    267    range = selection.getRangeAt(0);
    268    is(range.startContainer, doc.getElementById("s2").firstChild,
    269       `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
    270    if (kSelectToStartOrEnd) {
    271      is(range.startOffset, 0,
    272         `${description} selection should be expanded to start of the first line`);
    273    } else {
    274      isfuzzy(range.startOffset, 3, 2,
    275              `${description} selection should be expanded to around the first line's 3rd insertion point`);
    276    }
    277    if (aExpandSelection) {
    278      is(range.endContainer, doc.getElementById("s5").firstChild,
    279         `${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
    280      is(range.endOffset, 3,
    281         `${description} selection should be expanded from the last line's 3rd insertion point`);
    282    } else {
    283      ok(range.collapsed, `${description} selection should be collapsed`);
    284    }
    285 
    286    body.innerHTML = '<span id="s1">first line in the body</span>' +
    287                       '<div id="d1" contenteditable>' +
    288                         '<span id="s2">first editable line</span><br>' +
    289                         '<div id="d2" style="height: 3em; line-height: 1em; overflow: auto;">' +
    290                           '<span id="s3">first line</span><br>' +
    291                           '<span id="s4">second line</span>' +
    292                         "</div>" +
    293                         '<span id="s5">last editable line</span>' +
    294                       "</div>" +
    295                     '<span id="s6">last line in the body</span>';
    296    container = doc.getElementById("d2");
    297 
    298    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable div (but not scrollable along y-axis) in the editable div: `;
    299    is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
    300    selection.collapse(doc.getElementById("s3").firstChild, 3);
    301    doPageDown();
    302    is(container.scrollTop, 0, description + "scrollable div in the editable div (but not scrollable along y-axis) shouldn't be scrollable");
    303    range = selection.getRangeAt(0);
    304    if (aExpandSelection) {
    305      is(range.startContainer, doc.getElementById("s3").firstChild,
    306         `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
    307      is(range.startOffset, 3,
    308         `${description} selection should be expanded from the first line's 3rd insertion point`);
    309    } else {
    310      ok(range.collapsed, `${description} selection should be collapsed`);
    311    }
    312    is(range.endContainer, doc.getElementById("s5").firstChild,
    313       `${description} selection should be expanded into the last editable line (got: ${getNodeDescription(range.endContainer)})`);
    314    if (kSelectToStartOrEnd) {
    315      is(range.endOffset, range.endContainer.length,
    316         `${description} selection should be expanded to end of the last editable line`);
    317    } else {
    318      isfuzzy(range.endOffset, 3, 2,
    319              `${description} selection should be expanded to around the last editable line's 3rd insertion point`);
    320    }
    321 
    322    description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable div (but not scrollable along y-axis) in the editable div: `;
    323    selection.collapse(doc.getElementById("s4").firstChild, 3);
    324    doPageUp();
    325    is(container.scrollTop, 0, description + "scrollable div (but not scrollable along y-axis) in the editable div shouldn't be scrollable");
    326    range = selection.getRangeAt(0);
    327    is(range.startContainer, doc.getElementById("s2").firstChild,
    328       `${description} selection should be expanded into the first editable line (got: ${getNodeDescription(range.startContainer)})`);
    329    if (kSelectToStartOrEnd) {
    330      is(range.startOffset, 0,
    331         `${description} selection should be expanded to start of the first editable line`);
    332    } else {
    333      isfuzzy(range.startOffset, 3, 2,
    334              `${description} selection should be expanded to around the first editable line's 3rd insertion point`);
    335    }
    336    if (aExpandSelection) {
    337      is(range.endContainer, doc.getElementById("s4").firstChild,
    338         `${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
    339      is(range.endOffset, 3,
    340         `${description} selection should be expanded from the last line's 3rd insertion point`);
    341    } else {
    342      ok(range.collapsed, `${description} selection should be collapsed`);
    343    }
    344  }
    345 
    346  doTest(false);
    347  doTest(true);
    348 
    349  aWindow.close();
    350  SimpleTest.finish();
    351 }
    352 </script>
    353 </html>