Bug 1132518, document navigation tests, r=smaug
authorNeil Deakin <neil@mozilla.com>
Mon, 13 Jul 2015 06:07:50 -0400
changeset 252597 dc9d58b43abf5ad748e72a1eaa4e35e5edd4a3d8
parent 252596 87f44cd6e7f0cc030a7a86f47a84cb3b5222ee72
child 252598 a5aa2faca75e6a9fad0b119c32afab1ac240b36f
push id29038
push userkwierso@gmail.com
push dateMon, 13 Jul 2015 22:55:49 +0000
treeherdermozilla-central@c68d02e758f0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1132518
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1132518, document navigation tests, r=smaug
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_documentnavigation.js
browser/base/content/test/general/file_documentnavigation_frameset.html
dom/tests/mochitest/chrome/window_focus_docnav.xul
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -52,16 +52,17 @@ support-files =
   file_bug906190.sjs
   file_mixedContentFromOnunload.html
   file_mixedContentFromOnunload_test1.html
   file_mixedContentFromOnunload_test2.html
   file_bug970276_popup1.html
   file_bug970276_popup2.html
   file_bug970276_favicon1.ico
   file_bug970276_favicon2.ico
+  file_documentnavigation_frameset.html
   file_dom_notifications.html
   file_double_close_tab.html
   file_favicon_change.html
   file_favicon_change_not_in_document.html
   file_fullscreen-window-open.html
   get_user_media.html
   head.js
   healthreport_pingData.js
@@ -282,16 +283,17 @@ skip-if = !datareporting
 skip-if = buildapp == 'mulet' || (os == "linux" && debug) || e10s # linux: bug 976544; e10s: bug 1071623
 [browser_devices_get_user_media_about_urls.js]
 skip-if = e10s # Bug 1071623
 [browser_devices_get_user_media_in_frame.js]
 skip-if = e10s # Bug 1071623
 [browser_discovery.js]
 [browser_double_close_tab.js]
 skip-if = e10s
