tor-browser

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

test_selection_at_beforeinput_insertReplacementText.html (5046B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <title>Selection should select the target misspelled word before `beforeinput` event</title>
      6 <script src="/tests/SimpleTest/SimpleTest.js"></script>
      7 <script src="/tests/SimpleTest/EventUtils.js"></script>
      8 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
      9 <script>
     10 "use strict";
     11 
     12 SimpleTest.waitForExplicitFinish();
     13 SimpleTest.waitForFocus(async () => {
     14  const { maybeOnSpellCheck } = SpecialPowers.ChromeUtils.importESModule(
     15    "resource://testing-common/AsyncSpellCheckTestHelper.sys.mjs"
     16  );
     17 
     18  function testTextEditor(aTextControl) {
     19    const description = aTextControl.localName;
     20    aTextControl.setAttribute("spellcheck", "true");
     21    aTextControl.value = "abc abx abc";
     22    aTextControl.focus();
     23 
     24    const textEditor = SpecialPowers.wrap(aTextControl).editor;
     25    const inlineSpellChecker = textEditor.getInlineSpellChecker(true);
     26 
     27    return new Promise(resolve => {
     28      maybeOnSpellCheck(aTextControl, () => {
     29        aTextControl.addEventListener("beforeinput", event => {
     30          is(
     31            `${event.type} (inputType=${event.inputType}), selectionStart=${
     32              aTextControl.selectionStart
     33            }, selectionEnd=${aTextControl.selectionEnd}`,
     34            "beforeinput (inputType=insertReplacementText), selectionStart=4, selectionEnd=7",
     35            `${description}: Selection should select the replacing word`
     36          );
     37          resolve();
     38        }, {once: true});
     39        aTextControl.selectionStart = aTextControl.selectionEnd = 5;
     40        const misspelledWord = inlineSpellChecker.getMisspelledWord(textEditor.rootElement.firstChild, 5);
     41        is(
     42          `${misspelledWord.startOffset}-${misspelledWord.endOffset}`,
     43          "4-7",
     44          `${description}: misspelled word range should be "abc [abx] abc"`
     45        );
     46        info(`${description}: Replacing "abx" with "aux"...`);
     47        inlineSpellChecker.replaceWord(textEditor.rootElement.firstChild, 5, "aux");
     48      });
     49    });
     50  }
     51  await testTextEditor(document.querySelector("input"));
     52  await testTextEditor(document.querySelector("textarea"));
     53 
     54  function testContentEditable(aEditingHost) {
     55    const description = "contenteditable";
     56    aEditingHost.setAttribute("spellcheck", "true");
     57    aEditingHost.textContent = "abc abx abc";
     58    aEditingHost.focus();
     59 
     60    const htmlEditor = SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window);
     61    const inlineSpellChecker = htmlEditor.getInlineSpellChecker(true);
     62 
     63    return new Promise(resolve => {
     64      maybeOnSpellCheck(aEditingHost, async () => {
     65        await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
     66        function getRangeDescription(range) {
     67          function getNodeDescription(node) {
     68            if (!node) {
     69              return "null";
     70            }
     71            switch (node.nodeType) {
     72              case Node.TEXT_NODE:
     73                return `${node.nodeName} "${node.data}"`;
     74              case Node.ELEMENT_NODE:
     75                return `<${node.nodeName.toLowerCase()}>`;
     76              default:
     77                return `${node.nodeName}`;
     78            }
     79          }
     80          if (range === null) {
     81            return "null";
     82          }
     83          if (range === undefined) {
     84            return "undefined";
     85          }
     86          return range.startContainer == range.endContainer &&
     87            range.startOffset == range.endOffset
     88            ? `(${getNodeDescription(range.startContainer)}, ${range.startOffset})`
     89            : `(${getNodeDescription(range.startContainer)}, ${
     90                range.startOffset
     91              }) - (${getNodeDescription(range.endContainer)}, ${range.endOffset})`;
     92        }
     93        aEditingHost.addEventListener("beforeinput", event => {
     94          is(
     95            `${event.type} (inputType=${event.inputType}), selection=${getRangeDescription(getSelection().getRangeAt(0))}`,
     96            `beforeinput (inputType=insertReplacementText), selection=${getRangeDescription({
     97              startContainer: aEditingHost.firstChild,
     98              startOffset: 4,
     99              endContainer: aEditingHost.firstChild,
    100              endOffset: 7,
    101            })}`,
    102            `${description}: Selection should select the replacing word`
    103          );
    104          resolve();
    105        }, {once: true});
    106        getSelection().collapse(aEditingHost.firstChild, 5);
    107        const misspelledWord = inlineSpellChecker.getMisspelledWord(aEditingHost.firstChild, 5);
    108        is(
    109          `${misspelledWord.startOffset}-${misspelledWord.endOffset}`,
    110          "4-7",
    111          `${description}: misspelled word range should be "abc [abx] abc"`
    112        );
    113        info(`${description}: Replacing "abx" with "aux"...`);
    114        inlineSpellChecker.replaceWord(aEditingHost.firstChild, 5, "aux");
    115      });
    116    });
    117  }
    118  await testContentEditable(document.querySelector("div[contenteditable]"));
    119 
    120  SimpleTest.finish();
    121 });
    122 </script>
    123 </head>
    124 <body>
    125 <input>
    126 <textarea></textarea>
    127 <div contenteditable></div>
    128 </body>
    129 </html>