tor-browser

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

test_contenteditable_text_input_handling.html (11462B)


      1 <html>
      2 <head>
      3  <title>Test for text input event handling on contenteditable editor</title>
      4  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
      5  <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
      6  <link rel="stylesheet" type="text/css"
      7          href="chrome://mochikit/content/tests/SimpleTest/test.css" />
      8 </head>
      9 <body>
     10 <div id="display">
     11  <p id="static">static content<input id="inputInStatic"><textarea id="textareaInStatic"></textarea></p>
     12  <p id="editor"contenteditable="true">content editable<input id="inputInEditor"><textarea id="textareaInEditor"></textarea></p>
     13 </div>
     14 <div id="content" style="display: none">
     15 
     16 </div>
     17 <pre id="test">
     18 </pre>
     19 
     20 <script class="testbody" type="application/javascript">
     21 
     22 SimpleTest.waitForExplicitFinish();
     23 SimpleTest.waitForFocus(runTests);
     24 const { AppConstants } = ChromeUtils.importESModule(
     25  "resource://gre/modules/AppConstants.sys.mjs"
     26 );
     27 const kLF = !navigator.platform.indexOf("Win") && false ? "\r\n" : "\n";
     28 
     29 function runTests() {
     30  var fm = Services.focus;
     31 
     32  var listener = {
     33    handleEvent: function _hv(aEvent) {
     34      aEvent.preventDefault(); // prevent the browser default behavior
     35    },
     36  };
     37  SpecialPowers.wrap(window).addEventListener("keypress", listener, { mozSystemGroup: true });
     38 
     39  var staticContent = document.getElementById("static");
     40  staticContent._defaultValue = getTextValue(staticContent);
     41  staticContent._isFocusable = false;
     42  staticContent._isEditable = false;
     43  staticContent._isContentEditable = false;
     44  staticContent._description = "non-editable p element";
     45  var inputInStatic = document.getElementById("inputInStatic");
     46  inputInStatic._defaultValue = getTextValue(inputInStatic);
     47  inputInStatic._isFocusable = true;
     48  inputInStatic._isEditable = true;
     49  inputInStatic._isContentEditable = false;
     50  inputInStatic._description = "input element in static content";
     51  var textareaInStatic = document.getElementById("textareaInStatic");
     52  textareaInStatic._defaultValue = getTextValue(textareaInStatic);
     53  textareaInStatic._isFocusable = true;
     54  textareaInStatic._isEditable = true;
     55  textareaInStatic._isContentEditable = false;
     56  textareaInStatic._description = "textarea element in static content";
     57  var editor = document.getElementById("editor");
     58  editor._defaultValue = getTextValue(editor);
     59  editor._isFocusable = true;
     60  editor._isEditable = true;
     61  editor._isContentEditable = true;
     62  editor._description = "contenteditable editor";
     63  var inputInEditor = document.getElementById("inputInEditor");
     64  inputInEditor._defaultValue = getTextValue(inputInEditor);
     65  inputInEditor._isFocusable = true;
     66  inputInEditor._isEditable = true;
     67  inputInEditor._isContentEditable = false;
     68  inputInEditor._description = "input element in contenteditable editor";
     69  var textareaInEditor = document.getElementById("textareaInEditor");
     70  textareaInEditor._defaultValue = getTextValue(textareaInEditor);
     71  textareaInEditor._isFocusable = true;
     72  textareaInEditor._isEditable = true;
     73  textareaInEditor._isContentEditable = false;
     74  textareaInEditor._description = "textarea element in contenteditable editor";
     75 
     76  function getTextValue(aElement) {
     77    if (aElement == editor) {
     78      var value = "";
     79      for (var node = aElement.firstChild; node; node = node.nextSibling) {
     80        if (node.nodeType == Node.TEXT_NODE) {
     81          value += node.data;
     82        } else if (node.nodeType == Node.ELEMENT_NODE) {
     83          var tagName = node.tagName.toLowerCase();
     84          switch (tagName) {
     85            case "input":
     86            case "textarea":
     87              value += kLF;
     88              break;
     89            default:
     90              ok(false, "Undefined tag is used in the editor: " + tagName);
     91              break;
     92          }
     93        }
     94      }
     95      return value;
     96    }
     97    return aElement.value;
     98  }
     99 
    100  function testTextInput(aFocus) {
    101    var when = " when " +
    102      ((aFocus && aFocus._isFocusable) ? aFocus._description + " has focus" :
    103                                         "nobody has focus");
    104 
    105    function checkValue(aElement, aInsertedText) {
    106      if (aElement == aFocus && aElement._isEditable) {
    107        is(getTextValue(aElement), aInsertedText + aElement._defaultValue,
    108           aElement._description +
    109             " wasn't edited by synthesized key events" + when);
    110        return;
    111      }
    112      is(getTextValue(aElement), aElement._defaultValue,
    113         aElement._description +
    114           " was edited by synthesized key events" + when);
    115    }
    116 
    117    if (aFocus && aFocus._isFocusable) {
    118      aFocus.focus();
    119      is(fm.focusedElement, aFocus,
    120         aFocus._description + " didn't get focus at preparing tests" + when);
    121    } else {
    122      var focusedElement = fm.focusedElement;
    123      if (focusedElement) {
    124        focusedElement.blur();
    125      }
    126      ok(!fm.focusedElement,
    127         "Failed to blur at preparing tests" + when);
    128    }
    129 
    130    if (aFocus && aFocus._isFocusable) {
    131      sendString("ABC");
    132      checkValue(staticContent, "ABC");
    133      checkValue(inputInStatic, "ABC");
    134      checkValue(textareaInStatic, "ABC");
    135      checkValue(editor, "ABC");
    136      checkValue(inputInEditor, "ABC");
    137      checkValue(textareaInEditor, "ABC");
    138 
    139      if (aFocus._isEditable) {
    140        synthesizeKey("KEY_Backspace", {repeat: 3});
    141        checkValue(staticContent, "");
    142        checkValue(inputInStatic, "");
    143        checkValue(textareaInStatic, "");
    144        checkValue(editor, "");
    145        checkValue(inputInEditor, "");
    146        checkValue(textareaInEditor, "");
    147      }
    148    }
    149 
    150    // When key events are fired on unfocused editor.
    151    function testDispatchedKeyEvent(aTarget) {
    152      var targetDescription = " (dispatched to " + aTarget._description + ")";
    153      function dispatchKeyEvent(aKeyCode, aChar, aDispatchTarget) {
    154        var keyEvent = new KeyboardEvent("keypress", {
    155          bubbles: true,
    156          cancelable: true,
    157          view: null,
    158          keyCode: aKeyCode,
    159          charCode: aChar ? aChar.charCodeAt(0) : 0
    160        });
    161        aDispatchTarget.dispatchEvent(keyEvent);
    162      }
    163 
    164      function checkValueForDispatchedKeyEvent(aElement, aInsertedText) {
    165        if (aElement == aTarget && aElement._isEditable &&
    166            (!aElement._isContentEditable || aElement == aFocus)) {
    167          is(getTextValue(aElement), aInsertedText + aElement._defaultValue,
    168             aElement._description +
    169               " wasn't edited by dispatched key events" +
    170               when + targetDescription);
    171          return;
    172        }
    173        if (aElement == aTarget) {
    174          is(getTextValue(aElement), aElement._defaultValue,
    175             aElement._description +
    176               " was edited by dispatched key events" +
    177               when + targetDescription);
    178          return;
    179        }
    180        is(getTextValue(aElement), aElement._defaultValue,
    181           aElement._description +
    182             " was edited by key events unexpectedly" +
    183             when + targetDescription);
    184      }
    185 
    186      dispatchKeyEvent(0, "A", aTarget);
    187      dispatchKeyEvent(0, "B", aTarget);
    188      dispatchKeyEvent(0, "C", aTarget);
    189 
    190      checkValueForDispatchedKeyEvent(staticContent, "ABC");
    191      checkValueForDispatchedKeyEvent(inputInStatic, "ABC");
    192      checkValueForDispatchedKeyEvent(textareaInStatic, "ABC");
    193      checkValueForDispatchedKeyEvent(editor, "ABC");
    194      checkValueForDispatchedKeyEvent(inputInEditor, "ABC");
    195      checkValueForDispatchedKeyEvent(textareaInEditor, "ABC");
    196 
    197      dispatchKeyEvent(KeyboardEvent.DOM_VK_BACK_SPACE, 0, aTarget);
    198      dispatchKeyEvent(KeyboardEvent.DOM_VK_BACK_SPACE, 0, aTarget);
    199      dispatchKeyEvent(KeyboardEvent.DOM_VK_BACK_SPACE, 0, aTarget);
    200 
    201      checkValueForDispatchedKeyEvent(staticContent, "");
    202      checkValueForDispatchedKeyEvent(inputInStatic, "");
    203      checkValueForDispatchedKeyEvent(textareaInStatic, "");
    204      checkValueForDispatchedKeyEvent(editor, "");
    205      checkValueForDispatchedKeyEvent(inputInEditor, "");
    206      checkValueForDispatchedKeyEvent(textareaInEditor, "");
    207    }
    208 
    209    testDispatchedKeyEvent(staticContent);
    210    testDispatchedKeyEvent(inputInStatic);
    211    testDispatchedKeyEvent(textareaInStatic);
    212    testDispatchedKeyEvent(editor);
    213    testDispatchedKeyEvent(inputInEditor);
    214    testDispatchedKeyEvent(textareaInEditor);
    215 
    216    if (!aFocus._isEditable) {
    217      return;
    218    }
    219 
    220    // IME
    221    // input first character
    222    synthesizeCompositionChange(
    223      { "composition":
    224        { "string": "\u3089",
    225          "clauses":
    226          [
    227            { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE },
    228          ],
    229        },
    230        "caret": { "start": 1, "length": 0 },
    231      });
    232    var queryText = synthesizeQueryTextContent(0, 100);
    233    ok(queryText, "query text event result is null" + when);
    234    if (!queryText) {
    235      return;
    236    }
    237    ok(queryText.succeeded, "query text event failed" + when);
    238    if (!queryText.succeeded) {
    239      return;
    240    }
    241    is(queryText.text, "\u3089" + aFocus._defaultValue,
    242       "composing text is incorrect" + when);
    243    var querySelectedText = synthesizeQuerySelectedText();
    244    ok(querySelectedText, "query selected text event result is null" + when);
    245    if (!querySelectedText) {
    246      return;
    247    }
    248    ok(querySelectedText.succeeded, "query selected text event failed" + when);
    249    if (!querySelectedText.succeeded) {
    250      return;
    251    }
    252    is(querySelectedText.offset, 1,
    253       "query selected text event returns wrong offset" + when);
    254    is(querySelectedText.text, "",
    255       "query selected text event returns wrong selected text" + when);
    256    // commit composition
    257    synthesizeComposition({ type: "compositioncommitasis" });
    258    queryText = synthesizeQueryTextContent(0, 100);
    259    ok(queryText, "query text event result is null after commit" + when);
    260    if (!queryText) {
    261      return;
    262    }
    263    ok(queryText.succeeded, "query text event failed after commit" + when);
    264    if (!queryText.succeeded) {
    265      return;
    266    }
    267    is(queryText.text, "\u3089" + aFocus._defaultValue,
    268       "composing text is incorrect after commit" + when);
    269    querySelectedText = synthesizeQuerySelectedText();
    270    ok(querySelectedText,
    271       "query selected text event result is null after commit" + when);
    272    if (!querySelectedText) {
    273      return;
    274    }
    275    ok(querySelectedText.succeeded,
    276       "query selected text event failed after commit" + when);
    277    if (!querySelectedText.succeeded) {
    278      return;
    279    }
    280    is(querySelectedText.offset, 1,
    281       "query selected text event returns wrong offset after commit" + when);
    282    is(querySelectedText.text, "",
    283       "query selected text event returns wrong selected text after commit" +
    284         when);
    285 
    286    checkValue(staticContent, "\u3089");
    287    checkValue(inputInStatic, "\u3089");
    288    checkValue(textareaInStatic, "\u3089");
    289    checkValue(editor, "\u3089");
    290    checkValue(inputInEditor, "\u3089");
    291    checkValue(textareaInEditor, "\u3089");
    292 
    293    synthesizeKey("KEY_Backspace");
    294    checkValue(staticContent, "");
    295    checkValue(inputInStatic, "");
    296    checkValue(textareaInStatic, "");
    297    checkValue(editor, "");
    298    checkValue(inputInEditor, "");
    299    checkValue(textareaInEditor, "");
    300  }
    301 
    302  testTextInput(inputInStatic);
    303  testTextInput(textareaInStatic);
    304  testTextInput(editor);
    305  testTextInput(inputInEditor);
    306  testTextInput(textareaInEditor);
    307 
    308  SpecialPowers.wrap(window).removeEventListener("keypress", listener, { mozSystemGroup: true });
    309 
    310  SimpleTest.finish();
    311 }
    312 
    313 </script>
    314 </body>
    315 
    316 </html>