+[browser_documentnavigation.js]
 [browser_duplicateIDs.js]
 [browser_drag.js]
 skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
 [browser_favicon_change.js]
 [browser_favicon_change_not_in_document.js]
 [browser_findbarClose.js]
 [browser_fullscreen-window-open.js]
 skip-if = buildapp == 'mulet' || e10s || os == "linux" # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly. Linux: Intermittent failures - bug 941575.
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_documentnavigation.js
@@ -0,0 +1,266 @@
+/*
+ * This test checks that focus is adjusted properly in a browser when pressing F6 and Shift+F6.
+ * There are additional tests in dom/tests/mochitest/chrome/test_focus_docnav.xul which test
+ * non-browser cases.
+ */
+
+let testPage1 = "data:text/html,<html id='html1'><body id='body1'><button id='button1'>Tab 1</button></body></html>";
+let testPage2 = "data:text/html,<html id='html2'><body id='body2'><button id='button2'>Tab 2</button></body></html>";
+let testPage3 = "data:text/html,<html id='html3'><body id='body3' contenteditable='true'><button id='button3'>Tab 3</button></body></html>";
+
+let fm = Services.focus;
+
+function* expectFocusOnF6(backward, expectedDocument, expectedElement, onContent, desc)
+{
+  let focusChangedInChildResolver = null;
+  let focusPromise = onContent ? new Promise(resolve => focusChangedInChildResolver = resolve) :
+                                 BrowserTestUtils.waitForEvent(window, "focus", true);
+
+  function focusChangedListener(msg) {
+    let expected = expectedDocument;
+    if (!expectedElement.startsWith("html")) {
+      expected += "," + expectedElement;
+    }
+
+    is(msg.data.details, expected, desc + " child focus matches");
+    focusChangedInChildResolver();
+  }
+
+  if (onContent) {
+    messageManager.addMessageListener("BrowserTest:FocusChanged", focusChangedListener);
+
+    yield ContentTask.spawn(gBrowser.selectedBrowser, { expectedElementId: expectedElement }, function* (arg) {
+      let expectedElement = content.document.getElementById(arg.expectedElementId);
+      if (!expectedElement) {
+        // Element not found, so look in the child frames.
+        for (let f = 0; f < content.frames.length; f++) {
+          if (content.frames[f].document.getElementById(arg.expectedElementId)) {
+            expectedElement = content.frames[f].document;
+            break;
+          }
+        }
+      }
+      else if (expectedElement.localName == "html") {
+        expectedElement = expectedElement.ownerDocument;
+      }
+
+      if (!expectedElement) {
+        sendSyncMessage("BrowserTest:FocusChanged",
+                        { details : "expected element " + arg.expectedElementId + " not found" });
+        return;
+      }
+
+      expectedElement.addEventListener("focus", function focusReceived() {
+        expectedElement.removeEventListener("focus", focusReceived, true);
+
+        const fm = Components.classes["@mozilla.org/focus-manager;1"].
+                              getService(Components.interfaces.nsIFocusManager);
+        let details = fm.focusedWindow.document.documentElement.id;
+        if (fm.focusedElement) {
+          details += "," + fm.focusedElement.id;
+        }
+
+        sendSyncMessage("BrowserTest:FocusChanged", { details : details });
+      }, true);
+    });
+  }
+
+  EventUtils.synthesizeKey("VK_F6", { shiftKey: backward });
+  yield focusPromise;
+
+  if (typeof expectedElement == "string") {
+    expectedElement = fm.focusedWindow.document.getElementById(expectedElement);
+  }
+
+  if (gMultiProcessBrowser && onContent) {
+    expectedDocument = "main-window";
+    expectedElement = gBrowser.selectedBrowser;
+  }
+
+  is(fm.focusedWindow.document.documentElement.id, expectedDocument, desc + " document matches");
+  is(fm.focusedElement, expectedElement, desc + " element matches");
+
+  if (onContent) {
+    messageManager.removeMessageListener("BrowserTest:FocusChanged", focusChangedListener);
+  }
+}
+
+// Load a page and navigate between it and the chrome window. 
+add_task(function* ()
+{
+  let page1Promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+  gBrowser.selectedBrowser.loadURI(testPage1);
+  yield page1Promise;
+
+  // When the urlbar is focused, pressing F6 should focus the root of the content page.
+  gURLBar.focus();
+  yield* expectFocusOnF6(false, "html1", "html1",
+                                true, "basic focus content page");
+
+  // When the content is focused, pressing F6 should focus the urlbar.
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "basic focus content page urlbar");
+
+  // When a button in content is focused, pressing F6 should focus the urlbar.
+  yield* expectFocusOnF6(false, "html1", "html1",
+                                true, "basic focus content page with button focused");
+
+  return ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () {
+    return content.document.getElementById("button1").focus();
+  });
+
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "basic focus content page with button focused urlbar");
+
+  // The document root should be focused, not the button
+  yield* expectFocusOnF6(false, "html1", "html1",
+                                true, "basic focus again content page with button focused");
+
+  // Check to ensure that the root element is focused
+  let match = yield ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () {
+    return content.document.activeElement == content.document.documentElement;
+  });
+  ok(match, "basic focus again content page with button focused child root is focused");
+});
+
+// Open a second tab. Document focus should skip the background tab.
+add_task(function* ()
+{
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, testPage2);
+
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "basic focus content page and second tab urlbar");
+  yield* expectFocusOnF6(false, "html2", "html2",
+                                true, "basic focus content page with second tab");
+
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+// Shift+F6 should navigate backwards. There's only one document here so the effect
+// is the same.
+add_task(function* ()
+{
+  gURLBar.focus();
+  yield* expectFocusOnF6(true, "html1", "html1",
+                               true, "back focus content page");
+  yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
+                               false, "back focus content page urlbar");
+});
+
+// Open the sidebar and navigate between the sidebar, content and top-level window
+add_task(function* ()
+{
+  let sidebar = document.getElementById("sidebar");
+
+  let loadPromise = BrowserTestUtils.waitForEvent(sidebar, "load", true);
+  SidebarUI.toggle('viewBookmarksSidebar');
+  yield loadPromise;
+
+  
+  gURLBar.focus();
+  yield* expectFocusOnF6(false, "bookmarksPanel",
+                                sidebar.contentDocument.getElementById("search-box").inputField,
+                                false, "focus with sidebar open sidebar");
+  yield* expectFocusOnF6(false, "html1", "html1",
+                                true, "focus with sidebar open content");
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "focus with sidebar urlbar");
+
+  // Now go backwards
+  yield* expectFocusOnF6(true, "html1", "html1",
+                               true, "back focus with sidebar open content");
+  yield* expectFocusOnF6(true, "bookmarksPanel",
+                               sidebar.contentDocument.getElementById("search-box").inputField,
+                               false, "back focus with sidebar open sidebar");
+  yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
+                               false, "back focus with sidebar urlbar");
+
+  SidebarUI.toggle('viewBookmarksSidebar');
+});
+
+// Navigate when the downloads panel is open
+add_task(function* ()
+{
+  yield pushPrefs(["accessibility.tabfocus", 7]);
+
+  let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown", true);
+  EventUtils.synthesizeMouseAtCenter(document.getElementById("downloads-button"), { });
+  yield popupShownPromise;
+
+  gURLBar.focus();
+  yield* expectFocusOnF6(false, "main-window", document.getElementById("downloadsHistory"),
+                                false, "focus with downloads panel open panel");
+  yield* expectFocusOnF6(false, "html1", "html1",
+                                true, "focus with downloads panel open");
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "focus downloads panel open urlbar");
+
+  // Now go backwards
+  yield* expectFocusOnF6(true, "html1", "html1",
+                               true, "back focus with downloads panel open");
+  yield* expectFocusOnF6(true, "main-window", document.getElementById("downloadsHistory"),
+                               false, "back focus with downloads panel open");
+  yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
+                               false, "back focus downloads panel open urlbar");
+
+  let downloadsPopup = document.getElementById("downloadsPanel");
+  let popupHiddenPromise = BrowserTestUtils.waitForEvent(downloadsPopup, "popuphidden", true);
+  downloadsPopup.hidePopup();
+  yield popupHiddenPromise;
+});
+
+// Navigation with a contenteditable body
+add_task(function* ()
+{
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, testPage3);
+
+  // The body should be focused when it is editable, not the root.
+  gURLBar.focus();
+  yield* expectFocusOnF6(false, "html3", "body3",
+                                true, "focus with contenteditable body");
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "focus with contenteditable body urlbar");
+
+  // Now go backwards
+
+  yield* expectFocusOnF6(false, "html3", "body3",
+                                true, "back focus with contenteditable body");
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "back focus with contenteditable body urlbar");
+
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+// Navigation with a frameset loaded
+add_task(function* ()
+{
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser,
+    "http://mochi.test:8888/browser/browser/base/content/test/general/file_documentnavigation_frameset.html");
+
+  gURLBar.focus();
+  yield* expectFocusOnF6(false, "htmlframe1", "htmlframe1",
+                                true, "focus on frameset frame 0");
+  yield* expectFocusOnF6(false, "htmlframe2", "htmlframe2",
+                                true, "focus on frameset frame 1");
+  yield* expectFocusOnF6(false, "htmlframe3", "htmlframe3",
+                                true, "focus on frameset frame 2");
+  yield* expectFocusOnF6(false, "htmlframe4", "htmlframe4",
+                                true, "focus on frameset frame 3");
+  yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
+                                false, "focus on frameset frame urlbar");
+
+  yield* expectFocusOnF6(true, "htmlframe4", "htmlframe4",
+                               true, "back focus on frameset frame 3");
+  yield* expectFocusOnF6(true, "htmlframe3", "htmlframe3",
+                               true, "back focus on frameset frame 2");
+  yield* expectFocusOnF6(true, "htmlframe2", "htmlframe2",
+                               true, "back focus on frameset frame 1");
+  yield* expectFocusOnF6(true, "htmlframe1", "htmlframe1",
+                               true, "back focus on frameset frame 0");
+  yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
+                               false, "back focus on frameset frame urlbar");
+
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
+// XXXndeakin add tests for browsers inside of panels
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/file_documentnavigation_frameset.html
@@ -0,0 +1,12 @@
+<html id="outer">
+
+<frameset rows="30%, 70%">
+  <frame src="data:text/html,&lt;html id='htmlframe1' &gt;&lt;body id='framebody1'&gt;&lt;input id='i1'&gt;&lt;body&gt;&lt;/html&gt;">
+  <frameset cols="30%, 33%, 34%">
+    <frame src="data:text/html,&lt;html id='htmlframe2'&gt;&lt;body id='framebody2'&gt;&lt;input id='i2'&gt;&lt;body&gt;&lt;/html&gt;">
+    <frame src="data:text/html,&lt;html id='htmlframe3'&gt;&lt;body id='framebody3'&gt;&lt;input id='i3'&gt;&lt;body&gt;&lt;/html&gt;">
+    <frame src="data:text/html,&lt;html id='htmlframe4'&gt;&lt;body id='framebody4'&gt;&lt;input id='i4'&gt;&lt;body&gt;&lt;/html&gt;">
+  </frameset>
+</frameset>
+
+</html>
--- a/dom/tests/mochitest/chrome/window_focus_docnav.xul
+++ b/dom/tests/mochitest/chrome/window_focus_docnav.xul
@@ -4,23 +4,23 @@
 <window onload="start()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
 <script type="application/javascript"
         src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
 <textbox id="textbox"/>
 
