Bug 1067903 - Part 3: Update tests to deal with autoselect and textValue. r=mak
authorBlair McBride <bmcbride@mozilla.com>
Mon, 24 Nov 2014 12:19:44 +1300
changeset 241410 1791d8198cc3
parent 241409 77a8dfd5559e
child 241411 45e442b7d671
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs1067903
milestone36.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 1067903 - Part 3: Update tests to deal with autoselect and textValue. r=mak
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_URLBarSetURI.js
browser/base/content/test/general/browser_action_searchengine.js
browser/base/content/test/general/browser_autocomplete_autoselect.js
browser/base/content/test/general/browser_bug1003461-switchtab-override.js
browser/base/content/test/general/browser_bug1024133-switchtab-override-keynav.js
browser/base/content/test/general/browser_bug1070778.js
browser/base/content/test/general/browser_bug304198.js
browser/base/content/test/general/browser_bug556061.js
browser/base/content/test/general/browser_canonizeURL.js
browser/base/content/test/general/browser_locationBarCommand.js
browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js
browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js
browser/base/content/test/general/browser_urlbarCopying.js
browser/base/content/test/general/browser_urlbarEnter.js
browser/base/content/test/general/browser_urlbarStop.js
browser/base/content/test/general/browser_urlbarTrimURLs.js
browser/base/content/test/general/head.js
browser/components/sessionstore/test/browser_522545.js
toolkit/components/places/tests/PlacesTestUtils.jsm
toolkit/components/places/tests/moz.build
toolkit/content/widgets/autocomplete.xml
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -117,16 +117,18 @@ skip-if = os == "linux" || e10s # Bug 10
 [browser_action_searchengine_alias.js]
 skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
 [browser_addKeywordSearch.js]
 [browser_search_favicon.js]
 skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
 [browser_alltabslistener.js]
 [browser_autocomplete_a11y_label.js]
 skip-if = e10s # Bug 1101993 - times out for unknown reasons when run in the dir (works on its own)
+[browser_autocomplete_autoselect.js]
+skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
 [browser_backButtonFitts.js]
 skip-if = os != "win" || e10s # The Fitts Law back button is only supported on Windows (bug 571454) / e10s - Bug 1099154: test touches content (attempts to add an event listener directly to the contentWindow)
 [browser_blob-channelname.js]
 [browser_bookmark_titles.js]
 skip-if = buildapp == 'mulet' || toolkit == "windows" || e10s # Disabled on Windows due to frequent failures (bugs 825739, 841341) / e10s - Bug 1094205 - places doesn't return the right thing in e10s mode, for some reason
 [browser_bug304198.js]
 skip-if = e10s
 [browser_bug321000.js]
@@ -284,17 +286,17 @@ skip-if = e10s # Bug 1093373 - relies on
 [browser_bug906190.js]
 skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus
 [browser_bug970746.js]
 skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug1015721.js]
 skip-if = os == 'win' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug1064280_changeUrlInPinnedTab.js]
 [browser_bug1070778.js]
-skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux
+skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
 [browser_canonizeURL.js]
 skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only
 [browser_contentAreaClick.js]
 skip-if = e10s
 [browser_contextSearchTabPosition.js]
 skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash
 [browser_ctrlTab.js]
 [browser_customize_popupNotification.js]
--- a/browser/base/content/test/general/browser_URLBarSetURI.js
+++ b/browser/base/content/test/general/browser_URLBarSetURI.js
@@ -26,57 +26,57 @@ function nextTest() {
     executeSoon(finish);
   }
 }
 
 let tests = [
   function revert(next) {
     loadTabInWindow(window, function (tab) {
       gURLBar.handleRevert();
-      is(gURLBar.value, "example.com", "URL bar had user/pass stripped after reverting");
+      is(gURLBar.textValue, "example.com", "URL bar had user/pass stripped after reverting");
       gBrowser.removeTab(tab);
       next();
     });
   },
   function customize(next) {
     whenNewWindowLoaded(undefined, function (win) {
       // Need to wait for delayedStartup for the customization part of the test,
       // since that's where BrowserToolboxCustomizeDone is set.
       whenDelayedStartupFinished(win, function () {
         loadTabInWindow(win, function () {
           openToolbarCustomizationUI(function () {
             closeToolbarCustomizationUI(function () {
-              is(win.gURLBar.value, "example.com", "URL bar had user/pass stripped after customize");
+              is(win.gURLBar.textValue, "example.com", "URL bar had user/pass stripped after customize");
               win.close();
               next();
             }, win);
           }, win);
         });
       });
     });
   },
   function pageloaderror(next) {
     loadTabInWindow(window, function (tab) {
       // Load a new URL and then immediately stop it, to simulate a page load
       // error.
       tab.linkedBrowser.loadURI("http://test1.example.com");
       tab.linkedBrowser.stop();
-      is(gURLBar.value, "example.com", "URL bar had user/pass stripped after load error");
+      is(gURLBar.textValue, "example.com", "URL bar had user/pass stripped after load error");
       gBrowser.removeTab(tab);
       next();
     });
   }
 ];
 
 function loadTabInWindow(win, callback) {
   info("Loading tab");
   let url = "http://user:pass@example.com/";
   let tab = win.gBrowser.selectedTab = win.gBrowser.addTab(url);
   tab.linkedBrowser.addEventListener("load", function listener() {
     info("Tab loaded");
     if (tab.linkedBrowser.currentURI.spec != url)
       return;
     tab.linkedBrowser.removeEventListener("load", listener, true);
 
-    is(win.gURLBar.value, "example.com", "URL bar had user/pass stripped initially");
+    is(win.gURLBar.textValue, "example.com", "URL bar had user/pass stripped initially");
     callback(tab);
   }, true);
 }
