Bug 1654862 - Tests. r=adw
authorMarco Bonardo <mbonardo@mozilla.com>
Sat, 08 Aug 2020 21:07:39 +0000
changeset 544040 83b89001fa0c095cb213d5ef516dd56b06675008
parent 544039 b9a3af079f0e1cd8eb3f8c2b4dbfd5be776173a9
child 544041 80da3bcb8ef3fd058ab2220c249ae07a67db63af
push id123771
push userdwillcoxon@mozilla.com
push dateSun, 09 Aug 2020 03:27:01 +0000
treeherderautoland@83b89001fa0c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersadw
bugs1654862
milestone81.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 1654862 - Tests. r=adw Differential Revision: https://phabricator.services.mozilla.com/D86386
browser/components/urlbar/UrlbarProviderSearchSuggestions.jsm
browser/components/urlbar/tests/UrlbarTestUtils.jsm
browser/components/urlbar/tests/browser/browser.ini
browser/components/urlbar/tests/browser/browser_oneOffs_searchSuggestions.js
browser/components/urlbar/tests/browser/browser_searchModeIndicator.js
browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js
browser/components/urlbar/tests/unit/head.js
--- a/browser/components/urlbar/UrlbarProviderSearchSuggestions.jsm
+++ b/browser/components/urlbar/UrlbarProviderSearchSuggestions.jsm
@@ -393,16 +393,17 @@ class ProviderSearchSuggestions extends 
 
     for (let entry of fetchData.local) {
       results.push(
         new UrlbarResult(
           UrlbarUtils.RESULT_TYPE.SEARCH,
           UrlbarUtils.RESULT_SOURCE.HISTORY,
           ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
             engine: engine.name,
+            isSearchHistory: true,
             suggestion: [entry.value, UrlbarUtils.HIGHLIGHT.SUGGESTED],
             lowerCaseSuggestion: entry.value.toLocaleLowerCase(),
           })
         )
       );
     }
 
     // If we don't return many results, then keep track of the query. If the
