tor-browser

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

test_editor.xhtml (8540B)


      1 <?xml version="1.0"?>
      2 
      3 <window title="Browser element keyhandling tests"
      4        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
      5        onload="test();">
      6 
      7  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
      8  <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
      9  <script src="chrome://mochikit/content/tests/SimpleTest/NativeKeyCodes.js"/>
     10 
     11  <script type="application/javascript">
     12  <![CDATA[
     13    SimpleTest.waitForExplicitFinish();
     14 
     15    const IS_MAC = navigator.platform.indexOf("Mac") === 0;
     16    const VK = {};
     17    const CHARS = {};
     18 
     19    // Copied values from NativeKeyCodes.js and EventUtils.js
     20    if (IS_MAC) {
     21      VK.LEFT = MAC_VK_LeftArrow;
     22      CHARS.LEFT = "\uF702";
     23      VK.RIGHT = MAC_VK_RightArrow;
     24      CHARS.RIGHT = "\uF703";
     25      VK.UP = MAC_VK_UpArrow;
     26      CHARS.UP = "\uF700";
     27      VK.DOWN = MAC_VK_DownArrow;
     28      CHARS.DOWN = "\uF701";
     29      VK.SPACE = MAC_VK_Space;
     30      VK.X = MAC_VK_ANSI_X;
     31      VK.V = MAC_VK_ANSI_V;
     32      VK.A = MAC_VK_ANSI_A;
     33      VK.Z = MAC_VK_ANSI_Z;
     34      VK.F = MAC_VK_ANSI_F;
     35      VK.O = MAC_VK_ANSI_O;
     36      VK.BACKSPACE = MAC_VK_PC_Backspace;
     37      CHARS.BACKSPACE = "\u007F";
     38    } else {
     39      VK.LEFT = WIN_VK_LEFT;
     40      CHARS.LEFT = "";
     41      VK.RIGHT = WIN_VK_RIGHT;
     42      CHARS.RIGHT = "";
     43      VK.HOME = WIN_VK_HOME;
     44      CHARS.HOME = "";
     45      VK.END = WIN_VK_END;
     46      CHARS.END = "";
     47      VK.SPACE = WIN_VK_SPACE;
     48      VK.X = WIN_VK_X;
     49      VK.V = WIN_VK_V;
     50      VK.A = WIN_VK_A;
     51      VK.Z = WIN_VK_Z;
     52      VK.Y = WIN_VK_Y;
     53      VK.F = WIN_VK_F;
     54      VK.O = WIN_VK_O;
     55      VK.BACKSPACE = WIN_VK_BACK;
     56      CHARS.BACKSPACE = "";
     57    }
     58 
     59    function waitForEvent(target, event) {
     60      info(`Waiting for ${event} event.`);
     61      return new Promise(resolve => {
     62        browser.addEventListener(event, resolve, { once: true });
     63      });
     64    }
     65 
     66    function synthesizeKey(keyCode, modifiers, chars) {
     67      return new Promise((resolve, reject) => {
     68        if (!synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, keyCode, modifiers, chars, chars, resolve)) {
     69          reject();
     70        }
     71      });
     72    }
     73 
     74    function* nodes(element) {
     75      let node = element.firstChild;
     76      while (node) {
     77        yield node;
     78 
     79        if (node.nodeType === Node.ELEMENT_NODE) {
     80          yield* nodes(node);
     81        }
     82 
     83        node = node.nextSibling;
     84      }
     85    }
     86 
     87    async function checkElement(element, start, selectedText, content = "Test text") {
     88      selectionPosition = (element, range) => {
     89        let pos = 0;
     90        for (let node of nodes(element)) {
     91          if (node.nodeType === Node.TEXT_NODE) {
     92            if (node === range.startContainer) {
     93              return pos + range.startOffset;
     94            } else {
     95              pos += node.nodeValue.length;
     96            }
     97          } else if (node === range.startContainer) {
     98            for (let i = 0; i < range.startOffset; i++) {
     99              pos += node.childNodes[i].textContent.length;
    100            }
    101 
    102            return pos;
    103          }
    104        }
    105 
    106        throw new Error("startContainer of range never found.");
    107      }
    108 
    109      isReady = () => {
    110        let selection = element.contentWindow.getSelection();
    111        let range = selection.getRangeAt(0);
    112        let pos = selectionPosition(element.contentDocument.documentElement, range);
    113 
    114        if (start != pos) {
    115          return false;
    116        }
    117        if (selectedText != selection.toString()) {
    118          return false;
    119        }
    120        if (content != element.contentDocument.documentElement.textContent) {
    121          return false;
    122        }
    123        return true;
    124      };
    125 
    126      for (let i = 0; i < 10; i++) {
    127        if (isReady()) {
    128          return;
    129        }
    130 
    131        SimpleTest.requestFlakyTimeout("Polling for changes to apply");
    132        await new Promise(resolve => setTimeout(resolve, 50));
    133      }
    134      ok(false, `Timed out waiting for state ${start} "${selectedText}" "${content}"`);
    135      let selection = element.contentWindow.getSelection();
    136      let range = selection.getRangeAt(0);
    137      info(`${selectionPosition(element.contentDocument.documentElement, range)} "${selection.toString()}" "${element.contentDocument.documentElement.textContent}"`);
    138    }
    139 
    140    async function test() {
    141      let editor = document.getElementById("editor");
    142      editor.contentDocument.designMode = "on";
    143      editor.contentWindow.focus();
    144      let edit = editor.getEditor(editor.contentWindow);
    145      edit.beginningOfDocument();
    146 
    147      await checkElement(editor, 0, "");
    148 
    149      info("right");
    150      await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
    151      await checkElement(editor, 1, "");
    152 
    153      info("shift+right");
    154      await synthesizeKey(VK.RIGHT, { shiftKey: true }, CHARS.RIGHT);
    155      await checkElement(editor, 1, "e");
    156 
    157      info("shift+right");
    158      await synthesizeKey(VK.RIGHT, { shiftKey: true }, CHARS.RIGHT);
    159      await checkElement(editor, 1, "es");
    160 
    161      info("shift+left");
    162      await synthesizeKey(VK.LEFT, { shiftKey: true }, CHARS.LEFT);
    163      await checkElement(editor, 1, "e");
    164 
    165      info("shift+left");
    166      await synthesizeKey(VK.LEFT, { shiftKey: true }, CHARS.LEFT);
    167      await checkElement(editor, 1, "");
    168 
    169      info("shift+left");
    170      await synthesizeKey(VK.LEFT, { shiftKey: true }, CHARS.LEFT);
    171      await checkElement(editor, 0, "T");
    172 
    173      info("shift+right");
    174      await synthesizeKey(VK.RIGHT, { shiftKey: true }, CHARS.RIGHT);
    175      await checkElement(editor, 1, "");
    176 
    177      info("left");
    178      await synthesizeKey(VK.LEFT, {}, CHARS.LEFT);
    179      await checkElement(editor, 0, "");
    180 
    181      if (IS_MAC) {
    182        info("down");
    183        await synthesizeKey(VK.DOWN, { shiftKey: true }, CHARS.DOWN);
    184      } else {
    185        info("end");
    186        await synthesizeKey(VK.END, { shiftKey: true }, CHARS.END);
    187      }
    188      await checkElement(editor, 0, "Test text");
    189 
    190      info("cut");
    191      await synthesizeKey(VK.X, { accelKey: true }, "x");
    192      await checkElement(editor, 0, "", "");
    193      let text = SpecialPowers.getClipboardData("text/plain");
    194      is(text, "Test text", "Should have cut to the clipboard");
    195      SpecialPowers.clipboardCopyString("New text");
    196 
    197      info("paste");
    198      await synthesizeKey(VK.V, { accelKey: true }, "v");
    199      await checkElement(editor, 8, "", "New text");
    200 
    201      if (IS_MAC) {
    202        info("up");
    203        await synthesizeKey(VK.UP, {}, CHARS.UP);
    204      } else {
    205        info("home");
    206        await synthesizeKey(VK.HOME, {}, CHARS.HOME);
    207      }
    208      await checkElement(editor, 0, "", "New text");
    209 
    210      info("select all");
    211      await synthesizeKey(VK.A, { accelKey: true}, "a", "select");
    212      await checkElement(editor, 0, "New text", "New text");
    213 
    214      info("right");
    215      await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
    216      await checkElement(editor, 8, "", "New text");
    217 
    218      info("word left");
    219      if (IS_MAC) {
    220        await synthesizeKey(VK.LEFT, { altKey: true }, CHARS.LEFT);
    221      } else {
    222        await synthesizeKey(VK.LEFT, { ctrlKey: true }, CHARS.LEFT);
    223      }
    224      await checkElement(editor, 4, "", "New text");
    225 
    226      info("delete word left");
    227      if (IS_MAC) {
    228        await synthesizeKey(VK.BACKSPACE, { altKey: true }, CHARS.BACKSPACE);
    229      } else {
    230        await synthesizeKey(VK.BACKSPACE, { ctrlKey: true }, CHARS.BACKSPACE);
    231      }
    232      await checkElement(editor, 0, "", "text");
    233 
    234      info("undo");
    235      await synthesizeKey(VK.Z, { accelKey: true }, "z");
    236      await checkElement(editor, 4, "", "New text");
    237 
    238      info("redo");
    239      if (IS_MAC) {
    240        await synthesizeKey(VK.Z, { accelKey: true, shiftKey: true }, "z");
    241      } else {
    242        await synthesizeKey(VK.Y, { accelKey: true }, "y");
    243      }
    244      await checkElement(editor, 0, "", "text");
    245 
    246      info("typing");
    247      await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
    248      await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
    249      await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
    250      await synthesizeKey(VK.RIGHT, {}, CHARS.RIGHT);
    251      await synthesizeKey(VK.SPACE, {}, " ");
    252      await synthesizeKey(VK.F, {}, "f");
    253      await synthesizeKey(VK.O, {}, "o");
    254      await synthesizeKey(VK.O, {}, "o");
    255      await checkElement(editor, 8, "", "text foo");
    256 
    257      SimpleTest.finish();
    258    }
    259  ]]>
    260  </script>
    261 
    262  <body xmlns="http://www.w3.org/1999/xhtml">
    263    <p id="display"></p>
    264    <div id="content" style="display:none;"></div>
    265    <pre id="test"></pre>
    266  </body>
    267  <editor id="editor" editortype="text" src="data:text/plain,Test text" style="height: 500px"/>
    268 </window>