-<panel id="panel2" onpopupshown="runTests(this, 2);" onpopuphidden="document.getElementById('panel').hidePopup()">
-  <textbox id="p2textbox" value="Popup2"/>
-</panel>
 <panel id="panel" onpopupshown="runTests(this, 1);"
                   onpopuphidden="done()">
   <textbox id="p1textbox" value="Popup1"/>
 </panel>
+<panel id="panel2" onpopupshown="runTests(this, 2);" onpopuphidden="document.getElementById('panel').hidePopup()">
+  <textbox id="p2textbox" value="Popup2"/>
+</panel>
 
 <browser id="browser" type="content" src="focus_frameset.html" width="500" height="400"/>
 
 <script type="application/javascript">
 <![CDATA[
 
 var fm = Components.classes["@mozilla.org/focus-manager;1"].
            getService(Components.interfaces.nsIFocusManager);
@@ -57,33 +57,33 @@ function runTests(panel, popupCount)
   if (!popupCount || popupCount > 2)
     popupCount = 0;
 
   fm.clearFocus(window);
 
   var childwin = document.getElementById("browser").contentWindow;
 
   if (popupCount) {
+    next(window, document.getElementById("p1textbox").inputField, "First into popup 1 with " + popupCount);
+
     if (popupCount == 2) {
       next(window, document.getElementById("p2textbox").inputField, "First into popup 2 with " + popupCount);
     }
-
-    next(window, document.getElementById("p1textbox").inputField, "First into popup 1 with " + popupCount);
   }
 
   next(childwin.frames[0], childwin.frames[0].document.documentElement, "First with " + popupCount);
   next(childwin.frames[1], childwin.frames[1].document.documentElement, "Second with " + popupCount);
   previous(childwin.frames[0], childwin.frames[0].document.documentElement, "Second back with " + popupCount);
 
   if (popupCount) {
-    previous(window, document.getElementById("p1textbox").inputField, "First back from popup 1 with " + popupCount);
-
     if (popupCount == 2) {
       previous(window, document.getElementById("p2textbox").inputField, "First back from popup 2 with " + popupCount);
     }
+
+    previous(window, document.getElementById("p1textbox").inputField, "First back from popup 1 with " + popupCount);
   }
 
   previous(window, document.getElementById("textbox").inputField, "First back with " + popupCount);
 
   if (panel == document.getElementById("panel"))
     document.getElementById("panel2").openPopup(null, "after_start", 100, 20);
   else if (panel == document.getElementById("panel2"))
     panel.hidePopup();