--- a/browser/components/urlbar/tests/UrlbarTestUtils.jsm
+++ b/browser/components/urlbar/tests/UrlbarTestUtils.jsm
@@ -46,16 +46,17 @@ var UrlbarTestUtils = {
    * and SimpleTest. Note this initialization is not enforced, thus helpers
    * should always check _testScope and provide a fallback path.
    * @param {object} scope The global scope where tests are being run.
    */
   init(scope) {
     this._testScope = scope;
     if (scope) {
       this.Assert = scope.Assert;
+      this.EventUtils = scope.EventUtils;
     }
   },
 
   /**
    * Waits to a search to be complete.
    * @param {object} win The window containing the urlbar
    * @returns {Promise} Resolved when done.
    */
@@ -367,16 +368,17 @@ var UrlbarTestUtils = {
 
   /**
    * Asserts that the input is in a given search mode, or no search mode.
    *
    * @param {Window} window
    *   The browser window.
    * @param {object} expectedSearchMode
    *   The expected search mode object.
+   * @note Can only be used if UrlbarTestUtils has been initialized with init().
    */
   assertSearchMode(window, expectedSearchMode) {
     this.Assert.equal(
       !!window.gURLBar.searchMode,
       window.gURLBar.hasAttribute("searchmode"),
       "Urlbar should never be in search mode without the corresponding attribute."
     );
 
@@ -432,16 +434,106 @@ var UrlbarTestUtils = {
         window.document.l10n.getAttributes(element),
         expectedL10n,
         "Expected l10n"
       );
     }
   },
 
   /**
+   * Enters search mode by clicking the first one-off.
+   * @param {object} window
+   * @note Can only be used if UrlbarTestUtils has been initialized with init().
+   */
+  async enterSearchMode(window) {
+    // Ensure any pending query is complete.
+    await this.promiseSearchComplete(window);
+    // Ensure oneoffbuttons
+    let oneOffs = this.getOneOffSearchButtons(window).getSelectableButtons(
+      true
+    );
+    this.EventUtils.synthesizeMouseAtCenter(oneOffs[0], {});
+    await this.promiseSearchComplete(window);
+    this.Assert.ok(this.isPopupOpen(window), "Urlbar view is still open.");
+    this.assertSearchMode(window, {
+      source: UrlbarUtils.RESULT_SOURCE.SEARCH,
+      engineName: oneOffs[0].engine.name,
+    });
+  },
+
+  /**
+   * Exits search mode.
+   * @param {object} window
+   * @param {boolean} options.backspace
+   *   Exits search mode by backspacing at the beginning of the search string.
+   * @param {boolean} options.clickClose
+   *   Exits search mode by clicking the close button on the search mode
+   *   indicator.
+   * @param {boolean} [waitForSearch]
+   *   Whether the test should wait for a search after exiting search mode.
+   *   Defaults to true.
+   * @note One and only one of `backspace` and `clickClose` should be passed
+   *       as true.
+   * @note Can only be used if UrlbarTestUtils has been initialized with init().
+   */
+  async exitSearchMode(
+    window,
+    { backspace, clickClose, waitForSearch = true }
+  ) {
+    let urlbar = window.gURLBar;
+    // If the Urlbar is not extended, ignore the clickClose parameter. The close
+    // button is not clickable in this state. This state might be encountered on
+    // Linux, where prefers-reduced-motion is enabled in automation.
+    if (!urlbar.hasAttribute("breakout-extend") && clickClose) {
+      if (waitForSearch) {
+        let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
+        urlbar.setSearchMode(null);
+        await searchPromise;
+      } else {
+        urlbar.setSearchMode(null);
+      }
+      return;
+    }
+
+    if (backspace) {
+      let urlbarValue = urlbar.value;
+      urlbar.selectionStart = urlbar.selectionEnd = 0;
+      if (waitForSearch) {
+        let searchPromise = this.promiseSearchComplete(window);
+        this.EventUtils.synthesizeKey("KEY_Backspace");
+        await searchPromise;
+      } else {
+        this.EventUtils.synthesizeKey("KEY_Backspace");
+      }
+      this.Assert.equal(
+        urlbar.value,
+        urlbarValue,
+        "Urlbar value hasn't changed."
+      );
+      this.assertSearchMode(window, null);
+    } else if (clickClose) {
+      // We need to hover the indicator to make the close button clickable in the
+      // test.
+      let indicator = urlbar.querySelector("#urlbar-search-mode-indicator");
+      this.EventUtils.synthesizeMouseAtCenter(indicator, { type: "mouseover" });
+      let closeButton = urlbar.querySelector(
+        "#urlbar-search-mode-indicator-close"
+      );
+      if (waitForSearch) {
+        let searchPromise = this.promiseSearchComplete(window);
+        this.EventUtils.synthesizeMouseAtCenter(closeButton, {});
+        await searchPromise;
+      } else {
+        this.EventUtils.synthesizeMouseAtCenter(closeButton, {});
+      }
+      this.assertSearchMode(window, null);
+    }
+  },
+
+  /**
    * Returns the userContextId (container id) for the last search.
    * @param {object} win The browser window
    * @returns {Promise} resolved when fetching is complete
    * @resolves {number} a userContextId
    */
   async promiseUserContextId(win) {
     const defaultId = Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
     let context = await win.gURLBar.lastQueryContextPromise;
--- a/browser/components/urlbar/tests/browser/browser.ini
+++ b/browser/components/urlbar/tests/browser/browser.ini
@@ -131,16 +131,20 @@ run-if = e10s
 [browser_remotetab.js]
 [browser_remove_match.js]
 [browser_removeUnsafeProtocolsFromURLBarPaste.js]
 [browser_restoreEmptyInput.js]
 [browser_resultSpan.js]
 [browser_retainedResultsOnFocus.js]
 [browser_revert.js]
 [browser_searchFunction.js]
+[browser_searchMode_suggestions.js]
+support-files =
+  searchSuggestionEngine.xml
+  searchSuggestionEngine.sjs
 [browser_searchModeIndicator.js]
 support-files =
   searchSuggestionEngine.xml
   searchSuggestionEngine.sjs
 [browser_searchSettings.js]
 [browser_searchSingleWordNotification.js]
 [browser_searchSuggestions.js]
 support-files =
--- a/browser/components/urlbar/tests/browser/browser_oneOffs_searchSuggestions.js
+++ b/browser/components/urlbar/tests/browser/browser_oneOffs_searchSuggestions.js
@@ -225,21 +225,24 @@ add_task(async function test_selectOneOf
     let heuristicResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
     Assert.ok(
       BrowserTestUtils.is_visible(heuristicResult.element.action),
       "The heuristic action should be visible because the result is selected"
     );
 
     // Now click the second suggestion.
     let result = await UrlbarTestUtils.getDetailsOfResultAt(window, index + 1);
-
+    // Note search history results don't change their engine when the selected
+    // one-off button changes!
     let resultsPromise = BrowserTestUtils.browserLoaded(
       gBrowser.selectedBrowser,
       false,
-      `http://localhost:20709/?terms=foobar`
+      usingFormHistory
+        ? `http://mochi.test:8888/?terms=foobar`
+        : `http://localhost:20709/?terms=foobar`
     );
     EventUtils.synthesizeMouseAtCenter(result.element.row, {});
     await resultsPromise;
   });
 });
 
 add_task(async function overridden_engine_not_reused() {
   info(
--- a/browser/components/urlbar/tests/browser/browser_searchModeIndicator.js
+++ b/browser/components/urlbar/tests/browser/browser_searchModeIndicator.js
@@ -40,97 +40,16 @@ add_task(async function setup() {
       ["browser.search.separatePrivateDefault.ui.enabled", false],
       ["browser.urlbar.update2", true],
       ["browser.urlbar.update2.localOneOffs", true],
       ["browser.urlbar.update2.oneOffsRefresh", true],
     ],
   });
 });
 
