Bug 1533054 - Add tests for selection key navigation: up/down, page-up/down, tab r=mak
authorDrew Willcoxon <adw@mozilla.com>
Thu, 04 Apr 2019 12:11:32 +0000
changeset 468434 eb068229a2d5579aa9555ea307ebdfcd06fafc9e
parent 468433 4af5a60f18eefbd3a39b3d1d137c99950c494e04
child 468435 2d61a31bec7d81e5f7225468d8c4396cec37382a
push id35837
push userrmaries@mozilla.com
push dateTue, 09 Apr 2019 03:43:40 +0000
treeherdermozilla-central@9eb55c9bf557 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs1533054
milestone68.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 1533054 - Add tests for selection key navigation: up/down, page-up/down, tab r=mak Differential Revision: https://phabricator.services.mozilla.com/D25901
browser/components/urlbar/UrlbarController.jsm
browser/components/urlbar/UrlbarUtils.jsm
browser/components/urlbar/tests/browser/browser.ini
browser/components/urlbar/tests/browser/browser_selectionKeyNavigation.js
--- a/browser/components/urlbar/UrlbarController.jsm
+++ b/browser/components/urlbar/UrlbarController.jsm
@@ -289,17 +289,17 @@ class UrlbarController {
         if (event.ctrlKey || event.altKey) {
           break;
         }
         if (this.view.isOpen) {
           this.userSelectionBehavior = "arrow";
           this.view.selectBy(
             event.keyCode == KeyEvent.DOM_VK_PAGE_DOWN ||
             event.keyCode == KeyEvent.DOM_VK_PAGE_UP ?
-              5 : 1,
+              UrlbarUtils.PAGE_UP_DOWN_DELTA : 1,
             { reverse: event.keyCode == KeyEvent.DOM_VK_UP ||
                        event.keyCode == KeyEvent.DOM_VK_PAGE_UP });
         } else {
           if (this.keyEventMovesCaret(event)) {
             break;
           }
           this.input.startQuery();
         }
--- a/browser/components/urlbar/UrlbarUtils.jsm
+++ b/browser/components/urlbar/UrlbarUtils.jsm
@@ -105,16 +105,19 @@ var UrlbarUtils = {
   },
 
   // This defines icon locations that are common used in the UI.
   ICON: {
     // DEFAULT is defined lazily so it doesn't eagerly initialize PlacesUtils.
     SEARCH_GLASS: "chrome://browser/skin/search-glass.svg",
   },
 
+  // The number of results by which Page Up/Down move the selection.
+  PAGE_UP_DOWN_DELTA: 5,
+
   // IME composition states.
   COMPOSITION: {
     NONE: 1,
     COMPOSING: 2,
     COMMIT: 3,
     CANCELED: 4,
   },
 
--- a/browser/components/urlbar/tests/browser/browser.ini
+++ b/browser/components/urlbar/tests/browser/browser.ini
@@ -58,16 +58,17 @@ support-files = redirect_error.sjs
 [browser_removeUnsafeProtocolsFromURLBarPaste.js]
 subsuite = clipboard
 [browser_search_favicon.js]
 skip-if = true # Bug 1526222 - Doesn't currently work with QuantumBar
 [browser_searchTelemetry.js]
 support-files =
   searchSuggestionEngine.xml
   searchSuggestionEngine.sjs
+[browser_selectionKeyNavigation.js]
 [browser_stop_pending.js]
 support-files =
   slow-page.sjs
 [browser_switchTab_closesUrlbarPopup.js]
 [browser_switchTab_decodeuri.js]
 [browser_switchTab_override.js]
 skip-if = ((os == 'win') && verify && debug)
 [browser_switchToTab_closes_newtab.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/urlbar/tests/browser/browser_selectionKeyNavigation.js
@@ -0,0 +1,139 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This test makes sure that the up/down, page-up/down, and tab keys properly
+// adjust the selection.  See also browser_caret_navigation.js.
+
+"use strict";
+
+const MAX_RESULTS = UrlbarPrefs.get("maxRichResults");
+
+add_task(async function init() {
+  for (let i = 0; i < MAX_RESULTS; i++) {
+    await PlacesTestUtils.addVisits("http://example.com/" + i);
+  }
+  registerCleanupFunction(async function() {
+    await PlacesUtils.history.clear();
+  });
+});
+
+add_task(async function downKey() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected initially");
+  for (let i = 1; i < MAX_RESULTS; i++) {
+    EventUtils.synthesizeKey("KEY_ArrowDown");
+    Assert.equal(UrlbarTestUtils.getSelectedIndex(window), i);
+  }
+  EventUtils.synthesizeKey("KEY_ArrowDown");
+  let oneOffs = UrlbarTestUtils.getOneOffSearchButtons(window);
+  Assert.ok(oneOffs.selectedButton, "A one-off should now be selected");
+  while (oneOffs.selectedButton) {
+    EventUtils.synthesizeKey("KEY_ArrowDown");
+  }
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected again");
+});
+
+add_task(async function upKey() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected initially");
+  EventUtils.synthesizeKey("KEY_ArrowUp");
+  let oneOffs = UrlbarTestUtils.getOneOffSearchButtons(window);
+  Assert.ok(oneOffs.selectedButton, "A one-off should now be selected");
+  while (oneOffs.selectedButton) {
+    EventUtils.synthesizeKey("KEY_ArrowUp");
+  }
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window),
+               MAX_RESULTS - 1,
+               "The last result should be selected");
+  for (let i = 1; i < MAX_RESULTS; i++) {
+    EventUtils.synthesizeKey("KEY_ArrowUp");
+    Assert.equal(UrlbarTestUtils.getSelectedIndex(window),
+                 MAX_RESULTS - i - 1);
+  }
+});
+
+add_task(async function pageDownKey() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected initially");
+  let pageCount = Math.ceil((MAX_RESULTS - 1) / UrlbarUtils.PAGE_UP_DOWN_DELTA);
+  for (let i = 0; i < pageCount; i++) {
+    EventUtils.synthesizeKey("KEY_PageDown");
+    Assert.equal(
+      UrlbarTestUtils.getSelectedIndex(window),
+      Math.min((i + 1) * UrlbarUtils.PAGE_UP_DOWN_DELTA, MAX_RESULTS - 1)
+    );
+  }
+  EventUtils.synthesizeKey("KEY_PageDown");
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "Page down at end should wrap around to first result");
+});
+
+add_task(async function pageUpKey() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected initially");
+  EventUtils.synthesizeKey("KEY_PageUp");
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), MAX_RESULTS - 1,
+               "Page up at start should wrap around to last result");
+  let pageCount = Math.ceil((MAX_RESULTS - 1) / UrlbarUtils.PAGE_UP_DOWN_DELTA);
+  for (let i = 0; i < pageCount; i++) {
+    EventUtils.synthesizeKey("KEY_PageUp");
+    Assert.equal(
+      UrlbarTestUtils.getSelectedIndex(window),
+      Math.max(MAX_RESULTS - 1 - ((i + 1) * UrlbarUtils.PAGE_UP_DOWN_DELTA), 0)
+    );
+  }
+});
+
+add_task(async function pageDownKeyShowsView() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  await UrlbarTestUtils.promisePopupClose(window);
+  EventUtils.synthesizeKey("KEY_PageDown");
+  await UrlbarTestUtils.promiseSearchComplete(window);
+  Assert.ok(UrlbarTestUtils.isPopupOpen(window));
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0);
+});
+
+add_task(async function pageUpKeyShowsView() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  await UrlbarTestUtils.promisePopupClose(window);
+  EventUtils.synthesizeKey("KEY_PageUp");
+  await UrlbarTestUtils.promiseSearchComplete(window);
+  Assert.ok(UrlbarTestUtils.isPopupOpen(window));
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0);
+});
+
+add_task(async function tabKey() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected initially");
+  for (let i = 1; i < MAX_RESULTS; i++) {
+    EventUtils.synthesizeKey("KEY_Tab");
+    Assert.equal(UrlbarTestUtils.getSelectedIndex(window), i);
+  }
+  EventUtils.synthesizeKey("KEY_Tab");
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected again");
+});
+
+add_task(async function tabKeyReverse() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
+               "The heuristic autofill result should be selected initially");
+  for (let i = 1; i < MAX_RESULTS; i++) {
+    EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
+    Assert.equal(UrlbarTestUtils.getSelectedIndex(window), MAX_RESULTS - i);
+  }
+});
+
+add_task(async function tabKeyBlur() {
+  await promiseAutocompleteResultPopup("exam", window, true);
+  await UrlbarTestUtils.promisePopupClose(window);
+  Assert.equal(document.activeElement, gURLBar.inputField);
+  EventUtils.synthesizeKey("KEY_Tab");
+  Assert.notEqual(document.activeElement, gURLBar.inputField);
+});