--- a/browser/base/content/test/general/browser_action_searchengine.js
+++ b/browser/base/content/test/general/browser_action_searchengine.js
@@ -38,16 +38,19 @@ add_task(function* () {
       gBrowser.removeTab(tab);
     } catch(ex) { /* tab may have already been closed in case of failure */ }
 
     return promiseClearHistory();
   });
 
   let result = yield promise_first_result("open a search");
   isnot(result, null, "Should have a result");
+  is(result.getAttribute("url"),
+     `moz-action:searchengine,{"engineName":"MozSearch","input":"open a search","searchQuery":"open a search"}`,
+     "Result should be a moz-action: for the correct search engine");
   is(result.hasAttribute("image"), false, "Result shouldn't have an image attribute");
 
   let tabPromise = promiseTabLoaded(gBrowser.selectedTab);
   EventUtils.synthesizeMouseAtCenter(result, {});
   yield tabPromise;
 
-  is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search");
+  is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search", "Correct URL should be loaded");
 });
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_autocomplete_autoselect.js
@@ -0,0 +1,59 @@
+function repeat(limit, func) {
+  for (let i = 0; i < limit; i++) {
+    func(i);
+  }
+}
+
+function* promiseAutoComplete(inputText) {
+  gURLBar.focus();
+  gURLBar.value = inputText.slice(0, -1);
+  EventUtils.synthesizeKey(inputText.slice(-1), {});
+  yield promiseSearchComplete();
+}
+
+function is_selected(index) {
+  is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`);
+}
+
+add_task(function*() {
+  registerCleanupFunction(promiseClearHistory);
+
+  let visits = [];
+  repeat(10, i => {
+    visits.push({
+      uri: makeURI("http://example.com/autocomplete/?" + i),
+    });
+  });
+  yield PlacesTestUtils.addVisits(visits);
+
+  yield promiseAutoComplete("example.com/autocomplete");
+
+  let popup = gURLBar.popup;
+  let results = popup.richlistbox.children;
+  // 1 extra for the current search engine match
+  is(results.length, 11, "Should get 11 results");
+  is_selected(0);
+
+  info("Key Down to select the next item");
+  EventUtils.synthesizeKey("VK_DOWN", {});
+  is_selected(1);
+
+  info("Key Down 11 times should wrap around all the way around");
+  repeat(11, () => EventUtils.synthesizeKey("VK_DOWN", {}));
+  is_selected(1);
+
+  info("Key Up 11 times should wrap around the other way");
+  repeat(11, () => EventUtils.synthesizeKey("VK_UP", {}));
+  is_selected(1);
+
+  info("Page Up will go up the list, but not wrap");
+  EventUtils.synthesizeKey("VK_PAGE_UP", {})
+  is_selected(0);
+
+  info("Page Up again will wrap around to the end of the list");
+  EventUtils.synthesizeKey("VK_PAGE_UP", {})
+  is_selected(10);
+
+  EventUtils.synthesizeKey("VK_ESCAPE", {});
+  yield promisePopupHidden(gURLBar.popup);
+});
--- a/browser/base/content/test/general/browser_bug1003461-switchtab-override.js
+++ b/browser/base/content/test/general/browser_bug1003461-switchtab-override.js
@@ -30,25 +30,24 @@ add_task(function* test_switchtab_overri
   registerCleanupFunction(() => {
     gURLBar.onSearchComplete = onSearchComplete;
   });
   gURLBar.onSearchComplete = function () {
     ok(gURLBar.popupOpen, "The autocomplete popup is correctly open");
     onSearchComplete.apply(gURLBar);
     deferred.resolve();
   }
-  
+
   gURLBar.focus();
   gURLBar.value = "dummy_pag";
   EventUtils.synthesizeKey("e" , {});
   yield deferred.promise;
 
   info("Select second autocomplete popup entry");
   EventUtils.synthesizeKey("VK_DOWN" , {});
-  EventUtils.synthesizeKey("VK_DOWN" , {});
   ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found");
 
   info("Override switch-to-tab");
   deferred = Promise.defer();
   // In case of failure this would switch tab.
   let onTabSelect = event => {
     deferred.reject(new Error("Should have overridden switch to tab"));
   };
@@ -56,13 +55,14 @@ add_task(function* test_switchtab_overri
   registerCleanupFunction(() => {
     gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect, false);
   });
   // Otherwise it would load the page.
   whenTabLoaded(secondTab, deferred.resolve);
 
   EventUtils.synthesizeKey("VK_SHIFT" , { type: "keydown" });
   EventUtils.synthesizeKey("VK_RETURN" , { });
+  info(`gURLBar.value = ${gURLBar.value}`);
   EventUtils.synthesizeKey("VK_SHIFT" , { type: "keyup" });
   yield deferred.promise;
 
   yield promiseClearHistory();
 });
--- a/browser/base/content/test/general/browser_bug1024133-switchtab-override-keynav.js
+++ b/browser/base/content/test/general/browser_bug1024133-switchtab-override-keynav.js
@@ -16,36 +16,23 @@ add_task(function* test_switchtab_overri
   registerCleanupFunction(() => {
     try {
       gBrowser.removeTab(tab);
       gBrowser.removeTab(secondTab);
     } catch(ex) { /* tabs may have already been closed in case of failure */ }
     return promiseClearHistory();
   });
 
-  info("Wait for autocomplete")
-  let searchDeferred = Promise.defer();
-  let onSearchComplete = gURLBar.onSearchComplete;
-  registerCleanupFunction(() => {
-    gURLBar.onSearchComplete = onSearchComplete;
-  });
-  gURLBar.onSearchComplete = function () {
-    ok(gURLBar.popupOpen, "The autocomplete popup is correctly open");
-    onSearchComplete.apply(gURLBar);
-    searchDeferred.resolve();
-  }
-
   gURLBar.focus();
   gURLBar.value = "dummy_pag";
   EventUtils.synthesizeKey("e" , {});
-  yield searchDeferred.promise;
+  yield promiseSearchComplete();
 
   info("Select second autocomplete popup entry");
   EventUtils.synthesizeKey("VK_DOWN" , {});
-  EventUtils.synthesizeKey("VK_DOWN" , {});
   ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found");
 
   info("Shift+left on switch-to-tab entry");
 
   EventUtils.synthesizeKey("VK_SHIFT" , { type: "keydown" });
   EventUtils.synthesizeKey("VK_LEFT", { shiftKey: true });
   EventUtils.synthesizeKey("VK_SHIFT" , { type: "keyup" });
 
--- a/browser/base/content/test/general/browser_bug1070778.js
+++ b/browser/base/content/test/general/browser_bug1070778.js
@@ -12,42 +12,38 @@ function is_selected(index) {
   is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`);
 }
 
 add_task(function*() {
   // This test is only relevant if UnifiedComplete is enabled.
   if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
     return;
 
-  let itemIds = [];
   registerCleanupFunction(() => {
-    itemIds.forEach(PlacesUtils.bookmarks.removeItem);
+    PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
   });
 
   let itemId =
     PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                          NetUtil.newURI("http://example.com/?q=%s"),
                                          PlacesUtils.bookmarks.DEFAULT_INDEX,
                                          "test");
   PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword");
-  itemIds.push(itemId);
 
   // This item only needed so we can select the keyword item, select something
   // else, then select the keyword item again.
   itemId =
     PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                          NetUtil.newURI("http://example.com/keyword"),
                                          PlacesUtils.bookmarks.DEFAULT_INDEX,
                                          "keyword abc");
-  itemIds.push(itemId);
 
   yield promiseAutoComplete("keyword a");
 
-  // Select keyword item
-  EventUtils.synthesizeKey("VK_DOWN", {});
+  // First item should already be selected
   is_selected(0);
   // Select next one (important!)
   EventUtils.synthesizeKey("VK_DOWN", {});
   is_selected(1);
   // Re-select keyword item
   EventUtils.synthesizeKey("VK_UP", {});
   is_selected(0);
 
--- a/browser/base/content/test/general/browser_bug304198.js
+++ b/browser/base/content/test/general/browser_bug304198.js
@@ -16,26 +16,25 @@ function test() {
   function cleanUp() {
     gBrowser.removeTab(fullURLTab);
     gBrowser.removeTab(partialURLTab);
     gBrowser.removeTab(deletedURLTab);
   }
 
   function cycleTabs() {
     gBrowser.selectedTab = fullURLTab;
-    is(gURLBar.value, testURL, 'gURLBar.value should be testURL after switching back to fullURLTab');
+    is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after switching back to fullURLTab');
 
     gBrowser.selectedTab = partialURLTab;
-    is(gURLBar.value, testPartialURL, 'gURLBar.value should be testPartialURL after switching back to partialURLTab');
-
+    is(gURLBar.textValue, testPartialURL, 'gURLBar.textValue should be testPartialURL after switching back to partialURLTab');
     gBrowser.selectedTab = deletedURLTab;
-    is(gURLBar.value, '', 'gURLBar.value should be "" after switching back to deletedURLTab');
+    is(gURLBar.textValue, '', 'gURLBar.textValue should be "" after switching back to deletedURLTab');
 
     gBrowser.selectedTab = fullURLTab;
-    is(gURLBar.value, testURL, 'gURLBar.value should be testURL after switching back to fullURLTab');
+    is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after switching back to fullURLTab');
   }
 
   // function borrowed from browser_bug386835.js
   function load(tab, url, cb) {
     tab.linkedBrowser.addEventListener("load", function (event) {
       event.currentTarget.removeEventListener("load", arguments.callee, true);
       cb();
     }, true);
@@ -54,49 +53,49 @@ function test() {
         EventUtils.synthesizeKey("VK_BACK_SPACE", {});
       });
     }, false);
     gURLBar.focus();
   }
 
   function prepareDeletedURLTab(cb) {
     gBrowser.selectedTab = deletedURLTab;
-    is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to deletedURLTab');
+    is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after initial switch to deletedURLTab');
 
     // simulate the user removing the whole url from the location bar
     gPrefService.setBoolPref("browser.urlbar.clickSelectsAll", true);
 
     urlbarBackspace(function () {
-      is(gURLBar.value, "", 'gURLBar.value should be "" (just set)');
+      is(gURLBar.textValue, "", 'gURLBar.textValue should be "" (just set)');
       if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll"))
         gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
       cb();
     });
   }
 
   function prepareFullURLTab(cb) {
     gBrowser.selectedTab = fullURLTab;
-    is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to fullURLTab');
+    is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after initial switch to fullURLTab');
     cb();
   }
 
   function preparePartialURLTab(cb) {
     gBrowser.selectedTab = partialURLTab;
-    is(gURLBar.value, testURL, 'gURLBar.value should be testURL after initial switch to partialURLTab');
+    is(gURLBar.textValue, testURL, 'gURLBar.textValue should be testURL after initial switch to partialURLTab');
 
     // simulate the user removing part of the url from the location bar
     gPrefService.setBoolPref("browser.urlbar.clickSelectsAll", false);
 
     var deleted = 0;
     urlbarBackspace(function () {
       deleted++;
       if (deleted < charsToDelete) {
         urlbarBackspace(arguments.callee);
       } else {
-        is(gURLBar.value, testPartialURL, "gURLBar.value should be testPartialURL (just set)");
+        is(gURLBar.textValue, testPartialURL, "gURLBar.textValue should be testPartialURL (just set)");
         if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll"))
           gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
         cb();
       }
     });
   }
 
   function runTests() {
--- a/browser/base/content/test/general/browser_bug556061.js
+++ b/browser/base/content/test/general/browser_bug556061.js
@@ -26,38 +26,38 @@ function cleanup() {
 }
 
 let tests = [
   {
     expected: testURL,
     setup: function() {
       gURLBar.value = testActionURL;
       gURLBar.valueIsTyped = true;
-    is(gURLBar._value, testActionURL, "gURLBar starts with the correct real value");
-    is(gURLBar.value, testURL, "gURLBar starts with the correct display value");
+      is(gURLBar.value, testActionURL, "gURLBar starts with the correct real value");
+      is(gURLBar.textValue, testURL, "gURLBar starts with the correct display value");
 
       // Focus the urlbar so we can select it all & copy
       gURLBar.focus();
       gURLBar.select();
       goDoCommand("cmd_copy");
     },
     success: function() {
-      is(gURLBar._value, testActionURL, "gURLBar.value didn't change when copying");
+      is(gURLBar.value, testActionURL, "gURLBar.value didn't change when copying");
     }
   },
   {
     expected: testURL.substring(0, 10),
     setup: function() {
       // Set selectionStart/End manually and make sure it matches the substring
       gURLBar.selectionStart = 0;
       gURLBar.selectionEnd = 10;
       goDoCommand("cmd_copy");
     },
     success: function() {
-      is(gURLBar._value, testActionURL, "gURLBar.value didn't change when copying");
+      is(gURLBar.value, testActionURL, "gURLBar.value didn't change when copying");
     }
   },
   {
     expected: testURL,
     setup: function() {
       // Setup for cut test...
       // Select all
       gURLBar.select();
@@ -69,18 +69,18 @@ let tests = [
   },
   {
     expected: testURL.substring(testURL.length - 10, testURL.length),
     setup: function() {
       // Reset urlbar value
       gURLBar.value = testActionURL;
       gURLBar.valueIsTyped = true;
       // Sanity check that we have the right value
-      is(gURLBar._value, testActionURL, "gURLBar starts with the correct real value");
-      is(gURLBar.value, testURL, "gURLBar starts with the correct display value");
+      is(gURLBar.value, testActionURL, "gURLBar starts with the correct real value");
+      is(gURLBar.textValue, testURL, "gURLBar starts with the correct display value");
 
       // Now just select part of the value & cut that.
       gURLBar.selectionStart = testURL.length - 10;
       gURLBar.selectionEnd = testURL.length;
       goDoCommand("cmd_cut");
     },
     success: function() {
       is(gURLBar.value, testURL.substring(0, testURL.length - 10), "gURLBar.value has the correct value");
--- a/browser/base/content/test/general/browser_canonizeURL.js
+++ b/browser/base/content/test/general/browser_canonizeURL.js
@@ -40,15 +40,17 @@ function testNext() {
 
         executeSoon(testNext);
       }
     }
   });
 
   gURLBar.addEventListener("focus", function onFocus() {
     gURLBar.removeEventListener("focus", onFocus);
+    gURLBar.inputField.value = inputValue.slice(0, -1);
+    EventUtils.synthesizeKey(inputValue.slice(-1) , {});
     EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
   });
 
   gBrowser.selectedBrowser.focus();
-  gURLBar.inputField.value = inputValue;
   gURLBar.focus();
+
 }
--- a/browser/base/content/test/general/browser_locationBarCommand.js
+++ b/browser/base/content/test/general/browser_locationBarCommand.js
@@ -32,20 +32,20 @@ function runAltLeftClickTest() {
 }
 
 function runShiftLeftClickTest() {
   let listener = new BrowserWindowListener(getBrowserURL(), function(aWindow) {
     Services.wm.removeListener(listener);
     addPageShowListener(aWindow.gBrowser.selectedBrowser, function() {
       executeSoon(function () {
         info("URL should be loaded in a new window");
-        is(gURLBar.value, "", "Urlbar reverted to original value");       
+        is(gURLBar.value, "", "Urlbar reverted to original value");
         is(gFocusManager.focusedElement, null, "There should be no focused element");
         is(gFocusManager.focusedWindow, aWindow.gBrowser.contentWindow, "Content window should be focused");
-        is(aWindow.gURLBar.value, TEST_VALUE, "New URL is loaded in new window");
+        is(aWindow.gURLBar.textValue, TEST_VALUE, "New URL is loaded in new window");
 
         aWindow.close();
 
         // Continue testing when the original window has focus again.
         whenWindowActivated(window, runNextTest);
       });
     }, "http://example.com/");
   });
@@ -56,17 +56,17 @@ function runShiftLeftClickTest() {
 }
 
 function runNextTest() {
   let test = gTests.shift();
   if (!test) {
     finish();
     return;
   }
-  
+
   info("Running test: " + test.desc);
   // Tab will be blank if test.startValue is null
   let tab = gBrowser.selectedTab = gBrowser.addTab(test.startValue);
   addPageShowListener(gBrowser.selectedBrowser, function() {
     triggerCommand(test.click, test.event);
     test.check(tab);
 
     // Clean up
@@ -101,17 +101,17 @@ let gTests = [
   { desc: "Shift+Ctrl/Cmd left click on go button",
     click: true,
     event: { accelKey: true, shiftKey: true },
     check: function(aTab) {
       info("URL should be loaded in a new background tab");
       is(gURLBar.value, "", "Urlbar reverted to original value");
       ok(!gURLBar.focused, "Urlbar is no longer focused after urlbar command");
       is(gBrowser.selectedTab, aTab, "Focus did not change to the new tab");
-    
+
       // Select the new background tab
       gBrowser.selectedTab = gBrowser.selectedTab.nextSibling;
       is(gURLBar.value, TEST_VALUE, "New URL is loaded in new tab");
     }
   },
 
   { desc: "Simple return keypress",
     event: {},
@@ -138,17 +138,17 @@ let gTests = [
 let gGoButton = document.getElementById("urlbar-go-button");
 function triggerCommand(aClick, aEvent) {
   gURLBar.value = TEST_VALUE;
   gURLBar.focus();
 
   if (aClick) {
     is(gURLBar.getAttribute("pageproxystate"), "invalid",
        "page proxy state must be invalid for go button to be visible");
-    EventUtils.synthesizeMouseAtCenter(gGoButton, aEvent); 
+    EventUtils.synthesizeMouseAtCenter(gGoButton, aEvent);
   }
   else
     EventUtils.synthesizeKey("VK_RETURN", aEvent);
 }
 
 /* Checks that the URL was loaded in the current tab */
 function checkCurrent(aTab) {
   info("URL should be loaded in the current tab");
--- a/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js
+++ b/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js
@@ -36,14 +36,14 @@ function testNext() {
     finish();
     return;
   }
 
   let [inputValue, expectedURL] = pairs.shift();
 
   gURLBar.focus();
   paste(inputValue, function() {
-    is(gURLBar.value, expectedURL, "entering '" + inputValue + "' strips relevant bits.");
+    is(gURLBar.textValue, expectedURL, "entering '" + inputValue + "' strips relevant bits.");
 
     setTimeout(testNext, 0);
   });
 }
 
--- a/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js
+++ b/browser/base/content/test/general/browser_urlbarAutoFillTrimURLs.js
@@ -22,45 +22,46 @@ function test() {
   // Adding a tab would hit switch-to-tab, so it's safer to just add a visit.
   let callback = {
     handleError:  function () {},
     handleResult: function () {},
     handleCompletion: continue_test
   };
   let history = Cc["@mozilla.org/browser/history;1"]
                   .getService(Ci.mozIAsyncHistory);
-  history.updatePlaces({ uri: NetUtil.newURI("http://www.autofilltrimurl.com/")
+  history.updatePlaces({ uri: NetUtil.newURI("http://www.autofilltrimurl.com/whatever")
                        , visits: [ { transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED
                                    , visitDate:      Date.now() * 1000
                                    } ]
                        }, callback);
 }
 
 function continue_test() {
   function test_autoFill(aTyped, aExpected, aCallback) {
     info(`Testing with input: ${aTyped}`);
     gURLBar.inputField.value = aTyped.substr(0, aTyped.length - 1);
     gURLBar.focus();
     gURLBar.selectionStart = aTyped.length - 1;
     gURLBar.selectionEnd = aTyped.length - 1;
 
     EventUtils.synthesizeKey(aTyped.substr(-1), {});
     waitForSearchComplete(function () {
-      is(gURLBar.value, aExpected, "trim was applied correctly");
+      info(`Got value: ${gURLBar.value}`);
+      is(gURLBar.value, aExpected, "Autofilled value is as expected");
       aCallback();
     });
   }
 
   test_autoFill("http://", "http://", function () {
     test_autoFill("http://au", "http://autofilltrimurl.com/", function () {
       test_autoFill("http://www.autofilltrimurl.com", "http://www.autofilltrimurl.com/", function () {
         // Now ensure selecting from the popup correctly trims.
-        is(gURLBar.controller.matchCount, 1, "Found the expected number of matches");
+        is(gURLBar.controller.matchCount, 2, "Found the expected number of matches");
         EventUtils.synthesizeKey("VK_DOWN", {});
-        is(gURLBar.value, "www.autofilltrimurl.com", "trim was applied correctly");
+        is(gURLBar.textValue, "www.autofilltrimurl.com/whatever", "trim was applied correctly");
         gURLBar.closePopup();
         waitForClearHistory(finish);
       });
     });
   });
 }
 
 function waitForClearHistory(aCallback) {
--- a/browser/base/content/test/general/browser_urlbarCopying.js
+++ b/browser/base/content/test/general/browser_urlbarCopying.js
@@ -151,17 +151,17 @@ function nextTest() {
   else
     runTest(test, nextTest);
 }
 
 function runTest(test, cb) {
   function doCheck() {
     if (test.setURL || test.loadURL) {
       gURLBar.valueIsTyped = !!test.setURL;
-      is(gURLBar.value, test.expectedURL, "url bar value set");
+      is(gURLBar.textValue, test.expectedURL, "url bar value set");
     }
 
     testCopy(test.copyVal, test.copyExpected, cb);
   }
 
   if (test.loadURL) {
     loadURL(test.loadURL, doCheck);
   } else {
@@ -175,17 +175,17 @@ function testCopy(copyVal, targetValue, 
   info("Expecting copy of: " + targetValue);
   waitForClipboard(targetValue, function () {
     gURLBar.focus();
     if (copyVal) {
       let startBracket = copyVal.indexOf("<");
       let endBracket = copyVal.indexOf(">");
       if (startBracket == -1 || endBracket == -1 ||
           startBracket > endBracket ||
-          copyVal.replace("<", "").replace(">", "") != gURLBar.value) {
+          copyVal.replace("<", "").replace(">", "") != gURLBar.textValue) {
         ok(false, "invalid copyVal: " + copyVal);
       }
       gURLBar.selectionStart = startBracket;
       gURLBar.selectionEnd = endBracket - 1;
     } else {
       gURLBar.select();
     }
 
--- a/browser/base/content/test/general/browser_urlbarEnter.js
+++ b/browser/base/content/test/general/browser_urlbarEnter.js
@@ -46,22 +46,22 @@ let gTests = [
 
   { desc: "Alt+Return keypress",
     event: { altKey: true },
     check: checkNewTab,
   },
 ]
 
 function checkCurrent(aTab) {
-  is(gURLBar.value, TEST_VALUE, "Urlbar should preserve the value on return keypress");
+  is(gURLBar.textValue, TEST_VALUE, "Urlbar should preserve the value on return keypress");
   is(gBrowser.selectedTab, aTab, "New URL was loaded in the current tab");
 }
 
 function checkNewTab(aTab) {
-  is(gURLBar.value, TEST_VALUE, "Urlbar should preserve the value on return keypress");
+  is(gURLBar.textValue, TEST_VALUE, "Urlbar should preserve the value on return keypress");
   isnot(gBrowser.selectedTab, aTab, "New URL was loaded in a new tab");
 }
 
 function addPageShowListener(aFunc) {
   gBrowser.selectedBrowser.addEventListener("pageshow", function loadListener() {
     gBrowser.selectedBrowser.removeEventListener("pageshow", loadListener, false);
     aFunc();
   });
--- a/browser/base/content/test/general/browser_urlbarStop.js
+++ b/browser/base/content/test/general/browser_urlbarStop.js
@@ -6,33 +6,33 @@ function test() {
 
   gBrowser.selectedTab = gBrowser.addTab(goodURL);
   gBrowser.selectedBrowser.addEventListener("load", onload, true);
 }
 
 function onload() {
   gBrowser.selectedBrowser.removeEventListener("load", onload, true);
 
-  is(gURLBar.value, gURLBar.trimValue(goodURL), "location bar reflects loaded page");
+  is(gURLBar.textValue, gURLBar.trimValue(goodURL), "location bar reflects loaded page");
 
   typeAndSubmit(badURL);
-  is(gURLBar.value, gURLBar.trimValue(badURL), "location bar reflects loading page");
+  is(gURLBar.textValue, gURLBar.trimValue(badURL), "location bar reflects loading page");
 
   gBrowser.contentWindow.stop();
-  is(gURLBar.value, gURLBar.trimValue(goodURL), "location bar reflects loaded page after stop()");
+  is(gURLBar.textValue, gURLBar.trimValue(goodURL), "location bar reflects loaded page after stop()");
   gBrowser.removeCurrentTab();
 
   gBrowser.selectedTab = gBrowser.addTab("about:blank");
-  is(gURLBar.value, "", "location bar is empty");
+  is(gURLBar.textValue, "", "location bar is empty");
 
   typeAndSubmit(badURL);
-  is(gURLBar.value, gURLBar.trimValue(badURL), "location bar reflects loading page");
+  is(gURLBar.textValue, gURLBar.trimValue(badURL), "location bar reflects loading page");
 
   gBrowser.contentWindow.stop();
-  is(gURLBar.value, gURLBar.trimValue(badURL), "location bar reflects stopped page in an empty tab");
+  is(gURLBar.textValue, gURLBar.trimValue(badURL), "location bar reflects stopped page in an empty tab");
   gBrowser.removeCurrentTab();
 
   finish();
 }
 
 function typeAndSubmit(value) {
   gBrowser.userTypedValue = value;
   URLBarSetURI();
--- a/browser/base/content/test/general/browser_urlbarTrimURLs.js
+++ b/browser/base/content/test/general/browser_urlbarTrimURLs.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 function testVal(originalValue, targetValue) {
   gURLBar.value = originalValue;
   gURLBar.valueIsTyped = false;
-  is(gURLBar.value, targetValue || originalValue, "url bar value set");
+  is(gURLBar.textValue, targetValue || originalValue, "url bar value set");
 }
 
 function test() {
   const prefname = "browser.urlbar.trimURLs";
 
   gBrowser.selectedTab = gBrowser.addTab();
 
   registerCleanupFunction(function () {
@@ -91,15 +91,15 @@ function test() {
     });
   }, true);
 
   gBrowser.loadURI("http://example.com/");
 }
 
 function testCopy(originalValue, targetValue, cb) {
   waitForClipboard(targetValue, function () {
-    is(gURLBar.value, originalValue, "url bar copy value set");
+    is(gURLBar.textValue, originalValue, "url bar copy value set");
 
     gURLBar.focus();
     gURLBar.select();
     goDoCommand("cmd_copy");
   }, cb, cb);
 }
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -1,16 +1,18 @@
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
   "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
   "resource://gre/modules/PlacesUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
+  "resource://testing-common/PlacesTestUtils.jsm");
 
 function closeAllNotifications () {
   let notificationBox = document.getElementById("global-notificationbox");
 
   if (!notificationBox || !notificationBox.currentNotification) {
     return Promise.resolve();
   }
 
--- a/browser/components/sessionstore/test/browser_522545.js
+++ b/browser/components/sessionstore/test/browser_522545.js
@@ -188,26 +188,26 @@ function test() {
     };
 
     waitForBrowserState(state, function() {
       let browser = gBrowser.selectedBrowser;
       // Make sure this tab isn't loading and state is clear before we test.
       is(browser.userTypedValue, null, "userTypedValue is empty to start");
       is(browser.userTypedClear, 0, "userTypedClear is 0 to start");
 
-      gURLBar.value = "example.org";
-      let event = document.createEvent("Events");
-      event.initEvent("input", true, false);
-      gURLBar.dispatchEvent(event);
+      let inputText = "example.org";
+      gURLBar.focus();
+      gURLBar.value = inputText.slice(0, -1);
+      EventUtils.synthesizeKey(inputText.slice(-1) , {});
 
       executeSoon(function () {
         is(browser.userTypedValue, "example.org",
-           "userTypedValue was set when changing gURLBar.value");
+           "userTypedValue was set when changing URLBar value");
         is(browser.userTypedClear, 0,
-           "userTypedClear was not changed when changing gURLBar.value");
+           "userTypedClear was not changed when changing URLBar value");
 
         // Now make sure ss gets these values too
         let newState = JSON.parse(ss.getBrowserState());
         is(newState.windows[0].tabs[0].userTypedValue, "example.org",
            "sessionstore got correct userTypedValue");
         is(newState.windows[0].tabs[0].userTypedClear, 0,
            "sessionstore got correct userTypedClear");
         runNextTest();
@@ -230,17 +230,17 @@ function test() {
     waitForBrowserState(state, function() {
       let browser = gBrowser.selectedBrowser;
       is(browser.currentURI.spec, "http://example.com/",
          "userTypedClear=2 caused userTypedValue to be loaded");
       is(browser.userTypedValue, null,
          "userTypedValue was null after loading a URI");
       is(browser.userTypedClear, 0,
          "userTypeClear reset to 0");
-      is(gURLBar.value, gURLBar.trimValue("http://example.com/"),
+      is(gURLBar.textValue, gURLBar.trimValue("http://example.com/"),
          "Address bar's value set after loading URI");
       runNextTest();
     });
   }
 
 
   let tests = [test_newTabFocused, test_newTabNotFocused,
                test_existingSHEnd_noClear, test_existingSHMiddle_noClear,
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/PlacesTestUtils.jsm
@@ -0,0 +1,76 @@
+"use strict";
+
+this.EXPORTED_SYMBOLS = [
+  "PlacesTestUtils",
+];
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+  "resource://gre/modules/PlacesUtils.jsm");
+
+
+this.PlacesTestUtils = Object.freeze({
+  /**
+   * Asynchronously adds visits to a page.
+   *
+   * @param aPlaceInfo
+   *        Can be an nsIURI, in such a case a single LINK visit will be added.
+   *        Otherwise can be an object describing the visit to add, or an array
+   *        of these objects:
+   *          { uri: nsIURI of the page,
+   *            [optional] transition: one of the TRANSITION_* from nsINavHistoryService,
+   *            [optional] title: title of the page,
+   *            [optional] visitDate: visit date in microseconds from the epoch
+   *            [optional] referrer: nsIURI of the referrer for this visit
+   *          }
+   *
+   * @return {Promise}
+   * @resolves When all visits have been added successfully.
+   * @rejects JavaScript exception.
+   */
+  addVisits(placeInfo) {
+    return new Promise((resolve, reject) => {
+      let places = [];
+      if (placeInfo instanceof Ci.nsIURI) {
+        places.push({ uri: placeInfo });
+      }
+      else if (Array.isArray(placeInfo)) {
+        places = places.concat(placeInfo);
+      } else {
+        places.push(placeInfo)
+      }
+
+      // Create mozIVisitInfo for each entry.
+      let now = Date.now();
+      for (let place of places) {
+        if (typeof place.title != "string") {
+          place.title = "test visit for " + place.uri.spec;
+        }
+        place.visits = [{
+          transitionType: place.transition === undefined ? Ci.nsINavHistoryService.TRANSITION_LINK
+                                                             : place.transition,
+          visitDate: place.visitDate || (now++) * 1000,
+          referrerURI: place.referrer
+        }];
+      }
+
+      PlacesUtils.asyncHistory.updatePlaces(
+        places,
+        {
+          handleError: function AAV_handleError(resultCode, placeInfo) {
+            let ex = new Components.Exception("Unexpected error in adding visits.",
+                                              resultCode);
+            reject(ex);
+          },
+          handleResult: function () {},
+          handleCompletion: function UP_handleCompletion() {
+            resolve();
+          }
+        }
+      );
+    });
+  },
+});
--- a/toolkit/components/places/tests/moz.build
+++ b/toolkit/components/places/tests/moz.build
@@ -1,16 +1,20 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['cpp']
 
+TESTING_JS_MODULES += [
+    'PlacesTestUtils.jsm',
+]
+
 XPCSHELL_TESTS_MANIFESTS += [
     'autocomplete/xpcshell.ini',
     'bookmarks/xpcshell.ini',
     'expiration/xpcshell.ini',
     'favicons/xpcshell.ini',
     'history/xpcshell.ini',
     'inline/xpcshell.ini',
     'migration/xpcshell.ini',
--- a/toolkit/content/widgets/autocomplete.xml
+++ b/toolkit/content/widgets/autocomplete.xml
@@ -1124,17 +1124,17 @@ extends="chrome://global/content/binding
           <![CDATA[
           var controller = this.mInput.controller;
           var matchCount = this._matchCount;
           var existingItemsCount = this.richlistbox.childNodes.length;
 
           // Process maxRows per chunk to improve performance and user experience
           for (let i = 0; i < this.maxRows; i++) {
             if (this._currentIndex >= matchCount)
-              return;
+              break;
 
             var item;
 
             // trim the leading/trailing whitespace
             var trimmedSearchString = controller.searchString.replace(/^\s+/, "").replace(/\s+$/, "");
 
             // Unescape the URI spec for showing as an entry in the popup
             let url = Components.classes["@mozilla.org/intl/texttosuburi;1"].
@@ -1180,18 +1180,24 @@ extends="chrome://global/content/binding
               // in the xbl constructor
               item.className = "autocomplete-richlistitem";
               this.richlistbox.appendChild(item);
             }
 
             this._currentIndex++;
           }
 
-          // yield after each batch of items so that typing the url bar is responsive
-          setTimeout(function (self) { self._appendCurrentResult(); }, 0, this);
+          if (typeof this.onResultsAdded == "function")
+            this.onResultsAdded();
+
+          if (this._currentIndex < matchCount) {
+            // yield after each batch of items so that typing the url bar is
+            // responsive
+            setTimeout(function (self) { self._appendCurrentResult(); }, 0, this);
+          }
         ]]>
         </body>
       </method>
 
       <method name="selectBy">
         <parameter name="aReverse"/>
         <parameter name="aPage"/>
         <body>