Bug 1328030 - Add basic tests that select content including form controls, using various mouse/kbd gestures.
☠☠ backed out by e93051c16952 ☠ ☠
authorMats Palmgren <mats@mozilla.com>
Tue, 10 Jan 2017 21:37:49 +0100
changeset 328859 9532ebc3faf001a04f12b97cb9e95224898f22ff
parent 328858 e0c4890bcfb493b1c86dfe314417814acf92a761
child 328860 dc76b4cad2f917e0ef7c966f6b2846c01e56e05d
push id31191
push usercbook@mozilla.com
push dateWed, 11 Jan 2017 15:24:19 +0000
treeherdermozilla-central@63ad56438630 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1328030
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1328030 - Add basic tests that select content including form controls, using various mouse/kbd gestures.
dom/base/test/mochitest.ini
dom/base/test/test_selection_with_anon_trees.html
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -729,16 +729,18 @@ support-files = file_receiveMessage.html
 [test_range_bounds.html]
 skip-if = toolkit == 'android'
 [test_reentrant_flush.html]
 skip-if = toolkit == 'android'
 [test_referrer_redirect.html]
 [test_root_iframe.html]
 [test_screen_orientation.html]
 [test_script_loader_crossorigin_data_url.html]
+[test_selection_with_anon_trees.html]
+skip-if = toolkit == 'android'
 [test_setInterval_uncatchable_exception.html]
 skip-if = debug == false
 [test_settimeout_extra_arguments.html]
 [test_settimeout_inner.html]
 [test_setTimeoutWith0.html]
 [test_setting_opener.html]
 [test_simplecontentpolicy.html]
 skip-if = e10s # Bug 1156489.
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_selection_with_anon_trees.html
@@ -0,0 +1,445 @@
+<!DOCTYPE>
+<html>
+<head>
+<title>selection over trees of anonymous nodes</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<style type="text/css">
+@font-face {
+  font-family: Ahem;
+  src: url("Ahem.ttf");
+}
+* { font-family: Ahem; font-size: 20px; }
+</style>
+
+</head>
+<body>
+
+<div id="test1">
+aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa
+<table>
+  <tbody>
+    <tr>
+      <td>
+        <input value="1111">
+      </td>
+    </tr>
+  <tbody>
+</table>
+bbbbbbbb
+<br>
+<br>
+</div>
+
+<div id="test2">
+ccccc ccccccc cccccccccccc ccccccccc
+<div>
+  <input value="2222">
+</div>
+dddddd
+</div>
+
+<div id="test3">
+aaaaa
+<br>
+<input type="button"><br>
+<br>
+<input type="button"><br>
+BBBBB BB<br>
+<br>
+</div>
+
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+const kIsWin = navigator.platform.indexOf("Win") == 0;
+
+function test()
+{
+  function clear(w)
+  {
+    var sel = (w ? w : window).getSelection();
+    sel.removeAllRanges();
+  }
+  function doneTest(e)
+  {
+    // We hide the elements we're done with so that later tests
+    // are inside the rather narrow iframe mochitest gives us.
+    // It matters for synthesizeMouse event tests.
+    e.style.display = 'none';
+    e.offsetHeight;
+  }
+  function show(e) { e.style.display = ''; }
+
+  function dragSelectWithKey(e, clickCount, shiftKey, pointsArray)
+  {
+    const kMove = { type:"mousemove", shiftKey:shiftKey };
+    let pt = pointsArray[0];
+    let x = pt[0];
+    let y = pt[1];
+    synthesizeMouse(e, x, y, { type:"mousedown", clickCount:clickCount, shiftKey:shiftKey });
+    pointsArray.forEach(function(pt) {
+      let x = pt[0];
+      let y = pt[1];
+      synthesizeMouse(e, x, y, kMove);
+    });
+    pt = pointsArray[pointsArray.length - 1];
+    x = pt[0];
+    y = pt[1];
+    synthesizeMouse(e, x, y, kMove);
+    synthesizeMouse(e, x, y, { type:"mouseup", shiftKey:shiftKey });
+  }
+
+  function shiftDragSelect(e, clickCount, pointsArray)
+  {
+    dragSelectWithKey(e, clickCount, true, pointsArray);
+  }
+  function dragSelect(e, clickCount, pointsArray)
+  {
+    dragSelectWithKey(e, clickCount, false, pointsArray);
+  }
+
+  function shiftClick(e, x, y)
+  {
+    synthesizeMouse(e, x, y, { type: "mousedown", shiftKey: true });
+    synthesizeMouse(e, x, y, { type: "mouseup", shiftKey: true });
+  }
+
+  function click(e, x, y)
+  {
+    synthesizeMouse(e, x, y, { type: "mousedown" });
+    synthesizeMouse(e, x, y, { type: "mouseup" });
+  }
+
+  function repeatShiftKey(k, n) {
+    for (let i = 0; i < n; ++i) {
+      synthesizeKey(k, { shiftKey:true });
+    }
+  }
+
+  function init(arr, e)
+  {
+    clear();
+    var sel = window.getSelection();
+    for (i = 0; i < arr.length; ++i) {
+      var data = arr[i];
+      var r = new Range()
+      r.setStart(node(e, data[0]), data[1]);
+      r.setEnd(node(e, data[2]), data[3]);
+      sel.addRange(r);
+    }
+  }
+
+  function NL(s) { return s.replace(/(\r\n|\n\r|\r)/g, '\n'); }
+
+  function checkText(text, e)
+  {
+    var sel = window.getSelection();
+    is(NL(sel.toString()), text, e.id + ": selected text")
+  }
+
+  function checkRangeText(text, index)
+  {
+    var r = window.getSelection().getRangeAt(index);
+    is(NL(r.toString()), text, e.id + ": range["+index+"].toString()")
+  }
+
+  function node(e, arg)
+  {
+    if (typeof arg == "number")
+      return arg == -1 ? e : e.childNodes[arg];
+    return arg;
+  }
+
+  function checkRangeCount(n, e)
+  {
+    var sel = window.getSelection();
+    is(sel.rangeCount, n, e.id + ": Selection range count");
+  }
+
+  function checkRange(r, expected, e) {
+    is(r.startContainer, node(e, expected[0]), e.id + ": range["+i+"].startContainer");
+    is(r.startOffset, expected[1], e.id + ": range["+i+"].startOffset");
+    is(r.endContainer, node(e, expected[2]), e.id + ": range["+i+"].endContainer");
+    is(r.endOffset, expected[3], e.id + ": range["+i+"].endOffset");
+  }
+
+  function checkRanges(arr, e)
+  {
+    let sel = window.getSelection();
+    checkRangeCount(arr.length, e);
+    for (i = 0; i < arr.length; ++i) {
+      let expected = arr[i];
+      let r = sel.getRangeAt(i);
+      checkRange(r, expected, e);
+    }
+  }
+
+  // ======================================================
+  // ================== dragSelect tests ==================
+  // ======================================================
+
+  // Downward word-select with SHIFT
+  clear();
+  var e = document.getElementById('test1');
+  shiftDragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,110], [10,110]]);
+  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
+  checkRanges([[0,1,-1,3]], e);
+
+  // Downward word-select without SHIFT
+  clear();
+  dragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,110], [10,110]]);
+  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
+  checkRanges([[0,1,-1,3]], e);
+
+  // Downward char-select with SHIFT
+  clear();
+  click(e, 1, 1);
+  shiftDragSelect(e, 1, [[30,5], [250,5], [250,20], [250,50], [60,110], [20,110]]);
+  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nb', e);
+  checkRanges([[0,1,2,2]], e);
+
+  // Downward char-select without SHIFT
+  clear();
+  dragSelect(e, 1, [[40,5], [60,70], [30,110]]);
+  checkText('aaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nb', e);
+  checkRanges([[0,3,2,2]], e);
+
+  // Upward word-select with SHIFT
+  clear();
+  shiftDragSelect(e, 2, [[20,110], [60,110], [250,50], [250,20], [250,5], [30,5], [30,5]]);
+  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
+  checkRanges([[0,1,-1,3]], e);
+
+  // Upward word-select without SHIFT
+  clear();
+  dragSelect(e, 2, [[20,110], [60,110], [250,50], [250,20], [250,5], [30,5], [30,5]]);
+  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
+  checkRanges([[0,1,-1,3]], e);
+
+  // Upward char-select with SHIFT
+  clear();
+  click(e, 100, 110);
+  shiftDragSelect(e, 1, [[20,110], [250,50], [250,20], [250,5], [30,5]]);
+  checkText('aaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbb', e);
+  checkRanges([[0,2,2,6]], e);
+
+  // Upward char-select without SHIFT
+  clear();
+  dragSelect(e, 1, [[30,110], [60,110], [40,5]]);
+  checkText('aaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nb', e);
+  checkRanges([[0,3,2,2]], e);
+
+  doneTest(e);
+
+  // Downward word-select with SHIFT
+  var e = document.getElementById('test2');
+  shiftDragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,100], [10,100]]);
+  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
+  checkRanges([[0,1,2,7]], e);
+
+  // Downward word-select without SHIFT
+  clear();
+  dragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,100], [10,100]]);
+  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
+  checkRanges([[0,1,2,7]], e);
+
+  // Downward char-select with SHIFT
+  clear();
+  click(e, 1, 1);
+  shiftDragSelect(e, 1, [[30,5], [30,5], [250,5], [250,20], [250,50], [60,100], [20,100]]);
+  checkText('ccccc ccccccc cccccccccccc ccccccccc\nd', e);
+  checkRanges([[0,1,2,2]], e);
+
+  // Downward char-select without SHIFT
+  clear();
+  dragSelect(e, 1, [[40,5], [250,5], [250,20], [250,50], [60,100], [20,100]]);
+  checkText('ccc ccccccc cccccccccccc ccccccccc\nd', e);
+  checkRanges([[0,3,2,2]], e);
+
+  // Upward word-select with SHIFT
+  var e = document.getElementById('test2');
+  shiftDragSelect(e, 2, [[10,100], [60,100], [250,50], [250,20], [250,5], [30,5], [20,5]]);
+  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
+  checkRanges([[0,1,2,7]], e);
+
+  // Upward word-select without SHIFT
+  clear();
+  shiftDragSelect(e, 2, [[10,100], [60,100], [250,50], [250,20], [250,5], [30,5], [20,5]]);
+  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
+  checkRanges([[0,1,2,7]], e);
+
+  // Upward char-select with SHIFT
+  clear();
+  click(e, 100, 100);
+  shiftDragSelect(e, 1, [[20,100], [250,50], [250,20], [250,5], [60,5]]);
+  checkText('cc ccccccc cccccccccccc ccccccccc\nddddd', e);
+  checkRanges([[0,4,2,6]], e);
+
+  // Upward char-select without SHIFT
+  clear();
+  dragSelect(e, 1, [[20,100], [60,100], [60,5]]);
+  checkText('cc ccccccc cccccccccccc ccccccccc\nd', e);
+  checkRanges([[0,4,2,2]], e);
+
+  doneTest(e);
+
+  // On Windows word-selection also selects the space after the word.
+  kSpaceAfterWord = kIsWin ? ' ' : '';
+
+  // Downward word-select with SHIFT
+  e = document.getElementById('test3');
+  clear();
+  shiftDragSelect(e, 2, [[50,5], [60,125], [10,125]]);
+  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
+  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
+
+  // Downward word-select without SHIFT
+  e = document.getElementById('test3');
+  clear();
+  dragSelect(e, 2, [[40,5], [30,5], [50,5], [60,125], [10,125]]);
+  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
+  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
+
+  // Downward char-select without SHIFT
+  e = document.getElementById('test3');
+  clear();
+  dragSelect(e, 1, [[60,5], [60,125], [20,125]]);
+  checkText('aa\n\n\n\nB', e);
+  checkRanges([[0,4,-1,3], [4,0,-1,8], [9,0,10,2]], e);
+
+  // Upward word-select with SHIFT
+  e = document.getElementById('test3');
+  clear();
+  shiftDragSelect(e, 2, [[10,125], [60,125], [50,5]]);
+  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
+  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
+
+  // Upward word-select without SHIFT
+  e = document.getElementById('test3');
+  clear();
+  dragSelect(e, 2, [[40,125], [60,125], [50,5], [30,5], [20,5]]);
+  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
+  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
+
+  // Upward char-select without SHIFT
+  e = document.getElementById('test3');
+  clear();
+  dragSelect(e, 1, [[60,125], [60,125], [50,5], [30,5], [40,5]]);
+  checkText('aaa\n\n\n\nBBB', e);
+  checkRanges([[0,3,-1,3], [4,0,-1,8], [9,0,10,4]], e);
+
+  doneTest(e);
+
+
+  // ======================================================
+  // ================== shift+click tests =================
+  // ======================================================
+
+  e = document.getElementById('test1');
+  show(e);
+
+  clear();
+  init([[0,0,0,1]], e);
+  shiftClick(e, 100, 100);
+  checkText(' aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbb', e);
+  checkRanges([[0,0,2,6]], e);
+  
+  clear();
+  init([[2,6,2,6]], e);
+  shiftClick(e, 60, 5);
+  checkText('aa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbb', e);
+  checkRanges([[0,4,2,6]], e);
+  
+  doneTest(e);
+  e = document.getElementById('test2');
+  show(e);
+
+  clear();
+  init([[0,4,0,4]], e);
+  shiftClick(e, 100, 100);
+  checkText('cc ccccccc cccccccccccc ccccccccc\nddddd', e);
+  checkRanges([[0,4,2,6]], e);
+
+  clear();
+  init([[2,6,2,6]], e);
+  shiftClick(e, 1, 5);
+  checkText('ccccc ccccccc cccccccccccc ccccccccc\nddddd', e);
+  checkRanges([[0,1,2,6]], e);
+
+  doneTest(e);
+  e = document.getElementById('test3');
+  show(e);
+
+  clear();
+  init([[0,4,0,4]], e);
+  shiftClick(e, 70, 125);
+  checkText('aa\n\n\n\nBBB', e);
+  checkRanges([[0,4,-1,3], [4,0,-1,8], [9,0,10,4]], e);
+
+  // ======================================================
+  // ================== Kbd command tests =================
+  // ======================================================
+
+  doneTest(e);
+  e = document.getElementById('test1');
+  show(e);
+
+  clear();
+  init([[0,0,0,0]], e);
+  repeatShiftKey("VK_RIGHT", 45);
+  checkText(' aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbb', e);
+  checkRanges([[0,0,2,4]], e);
+
+  clear();
+  init([[2,5,2,5]], e);
+  repeatShiftKey("VK_LEFT", 45);
+  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbb', e);
+  checkRanges([[0,1,2,5]], e);
+
+  doneTest(e);
+  e = document.getElementById('test2');
+  show(e);
+
+  clear();
+  init([[0,0,0,0]], e);
+  repeatShiftKey("VK_RIGHT", 45);
+  checkText(' ccccc ccccccc cccccccccccc ccccccccc\ndddd', e);
+  checkRanges([[0,0,2,5]], e);
+
+  clear();
+  init([[2,6,2,6]], e);
+  repeatShiftKey("VK_LEFT", 45);
+  checkText('ccccc ccccccc cccccccccccc ccccccccc\nddddd', e);
+  checkRanges([[0,1,2,6]], e);
+
+  doneTest(e);
+  e = document.getElementById('test3');
+  show(e);
+
+  clear();
+  init([[0,0,0,0]], e);
+  repeatShiftKey("VK_RIGHT", 15);
+  checkText(' aaaaa\n\n\n\nBBB', e);
+  checkRanges([[0,0,-1,3], [4,0,-1,8], [9,0,10,4]], e);
+
+  clear();
+  init([[10,4,10,4]], e);
+  repeatShiftKey("VK_LEFT", 10);
+  checkText('aaaa\n\n\n\nBBB', e);
+  checkRanges([[0,2,-1,3], [4,0,-1,8], [9,0,10,4]], e);
+
+  clear();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(test);
+
+</script>
+</pre>
+</body>
+</html>