summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/mozilla/tests/focus
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/mozilla/tests/focus
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/mozilla/tests/focus')
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_collapse.html207
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_selectNode.html267
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_setEnd.html364
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_setStart.html353
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange.html1242
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html63
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html67
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html9
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_collapse.html148
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html134
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html142
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_extend.html189
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html112
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_removeRange.html112
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html254
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html926
-rw-r--r--testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html19
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html75
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html42
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html42
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html50
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html50
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html42
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html31
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html42
33 files changed, 5114 insertions, 0 deletions
diff --git a/testing/web-platform/mozilla/tests/focus/Range_collapse.html b/testing/web-platform/mozilla/tests/focus/Range_collapse.html
new file mode 100644
index 0000000000..7c16f16bec
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_collapse.html
@@ -0,0 +1,207 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.collapse()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(true) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(false) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(false) of selection between start of the first text node of 'staticBefore' and end of the first text node of 'anchor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(false) of selection between start of the first text node of 'editor' and end of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(true) of selection between start of the first text node of 'editor' and end of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.collapse(false) of selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.collapse(true) of selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Range.collapse(false) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Range.collapse(true) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is 'anchor'");
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(true) of selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(false) of selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(true) of selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(false) of selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(true) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(false) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(true) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.collapse(false) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' when active element is 'outerEditor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Range_selectNode.html b/testing/web-platform/mozilla/tests/focus/Range_selectNode.html
new file mode 100644
index 0000000000..3975653d2c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_selectNode.html
@@ -0,0 +1,267 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.selectNode() and Range.selectNodeContents()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+function selectNode(aNodeToSelect)
+{
+ document.getSelection().getRangeAt(0).selectNode(aNodeToSelect);
+}
+
+function selectNodeContents(aNodeToSelectItsContents)
+{
+ document.getSelection().getRangeAt(0).selectNodeContents(aNodeToSelectItsContents);
+}
+
+[{ func: selectNode, doingDescription: "Range.selectNode()" },
+ { func: selectNodeContents, doingDescription: "Range.selectNodeContents()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the <body>");
+
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'editor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'outerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'anchor'");
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Range_setEnd.html b/testing/web-platform/mozilla/tests/focus/Range_setEnd.html
new file mode 100644
index 0000000000..e1eed4ae71
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_setEnd.html
@@ -0,0 +1,364 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.setEnd(), Range.setEndAfter() and Range.setEndBefore()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+function setEnd(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setEnd(aNode, aOffset);
+}
+
+function setEndBefore(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setEndBefore(aNode);
+}
+
+function setEndAfter(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setEndAfter(aNode);
+}
+
+// Range.setEnd*() should work same as collapse if specified end position is before its start.
+[{ func: setEnd, doingDescription: "Range.setEnd()" },
+ { func: setEndBefore, doingDescription: "Range.setEndBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.textNode);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(anchor.textNode);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (before the selection) when active element is 'anchor'");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticBefore.textNode, staticBefore.textLength);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, editor.textLength);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticInEditor.textNode, staticInEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().collapse(anchor.textNode, anchor.textLength);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(anchor.textNode, anchor.textLength);
+ aTest.func(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'anchor' (before the collapsed selection) when active element is the <body>");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, staticBefore.textLength,
+ editor.textNode, editor.textLength);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the selection, between end of the first text node of 'staticBefore' and end of the first text node of 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, editor.textLength,
+ outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the selection, between end of the first text node of 'editor' and end of the first text node of 'outerEditor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, outerEditor.textLength,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection, between end of the first text node of 'outerEditor' and end of the first text node of 'innerEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, staticInEditor.textLength,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticInEditor' (before the selection, between end of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor') when active element is the <body>");
+});
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticAfter.textNode);
+ setEndAfter(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setEndAfter() with the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticAfter'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ setEndAfter(staticInEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setEndAfter() with the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.textNode);
+ setEndAfter(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ setEndAfter(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ setEndAfter(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setEndAfter() with the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ setEndAfter(staticBefore.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setEndAfter() with the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(anchor.textNode);
+ setEndAfter(staticBefore.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setEndAfter() with the first text node of 'staticBefore' (before the selection) when active element is 'anchor'");
+
+// Range.setEnd*() should blur focused editing host when it expands selection to outside of it.
+[{ func: setEnd, doingDescription: "Range.setEnd()" },
+ { func: setEndAfter, doingDescription: "Range.setEndAfter()" },
+ { func: setEndBefore, doingDescription: "Range.setEndBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, 0);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (after end of the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (after end of the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (after end of the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (after end of the selection) when active element is 'outerEditor'");
+});
+
+// Range.setEnd*() should move focus to an editing host when the range is shrunken into it.
+[{ func: setEnd, doingDescription: "Range.setEnd()" },
+ { func: setEndAfter, doingDescription: "Range.setEndAfter()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'outerEditor' and selection end is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'outerEditor' and selection end is in 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'innerEditor' and selection end is in 'staticAfter'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is the <body>");
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Range_setStart.html b/testing/web-platform/mozilla/tests/focus/Range_setStart.html
new file mode 100644
index 0000000000..9297aa02ab
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_setStart.html
@@ -0,0 +1,353 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.setStart(), Range.setStartAfter() and Range.setStartBefore()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+function setStart(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setStart(aNode, aOffset);
+}
+
+function setStartBefore(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setStartBefore(aNode);
+}
+
+function setStartAfter(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setStartAfter(aNode);
+}
+
+// Range.setStart*() should work same as collapse if specified start position is after its end.
+[{ func: setStart, doingDescription: "Range.setStart()" },
+ { func: setStartAfter, doingDescription: "Range.setStartAfter()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticBefore.textNode);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.textNode);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the selection) when active element is 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the collapsed selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, 0);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, 0);
+ aTest.func(staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, 0);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection, between start of the first text node of 'staticBefore' and start of the first text node of 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, 0);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection, between start of the first text node of 'editor' and start of the first text node of 'outerEditor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'staticInEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'innerEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'staticInEditor' and start of the first text node of 'innerEditor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, 0);
+ aTest.func(staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the selection, between start of the first text node of 'innerEditor' and start of the first text node of 'staticAfter') when active element is the <body>");
+});
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticBefore.textNode);
+ setStartBefore(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.setStartBefore() with the first text node of 'editor' (before the selection) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ setStartBefore(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.setStartBefore() with the first text node of 'outerEditor' (before the selection) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ setStartBefore(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ setStartBefore(staticAfter.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticAfter.textNode);
+ setStartBefore(anchor.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.setStartBefore() with the first text node of 'anchor' (before the selection) when active element is the <body>");
+
+// Range.setStart*() should blur focused editing host when it expands selection to outside of it.
+[{ func: setStart, doingDescription: "Range.setStart()" },
+ { func: setStartAfter, doingDescription: "Range.setStartAfter()" },
+ { func: setStartBefore, doingDescription: "Range.setStartBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, editor.textLength);
+ aTest.func(staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor'");
+});
+
+// Range.setStart*() should move focus to an editing host when the range is shrunken into it.
+[{ func: setStart, doingDescription: "Range.setStart()" },
+ { func: setStartBefore, doingDescription: "Range.setStartBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ aTest.func(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'anchor' (shrunken into 'anchor') when active element is the <body>");
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange.html
new file mode 100644
index 0000000000..d94e688158
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange.html
@@ -0,0 +1,1242 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.addRange()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+/**
+ * NOTE: When you add/modify something in this file, you should add same test to Selection_setBaseAndExtent.html too.
+ */
+
+
+// Selection.addRange() with collapsed range.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is the <body> and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.addRange() with non-collapsed range in a node.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.addRange() with a range across editing host boundary.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html
new file mode 100644
index 0000000000..71b7c26c46
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move and auto scroll tests caused by a call of Selection.addRange() into a contenteditable element in iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<iframe srcdoc="<div style='height: 1000px;'></div><div id='editor' contenteditable>editor</div>" style="height: 500px;"></iframe>
+<script>
+"use strict";
+setup({explicit_done:true});
+
+window.onload = ()=>{
+ test(function() {
+ var subDocument = document.querySelector("iframe").contentDocument;
+ var editorInFrame = subDocument.getElementById("editor");
+ var range = subDocument.createRange();
+ range.setStart(editorInFrame, 0);
+ var selection = subDocument.getSelection();
+ selection.removeAllRanges();
+ document.documentElement.scrollTop = 0;
+ subDocument.documentElement.scrollTop = 0;
+ selection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(subDocument.activeElement, editorInFrame);
+ assert_equals(subDocument.documentElement.scrollTop, 0);
+ }, "Moving selection into inactive contenteditable element in non-focused document shouldn't cause scrolling");
+
+ test(function() {
+ var iframe = document.querySelector("iframe");
+ var subDocument = iframe.contentDocument;
+ var selection = subDocument.getSelection();
+
+ // Reset selection in <iframe>
+ var editorInFrame = subDocument.getElementById("editor");
+ editorInFrame.blur();
+ selection.removeAllRanges();
+ var range = document.createRange();
+ range.setStart(subDocument.body, 0);
+ selection.addRange(range);
+ subDocument.documentElement.scrollTop = 0;
+
+ // Move focus to the <iframe>
+ iframe.contentWindow.focus();
+ document.documentElement.scrollTop = 0;
+ assert_equals(document.activeElement, iframe);
+ assert_equals(subDocument.activeElement, subDocument.body);
+ assert_equals(subDocument.documentElement.scrollTop, 0);
+
+ range = subDocument.createRange();
+ range.setStart(editorInFrame, 0);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ assert_equals(document.activeElement, iframe);
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(subDocument.activeElement, editorInFrame);
+ assert_equals(subDocument.documentElement.scrollTop, 0);
+ }, "Moving selection into inactive contenteditable element in focused document shouldn't cause scrolling");
+
+ done();
+};
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html
new file mode 100644
index 0000000000..e06e9cd17a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.addRange() into iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body onload="doTest()">
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p>Here is an iframe:</p>
+<iframe src="Selection_addRange_into_iframe_iframe.html"></iframe>
+<script>
+"use strict";
+
+setup({explicit_done:true});
+
+function doTest() {
+ var selection = document.getSelection();
+ var childDocument = document.getElementsByTagName("iframe")[0].contentDocument;
+ var childSelection = childDocument.getSelection();
+ test(function() {
+ selection.collapse(document.body.firstChild, 0);
+ childSelection.collapse(childDocument.body.firstChild, 0);
+
+ document.documentElement.scrollTop = 0;
+ childDocument.documentElement.scrollTop = 0;
+ childSelection.removeAllRanges();
+ var range = childDocument.createRange();
+ range.selectNodeContents(childDocument.getElementById("editor1"));
+ childSelection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(childDocument.activeElement, childDocument.getElementById("editor1"));
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(childDocument.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor1' in the <iframe> after Selection.addRange() but parent's active document should be the <body>");
+ test(function() {
+ selection.collapse(document.body.firstChild, 0);
+ childSelection.collapse(childDocument.getElementById("editor1").firstChild, 0);
+
+ document.documentElement.scrollTop = 0;
+ childDocument.documentElement.scrollTop = 0;
+ childSelection.removeAllRanges();
+ var range = childDocument.createRange();
+ range.selectNodeContents(childDocument.getElementById("editor2"));
+ childSelection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(childDocument.activeElement, childDocument.getElementById("editor2"));
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(childDocument.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor2' in the <iframe> after Selection.addRange() but parent's active document should be the <body>");
+ test(function() {
+ selection.collapse(document.body.firstChild, 0);
+ childSelection.collapse(childDocument.getElementById("editor2").firstChild, 0);
+
+ document.documentElement.scrollTop = 0;
+ childDocument.documentElement.scrollTop = 0;
+ childSelection.removeAllRanges();
+ var range = childDocument.createRange();
+ range.selectNodeContents(childDocument.getElementById("non-editor"));
+ childSelection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(childDocument.activeElement, childDocument.getElementById("editor2"));
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(childDocument.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor2' in the <iframe> after Selection.addRange() to non-editable <div> and parent's active document should be the <body>");
+
+ done();
+}
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html
new file mode 100644
index 0000000000..946d4aa5e7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset=utf-8>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p>Here are two editors:</p>
+<div id="editor1" contenteditable>The first editor.</div>
+<div id="editor2" contenteditable>The second editor.</div>
+<div id="non-editor">The non-editable div.</div>
+</body>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_collapse.html b/testing/web-platform/mozilla/tests/focus/Selection_collapse.html
new file mode 100644
index 0000000000..2e3050d822
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_collapse.html
@@ -0,0 +1,148 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.collapse()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapse() not moving selection from first text node in the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'outerEditor' to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in 'outerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of the <body>");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(anchor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html b/testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html
new file mode 100644
index 0000000000..f768782650
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html
@@ -0,0 +1,134 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.collapseToEnd()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToEnd() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToEnd() with selection between start of the first text node of 'staticBefore' and end of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapseToEnd() with selection between start of the first text node of 'editor' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.collapseToEnd() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' and 'anchor' has focus before the call");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapseToEnd() with selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html b/testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html
new file mode 100644
index 0000000000..238a436c1b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html
@@ -0,0 +1,142 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.collapseToStart()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToStart() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapseToStart() with selection between start of the first text node of 'editor' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.collapseToStart() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' and 'anchor' has focus before the call");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToStart() with selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_extend.html b/testing/web-platform/mozilla/tests/focus/Selection_extend.html
new file mode 100644
index 0000000000..62136cc4a3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_extend.html
@@ -0,0 +1,189 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.extend()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(editor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'staticAfter'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'anchor'");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().extend(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().extend(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().extend(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to start of the first text node of 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to end of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(editor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to start of the first text node of 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(anchor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'anchor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().extend(anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.extend() from selection at start of the first text node of 'anchor' to end of the first text node of 'anchor' and 'anchor' has focus before the call");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ anchor.element.blur();
+ document.getSelection().extend(anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'anchor' to end of the first text node of 'anchor' and 'anchor' doesn't have focus before the call");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html b/testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html
new file mode 100644
index 0000000000..6e6854d44b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.removeAllRanges()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange(staticBefore);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeAllRanges() when active element is the <body> and selection is at the start of the first text node of 'staticBefore'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.removeAllRanges() when active element is 'editor' and selection is at the start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.removeAllRanges() when active element is 'outerEditor' and selection is at the start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeAllRanges() when active element is the <body> and selection is at the start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.removeAllRanges() when active element is 'innerEditor' and selection is at the start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticAfter);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeAllRanges() when active element is the <body> and selection is at the start of the first text node of 'staticAfter'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.removeAllRanges() when active element is 'anchor' and selection is at the start of the first text node of 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_removeRange.html b/testing/web-platform/mozilla/tests/focus/Selection_removeRange.html
new file mode 100644
index 0000000000..14e78381d2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_removeRange.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.removeRange()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange(staticBefore);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeRange() to remove selected range at the start of the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.removeRange() to remove selected range at the start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.removeRange() to remove selected range at the start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeRange() to remove selected range at the start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.removeRange() to remove selected range at the start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticAfter);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeRange() to remove selected range at the start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.removeRange() to remove selected range at the start of the first text node of 'anchor' when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html b/testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html
new file mode 100644
index 0000000000..2753e60851
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html
@@ -0,0 +1,254 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.selectAllChildren()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.selectAllChildren() to select the children of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'ouerEditor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html b/testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html
new file mode 100644
index 0000000000..7cfc110009
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html
@@ -0,0 +1,926 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.setBaseAndExtent()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+/**
+ * NOTE: When you add/modify something in this file, you should add same test to Selection_addRange.html too.
+ */
+
+// Selection.setBaseAndExtent() with collapsed range.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is the <body> and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.setBaseAndExtent() with non-collapsed range in a node.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.setBaseAndExtent() with a range across editing host boundary.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html b/testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html
new file mode 100644
index 0000000000..35fd30f1f6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.addRange()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="host"></div>
+<script>
+let host = document.getElementById("host");
+let shadow = host.attachShadow({ mode: "open", delegatesFocus: true });
+shadow.innerHTML = `<button>Focusable</button>`;
+
+test(function() {
+ assert_true(SpecialPowers.Services.focus.elementIsFocusable(host, 0), "host is focusable");
+ host.focus();
+ assert_equals(document.activeElement, host, "Host is focused");
+ assert_equals(shadow.activeElement, shadow.querySelector("button"), "Button is focused");
+ assert_true(SpecialPowers.Services.focus.elementIsFocusable(host, 0), "host is still focusable");
+}, "isElementFocusable with delegateFocus");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html
new file mode 100644
index 0000000000..e765990145
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() before iframe loaded different site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-before-iframe-loaded-different-site-outer.sub.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html
new file mode 100644
index 0000000000..fd7c2bffa6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() before iframe loaded same site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-before-iframe-loaded-same-site-outer.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html
new file mode 100644
index 0000000000..58310fd687
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() from next tick before iframe loaded different site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html
new file mode 100644
index 0000000000..01b467718c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() from next tick before iframe loaded same site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-next-tick-before-iframe-loaded-same-site-outer.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html b/testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html
new file mode 100644
index 0000000000..82a1346ec6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test focus event after iframe gets focus</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+function waitForMessage(target, checkFn) {
+ return new Promise(resolve => {
+ target.addEventListener("message", e => {
+ if (checkFn && !checkFn(e)) {
+ return;
+ }
+ resolve();
+ }, { once: true });
+ });
+}
+
+function start(w) {
+ w.postMessage("start", "*");
+}
+
+// This will send message to outer frame and also inner frame to ask them
+// send the log they collect back, the logs of outer and inner will be
+// concatenated.
+async function getLog(w) {
+ let log = "";
+ step_timeout(function() {
+ w.postMessage("getlog", "*");
+ }, 0);
+ await waitForMessage(window, (e) => {
+ log = e.data;
+ return true;
+ });
+ return log;
+}
+
+function runSingleTest(url, focusIframeFunction, expectedResult, description) {
+ promise_test(async t => {
+ let w = window.open(url);
+ t.add_cleanup(() => { w.close(); });
+ await waitForMessage(window, e => e.data === "ready");
+ start(w);
+ focusIframeFunction(w);
+ assert_equals(await getLog(w), expectedResult);
+ }, description);
+}
+
+function runTests(url, description) {
+ // Test calling iframe.focus();
+ runSingleTest(url, (w) => {
+ w.postMessage("iframefocus", "*");
+ }, "outerlog:windowblur,innerlog:windowfocus,",
+ description + " via calling iframe.focus()");
+
+ // Test calling iframe.contentWindow.focus();
+ runSingleTest(url, (w) => {
+ w.postMessage("iframecontentWindowfocus", "*");
+ }, "outerlog:windowblur,innerlog:windowfocus,",
+ description + " via calling iframe.contentWindow.focus()");
+
+ // Test calling window.focus() in iframe;
+ runSingleTest(url, (w) => {
+ w.postMessage("windowfocus", "*");
+ }, "outerlog:windowblur,innerlog:willfocuswindow,windowfocus,didfocuswindow,",
+ description + " via calling window.focus() in iframe");
+}
+
+// Test same site iframe
+runTests("support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html",
+ "Check iframe focus event after same site iframe gets focus");
+
+// Test different site iframe
+runTests("support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html",
+ "Check iframe focus event after different site iframe gets focus");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html
new file mode 100644
index 0000000000..bcf23627d2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() before iframe loaded different site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html
new file mode 100644
index 0000000000..e95fe7d292
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() before iframe loaded different site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/_mozilla/focus/support/focus-before-iframe-loaded-different-site-inner.html";
+document.body.appendChild(iframe);
+iframe.focus();
+if (document.activeElement != iframe) {
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html
new file mode 100644
index 0000000000..3c277f078f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() before iframe loaded same site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html
new file mode 100644
index 0000000000..8c829d6d47
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() before iframe loaded same site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "focus-before-iframe-loaded-same-site-inner.html";
+document.body.appendChild(iframe);
+iframe.focus();
+if (document.activeElement != iframe) {
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html
new file mode 100644
index 0000000000..2c1b35f2b2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() from next tick before iframe loaded different site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html
new file mode 100644
index 0000000000..83a48e303d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() from next tick before iframe loaded different site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "tick") {
+ iframe.focus();
+ if (document.activeElement != iframe) {
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+ }
+ return;
+ }
+
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/_mozilla/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html";
+document.body.appendChild(iframe);
+window.postMessage("tick", "*");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html
new file mode 100644
index 0000000000..62add75ed9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() from next tick before iframe loaded same site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html
new file mode 100644
index 0000000000..a68d34039d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() from next tick before iframe loaded same site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "tick") {
+ iframe.focus();
+ if (document.activeElement != iframe) {
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+ }
+ return;
+ }
+
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "focus-next-tick-before-iframe-loaded-same-site-inner.html";
+document.body.appendChild(iframe);
+window.postMessage("tick", "*");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html
new file mode 100644
index 0000000000..d69580237c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Iframe focus event after different site iframe gets focus outer</title>
+<iframe src="http://{{hosts[alt][www]}}:{{ports[http][0]}}/_mozilla/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html"></iframe>
+<script>
+let outerlog = "outerlog:";
+
+let iframe = document.querySelector("iframe");
+window.onmessage = function(e) {
+ if (e.data == "start") {
+ window.onfocus = function() {
+ outerlog += "windowfocus,";
+ };
+ } else if (e.data == "iframefocus") {
+ iframe.focus();
+ } else if (e.data == "iframecontentWindowfocus") {
+ iframe.contentWindow.focus();
+ } else if (e.data == "windowfocus") {
+ iframe.contentWindow.postMessage("windowfocus", "*");
+ } else if (e.data == "getlog") {
+ iframe.contentWindow.postMessage("getlog", "*");
+ } else {
+ opener.postMessage(outerlog + e.data, "*");
+ }
+};
+
+window.onload = function() {
+ window.onblur = function() {
+ outerlog += "windowblur,";
+ };
+
+ iframe.onfocus = function() {
+ outerlog += "iframefocus,";
+ };
+
+ iframe.onblur = function() {
+ outerlog += "iframeblur,";
+ };
+
+ opener.postMessage("ready", "*");
+};
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html
new file mode 100644
index 0000000000..64a360d248
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Iframe focus event inner document</title>
+</head>
+<body>
+<h1>Inner</h1>
+<script>
+let innerlog = "innerlog:";
+
+window.onmessage = function(e) {
+ if (e.data == "windowfocus") {
+ innerlog += "willfocuswindow,";
+ window.focus();
+ innerlog += "didfocuswindow,";
+ } else if (e.data == "getlog") {
+ parent.postMessage(innerlog, "*");
+ }
+};
+
+window.onfocus = function() {
+ innerlog += "windowfocus,";
+};
+
+window.onblur = function() {
+ innerlog += "windowblur,";
+};
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html
new file mode 100644
index 0000000000..06040d6485
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Iframe focus event after same site iframe gets focus outer</title>
+<iframe src="iframe-focus-event-after-iframe-gets-focus-inner.html"></iframe>
+<script>
+let outerlog = "outerlog:";
+
+let iframe = document.querySelector("iframe");
+window.onmessage = function(e) {
+ if (e.data == "start") {
+ window.onfocus = function() {
+ outerlog += "windowfocus,";
+ };
+ } else if (e.data == "iframefocus") {
+ iframe.focus();
+ } else if (e.data == "iframecontentWindowfocus") {
+ iframe.contentWindow.focus();
+ } else if (e.data == "windowfocus") {
+ iframe.contentWindow.postMessage("windowfocus", "*");
+ } else if (e.data == "getlog") {
+ iframe.contentWindow.postMessage("getlog", "*");
+ } else {
+ opener.postMessage(outerlog + e.data, "*");
+ }
+};
+
+window.onload = function() {
+ window.onblur = function() {
+ outerlog += "windowblur,";
+ };
+
+ iframe.onfocus = function() {
+ outerlog += "iframefocus,";
+ };
+
+ iframe.onblur = function() {
+ outerlog += "iframeblur,";
+ };
+
+ opener.postMessage("ready", "*");
+};
+</script>