-/**
- * Enters search mode by clicking the first one-off.
- * @param {object} window
- */
-async function enterSearchMode(window) {
-  let oneOffs = UrlbarTestUtils.getOneOffSearchButtons(
-    window
-  ).getSelectableButtons(true);
-  let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
-  EventUtils.synthesizeMouseAtCenter(oneOffs[0], {});
-  await searchPromise;
-  Assert.ok(UrlbarTestUtils.isPopupOpen(window), "Urlbar view is still open.");
-  UrlbarTestUtils.assertSearchMode(window, {
-    source: UrlbarUtils.RESULT_SOURCE.SEARCH,
-    engineName: oneOffs[0].engine.name,
-  });
-}
-
-/**
- * Exits search mode.
- * @param {object} window
- * @param {boolean} options.backspace
- *   Exits search mode by backspacing at the beginning of the search string.
- * @param {boolean} options.clickClose
- *   Exits search mode by clicking the close button on the search mode
- *   indicator.
- * @param {boolean} [waitForSearch]
- *   Whether the test should wait for a search after exiting search mode.
- *   Defaults to true.
- * @note One and only one of `backspace` and `clickClose` should be passed
- *       as true.
- */
-async function exitSearchMode(
-  window,
-  { backspace, clickClose, waitForSearch = true }
-) {
-  // If the Urlbar is not extended, ignore the clickClose parameter. The close
-  // button is not clickable in this state. This state might be encountered on
-  // Linux, where prefers-reduced-motion is enabled in automation.
-  if (!gURLBar.hasAttribute("breakout-extend") && clickClose) {
-    if (waitForSearch) {
-      let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
-      gURLBar.setSearchMode(null);
-      await searchPromise;
-    } else {
-      gURLBar.setSearchMode(null);
-    }
-    return;
-  }
-
-  if (backspace) {
-    let urlbarValue = gURLBar.value;
-    gURLBar.selectionStart = gURLBar.selectionEnd = 0;
-    if (waitForSearch) {
-      let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
-      EventUtils.synthesizeKey("KEY_Backspace");
-      await searchPromise;
-    } else {
-      EventUtils.synthesizeKey("KEY_Backspace");
-    }
-    Assert.equal(gURLBar.value, urlbarValue, "Urlbar value hasn't changed.");
-    UrlbarTestUtils.assertSearchMode(window, null);
-  } else if (clickClose) {
-    // We need to hover the indicator to make the close button clickable in the
-    // test.
-    let indicator = gURLBar.querySelector("#urlbar-search-mode-indicator");
-    EventUtils.synthesizeMouseAtCenter(indicator, { type: "mouseover" });
-    let closeButton = gURLBar.querySelector(
-      "#urlbar-search-mode-indicator-close"
-    );
-    if (waitForSearch) {
-      let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
-      EventUtils.synthesizeMouseAtCenter(closeButton, {});
-      await searchPromise;
-    } else {
-      EventUtils.synthesizeMouseAtCenter(closeButton, {});
-    }
-    UrlbarTestUtils.assertSearchMode(window, null);
-  }
-}
-
 async function verifySearchModeResultsAdded(window) {
   Assert.equal(
     UrlbarTestUtils.getResultCount(window),
     3,
     "There should be three results."
   );
   let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
   Assert.equal(
@@ -168,70 +87,76 @@ async function verifySearchModeResultsRe
 // Tests that the indicator is removed when backspacing at the beginning of
 // the search string.
 add_task(async function backspace() {
   // View open, with string.
   await UrlbarTestUtils.promiseAutocompleteResultPopup({
     window,
     value: TEST_QUERY,
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
   await verifySearchModeResultsAdded(window);
-  await exitSearchMode(window, { backspace: true });
+  await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
   await verifySearchModeResultsRemoved(window);
   Assert.ok(UrlbarTestUtils.isPopupOpen(window), "Urlbar view is open.");
 
   // View open, no string.
   // Open Top Sites.
   await UrlbarTestUtils.promisePopupOpen(window, () => {
     if (gURLBar.getAttribute("pageproxystate") == "invalid") {
       gURLBar.handleRevert();
     }
     EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
   });
-  await enterSearchMode(window);
-  await exitSearchMode(window, { backspace: true, waitForSearch: false });
+  await UrlbarTestUtils.enterSearchMode(window);
+  await UrlbarTestUtils.exitSearchMode(window, {
+    backspace: true,
+    waitForSearch: false,
+  });
   Assert.ok(UrlbarTestUtils.isPopupOpen(window), "Urlbar view is open.");
 
   // View closed, with string.
   // Open Top Sites.
   await UrlbarTestUtils.promiseAutocompleteResultPopup({
     window,
     value: TEST_QUERY,
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
   await verifySearchModeResultsAdded(window);
   UrlbarTestUtils.promisePopupClose(window);
-  await exitSearchMode(window, { backspace: true });
+  await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
   await verifySearchModeResultsRemoved(window);
   Assert.ok(UrlbarTestUtils.isPopupOpen(window), "Urlbar view is now open.");
 
   // View closed, no string.
   await UrlbarTestUtils.promisePopupOpen(window, () => {
     if (gURLBar.getAttribute("pageproxystate") == "invalid") {
       gURLBar.handleRevert();
     }
     EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
   UrlbarTestUtils.promisePopupClose(window);
-  await exitSearchMode(window, { backspace: true, waitForSearch: false });
+  await UrlbarTestUtils.exitSearchMode(window, {
+    backspace: true,
+    waitForSearch: false,
+  });
   Assert.ok(
     !UrlbarTestUtils.isPopupOpen(window),
     "Urlbar view is still closed."
   );
 });
 
 // Tests the indicator's interaction with the ESC key.
 add_task(async function escape() {
   await UrlbarTestUtils.promiseAutocompleteResultPopup({
     window,
     value: TEST_QUERY,
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
   await verifySearchModeResultsAdded(window);
 
   EventUtils.synthesizeKey("KEY_Escape");
   Assert.ok(!UrlbarTestUtils.isPopupOpen(window, "UrlbarView is closed."));
   Assert.equal(gURLBar.value, TEST_QUERY, "Urlbar value hasn't changed.");
 
   let oneOffs = UrlbarTestUtils.getOneOffSearchButtons(
     window
@@ -249,87 +174,96 @@ add_task(async function escape() {
 
 // Tests that the indicator is removed when its close button is clicked.
 add_task(async function click_close() {
   // Clicking close with the view open.
   await UrlbarTestUtils.promiseAutocompleteResultPopup({
     window,
     value: TEST_QUERY,
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
   await verifySearchModeResultsAdded(window);
-  await exitSearchMode(window, { clickClose: true });
+  await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
   await verifySearchModeResultsRemoved(window);
 
   // Clicking close with the view closed.
   await UrlbarTestUtils.promiseAutocompleteResultPopup({
     window,
     value: TEST_QUERY,
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
   UrlbarTestUtils.promisePopupClose(window);
-  await exitSearchMode(window, { clickClose: true, waitForSearch: false });
+  await UrlbarTestUtils.exitSearchMode(window, {
+    clickClose: true,
+    waitForSearch: false,
+  });
 });
 
 // Tests that Accel+K enters search mode with the default engine.
 add_task(async function keyboard_shortcut() {
   UrlbarTestUtils.assertSearchMode(window, null);
   EventUtils.synthesizeKey("k", { accelKey: true });
   UrlbarTestUtils.assertSearchMode(window, {
     source: UrlbarUtils.RESULT_SOURCE.SEARCH,
     engineName: defaultEngine.name,
   });
-  await exitSearchMode(window, { clickClose: true, waitForSearch: false });
+  await UrlbarTestUtils.exitSearchMode(window, {
+    clickClose: true,
+    waitForSearch: false,
+  });
 });
 
 // Tests that the Tools:Search menu item enters search mode with the default
 // engine.
 add_task(async function menubar_item() {
   UrlbarTestUtils.assertSearchMode(window, null);
   let command = window.document.getElementById("Tools:Search");
   command.doCommand();
   UrlbarTestUtils.assertSearchMode(window, {
     source: UrlbarUtils.RESULT_SOURCE.SEARCH,
     engineName: defaultEngine.name,
   });
-  await exitSearchMode(window, { clickClose: true, waitForSearch: false });
+  await UrlbarTestUtils.exitSearchMode(window, {
+    clickClose: true,
+    waitForSearch: false,
+  });
 });
 
 // Tests that entering search mode invalidates pageproxystate and that
 // pageproxystate remains invalid after exiting search mode.
 add_task(async function invalidate_pageproxystate() {
   await BrowserTestUtils.withNewTab("about:robots", async function(browser) {
     await UrlbarTestUtils.promisePopupOpen(window, () => {
       EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
     });
     Assert.equal(gURLBar.getAttribute("pageproxystate"), "valid");
-    await enterSearchMode(window);
+    await UrlbarTestUtils.enterSearchMode(window);
     Assert.equal(
       gURLBar.getAttribute("pageproxystate"),
       "invalid",
       "Entering search mode should clear pageproxystate."
     );
     Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
-    await exitSearchMode(window, { clickClose: true });
+    await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
     Assert.equal(
       gURLBar.getAttribute("pageproxystate"),
       "invalid",
       "Pageproxystate should still be invalid after exiting search mode."
     );
   });
 });
 
 // Tests that the user doesn't get trapped in search mode if the update2 pref
 // is disabled after entering search mode.
 add_task(async function pref_flip_while_enabled() {
   await UrlbarTestUtils.promiseAutocompleteResultPopup({
     window,
     value: TEST_QUERY,
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
   await verifySearchModeResultsAdded(window);
   await SpecialPowers.pushPrefEnv({
     set: [["browser.urlbar.update2", false]],
   });
   UrlbarTestUtils.assertSearchMode(window, null);
   await SpecialPowers.popPrefEnv();
 });
 
@@ -352,17 +286,17 @@ add_task(async function tab_switch() {
   // userTypedValue is set and restored when we switch back to this tab.  This
   // isn't really necessary but it simulates the user's typing, and it also
   // means that we'll start a search when we switch back to this tab.
   await UrlbarTestUtils.promiseAutocompleteResultPopup({
     window,
     value: TEST_QUERY,
     fireInputEvent: true,
   });
-  await enterSearchMode(window);
+  await UrlbarTestUtils.enterSearchMode(window);
 
   // Switch to tab 1.  Search mode should be exited.
   await BrowserTestUtils.switchTab(gBrowser, tabs[1]);
   UrlbarTestUtils.assertSearchMode(window, null);
 
   // Switch back to tab 0.  We should do a search (for TEST_QUERY) and re-enter
   // search mode.
   let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
@@ -422,17 +356,17 @@ add_task(async function tab_switch() {
   searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
   await BrowserTestUtils.switchTab(gBrowser, tabs[2]);
   await searchPromise;
   UrlbarTestUtils.assertSearchMode(window, {
     source: localOneOff.source,
   });
 
   // Exit search mode.
-  await exitSearchMode(window, { clickClose: true });
+  await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
 
   // Switch to tab 0.  We should do a search and re-enter search mode.
   searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
   await BrowserTestUtils.switchTab(gBrowser, tabs[0]);
   await searchPromise;
   UrlbarTestUtils.assertSearchMode(window, {
     source: UrlbarUtils.RESULT_SOURCE.SEARCH,
     engineName: oneOffs[0].engine.name,
@@ -450,17 +384,17 @@ add_task(async function tab_switch() {
   await BrowserTestUtils.switchTab(gBrowser, tabs[0]);
   await searchPromise;
   UrlbarTestUtils.assertSearchMode(window, {
     source: UrlbarUtils.RESULT_SOURCE.SEARCH,
     engineName: oneOffs[0].engine.name,
   });
 
   // Exit search mode.
-  await exitSearchMode(window, { clickClose: true });
+  await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
 
   // Switch back to tab 2.  We should do a search but no search mode.
   searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
   await BrowserTestUtils.switchTab(gBrowser, tabs[2]);
   await searchPromise;
   UrlbarTestUtils.assertSearchMode(window, null);
 
   // Switch back to tab 0.  We should do a search but no search mode.
new file mode 100644
--- /dev/null
+++ b/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js
@@ -0,0 +1,173 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests search suggestions in search mode.
+ */
+
+const TEST_QUERY = "hello";
+const DEFAULT_ENGINE_NAME = "Test";
+const SUGGESTIONS_ENGINE_NAME = "searchSuggestionEngine.xml";
+
+let suggestionsEngine;
+let defaultEngine;
+
+add_task(async function setup() {
+  suggestionsEngine = await SearchTestUtils.promiseNewSearchEngine(
+    getRootDirectory(gTestPath) + SUGGESTIONS_ENGINE_NAME
+  );
+
+  let oldDefaultEngine = await Services.search.getDefault();
+  defaultEngine = await Services.search.addEngineWithDetails(
+    DEFAULT_ENGINE_NAME,
+    {
+      template: "http://example.com/?search={searchTerms}",
+    }
+  );
+  await Services.search.setDefault(defaultEngine);
+  await Services.search.moveEngine(suggestionsEngine, 0);
+
+  // Add some form history.
+  await UrlbarTestUtils.formHistory.add([
+    { value: "hello formHistory 1", source: suggestionsEngine.name },
+    { value: "hello formHistory 2", source: suggestionsEngine.name },
+    { value: "hello formHistory global" },
+    { value: "hello formHistory other", source: "other engine" },
+  ]);
+
+  registerCleanupFunction(async () => {
+    await Services.search.setDefault(oldDefaultEngine);
+    await Services.search.removeEngine(defaultEngine);
+    await UrlbarTestUtils.formHistory.clear();
+  });
+
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      ["browser.search.separatePrivateDefault.ui.enabled", false],
+      ["browser.urlbar.update2", true],
+      ["browser.urlbar.update2.oneOffsRefresh", true],
+    ],
+  });
+});
+
+add_task(async function emptySearch() {
+  await BrowserTestUtils.withNewTab("about:robots", async function(browser) {
+    await UrlbarTestUtils.promiseAutocompleteResultPopup({
+      window,
+      value: "",
+    });
+    await UrlbarTestUtils.enterSearchMode(window);
+    Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
+    // For the empty search case, we expect to get the heuristic and
+    // form history relative to the picked engine.
+    await checkResults([
+      {
+        isSearchHistory: false,
+        suggestion: undefined,
+      },
+      {
+        isSearchHistory: true,
+        suggestion: "hello formHistory 1",
+      },
+      {
+        isSearchHistory: true,
+        suggestion: "hello formHistory 2",
+      },
+    ]);
+
+    await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
+  });
+});
+
+add_task(async function nonEmptySearch() {
+  await BrowserTestUtils.withNewTab("about:robots", async function(browser) {
+    await UrlbarTestUtils.promiseAutocompleteResultPopup({
+      window,
+      value: "hello",
+    });
+    await UrlbarTestUtils.enterSearchMode(window);
+    Assert.equal(gURLBar.value, "hello", "Urlbar value should be set.");
+    // We expect to get the heuristic and all the suggestions.
+    await checkResults([
+      {
+        isSearchHistory: false,
+        suggestion: undefined,
+      },
+      {
+        isSearchHistory: true,
+        suggestion: "hello formHistory 1",
+      },
+      {
+        isSearchHistory: true,
+        suggestion: "hello formHistory 2",
+      },
+      {
+        isSearchHistory: false,
+        suggestion: `${TEST_QUERY}foo`,
+      },
+      {
+        isSearchHistory: false,
+        suggestion: `${TEST_QUERY}bar`,
+      },
+    ]);
+
+    await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
+  });
+});
+
+add_task(async function nonEmptySearch_nonMatching() {
+  await BrowserTestUtils.withNewTab("about:robots", async function(browser) {
+    await UrlbarTestUtils.promiseAutocompleteResultPopup({
+      window,
+      value: "ciao",
+    });
+    await UrlbarTestUtils.enterSearchMode(window);
+    Assert.equal(gURLBar.value, "ciao", "Urlbar value should be set.");
+    // We expect to get the heuristic and the remote suggestions since the local
+    // ones don't match.
+    await checkResults([
+      {
+        isSearchHistory: false,
+        suggestion: undefined,
+      },
+      {
+        isSearchHistory: false,
+        suggestion: "ciaofoo",
+      },
+      {
+        isSearchHistory: false,
+        suggestion: "ciaobar",
+      },
+    ]);
+
+    await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
+  });
+});
+
+async function checkResults(resultsDetails) {
+  Assert.equal(
+    UrlbarTestUtils.getResultCount(window),
+    resultsDetails.length,
+    "Check results count."
+  );
+  for (let i = 0; i < resultsDetails.length; ++i) {
+    let result = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
+    Assert.equal(
+      result.searchParams.engine,
+      suggestionsEngine.name,
+      "It should be a search result for our suggestion engine."
+    );
+    Assert.equal(
+      result.searchParams.isSearchHistory,
+      resultsDetails[i].isSearchHistory,
+      "Check if it should be a local suggestion result."
+    );
+    Assert.equal(
+      result.searchParams.suggestion,
+      resultsDetails[i].suggestion,
+      "Check the suggestion value"
+    );
+  }
+}
--- a/browser/components/urlbar/tests/unit/head.js
+++ b/browser/components/urlbar/tests/unit/head.js
@@ -424,16 +424,17 @@ function makeBookmarkResult(
  */
 function makeFormHistoryResult(queryContext, { suggestion, engineName }) {
   return new UrlbarResult(
     UrlbarUtils.RESULT_TYPE.SEARCH,
     UrlbarUtils.RESULT_SOURCE.HISTORY,
     ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
       engine: engineName,
       suggestion: [suggestion, UrlbarUtils.HIGHLIGHT.SUGGESTED],
+      isSearchHistory: true,
       lowerCaseSuggestion: suggestion.toLocaleLowerCase(),
     })
   );
 }
 
 /**
  * Creates a UrlbarResult for an omnibox extension result. For more information,
  * see the documentation for omnibox.SuggestResult: