summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/browser/browser_hideHeuristic.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/tests/browser/browser_hideHeuristic.js')
-rw-r--r--browser/components/urlbar/tests/browser/browser_hideHeuristic.js513
1 files changed, 513 insertions, 0 deletions
diff --git a/browser/components/urlbar/tests/browser/browser_hideHeuristic.js b/browser/components/urlbar/tests/browser/browser_hideHeuristic.js
new file mode 100644
index 0000000000..e8f8774e01
--- /dev/null
+++ b/browser/components/urlbar/tests/browser/browser_hideHeuristic.js
@@ -0,0 +1,513 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Basic smoke tests for the `browser.urlbar.experimental.hideHeuristic` pref,
+// which hides the heuristic result. Each task performs a search that triggers a
+// specific heuristic, verifies that it's hidden or shown as appropriate, and
+// verifies that it's picked when enter is pressed.
+//
+// If/when it becomes the default, we should update existing tests as necessary
+// and remove this one.
+
+"use strict";
+
+// Allow more time for Mac machines so they don't time out in verify mode.
+if (AppConstants.platform == "macosx") {
+ requestLongerTimeout(3);
+}
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.urlbar.experimental.hideHeuristic", true],
+ ["browser.urlbar.suggest.quickactions", false],
+ ],
+ });
+ await PlacesUtils.bookmarks.eraseEverything();
+ await PlacesUtils.history.clear();
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_EXTENSION should be hidden.
+add_task(async function extension() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ await withVisits(async visitURLs => {
+ // Add an extension provider that returns a heuristic.
+ let url = "http://example.com/extension-test";
+ let provider = new UrlbarTestUtils.TestProvider({
+ name: "ExtensionTest",
+ type: UrlbarUtils.PROVIDER_TYPE.EXTENSION,
+ results: [
+ Object.assign(
+ new UrlbarResult(
+ UrlbarUtils.RESULT_TYPE.URL,
+ UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
+ {
+ url,
+ title: "Test",
+ }
+ ),
+ { heuristic: true }
+ ),
+ ],
+ });
+ UrlbarProvidersManager.registerProvider(provider);
+
+ // Do a search that fetches the provider's result and check it.
+ let heuristic = await search({
+ value: "test",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_EXTENSION,
+ });
+ Assert.equal(heuristic.payload.url, url, "Heuristic URL is correct");
+
+ // Check the other visit results.
+ await checkVisitResults(visitURLs);
+
+ // Press enter to verify the heuristic result is loaded.
+ await synthesizeEnterAndAwaitLoad(url);
+
+ UrlbarProvidersManager.unregisterProvider(provider);
+ });
+ });
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_OMNIBOX should be hidden.
+add_task(async function omnibox() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ // Load an extension.
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ omnibox: {
+ keyword: "omniboxtest",
+ },
+ },
+ background() {
+ /* global browser */
+ browser.omnibox.onInputEntered.addListener(() => {
+ browser.test.sendMessage("onInputEntered");
+ });
+ },
+ });
+ await extension.startup();
+
+ // Do a search using the omnibox keyword and check the hidden heuristic
+ // result.
+ let heuristic = await search({
+ value: "omniboxtest foo",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_OMNIBOX,
+ });
+ Assert.equal(
+ heuristic.payload.keyword,
+ "omniboxtest",
+ "Heuristic keyword is correct"
+ );
+
+ // Press enter to verify the heuristic result is picked.
+ let messagePromise = extension.awaitMessage("onInputEntered");
+ EventUtils.synthesizeKey("KEY_Enter");
+ await messagePromise;
+
+ await extension.unload();
+ });
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_SEARCH_TIP should be shown.
+add_task(async function searchTip() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.urlbar.searchTips.test.ignoreShowLimits", true]],
+ });
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser: window.gBrowser,
+ url: "about:newtab",
+ // `withNewTab` hangs waiting for about:newtab to load without this.
+ waitForLoad: false,
+ },
+ async () => {
+ await UrlbarTestUtils.promisePopupOpen(window, () => {});
+ Assert.ok(true, "View opened");
+ Assert.equal(UrlbarTestUtils.getResultCount(window), 1);
+ let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
+ Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TIP);
+ Assert.ok(result.heuristic);
+ Assert.ok(UrlbarTestUtils.getSelectedElement(window), "Selection exists");
+ }
+ );
+ await SpecialPowers.popPrefEnv();
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_ENGINE_ALIAS should be hidden.
+add_task(async function engineAlias() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ await withVisits(async visitURLs => {
+ // Add an engine with an alias.
+ await withEngine({ keyword: "test" }, async () => {
+ // Do a search using the alias and check the hidden heuristic result.
+ // The heuristic will be HEURISTIC_FALLBACK, not HEURISTIC_ENGINE_ALIAS,
+ // because two searches are performed and
+ // `UrlbarTestUtils.promiseAutocompleteResultPopup` waits for both. The
+ // first returns a HEURISTIC_ENGINE_ALIAS that triggers search mode and
+ // then an immediate second search, which returns HEURISTIC_FALLBACK.
+ let heuristic = await search({
+ value: "test foo",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK,
+ });
+ Assert.equal(
+ heuristic.payload.engine,
+ "Example",
+ "Heuristic engine is correct"
+ );
+ Assert.equal(
+ heuristic.payload.query,
+ "foo",
+ "Heuristic query is correct"
+ );
+ await UrlbarTestUtils.assertSearchMode(window, {
+ engineName: "Example",
+ entry: "typed",
+ });
+
+ // Check the other visit results.
+ await checkVisitResults(visitURLs);
+
+ // Press enter to verify the heuristic result is loaded.
+ await synthesizeEnterAndAwaitLoad("https://example.com/?q=foo");
+ });
+ });
+ });
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_BOOKMARK_KEYWORD should be hidden.
+add_task(async function bookmarkKeyword() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ await withVisits(async visitURLs => {
+ // Add a bookmark with a keyword.
+ let keyword = "bm";
+ let bm = await PlacesUtils.bookmarks.insert({
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ url: "http://example.com/?q=%s",
+ title: "test",
+ });
+ await PlacesUtils.keywords.insert({ keyword, url: bm.url });
+
+ // Do a search using the keyword and check the hidden heuristic result.
+ let heuristic = await search({
+ value: "bm foo",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_BOOKMARK_KEYWORD,
+ });
+ Assert.equal(
+ heuristic.payload.keyword,
+ keyword,
+ "Heuristic keyword is correct"
+ );
+ let heuristicURL = "http://example.com/?q=foo";
+ Assert.equal(
+ heuristic.payload.url,
+ heuristicURL,
+ "Heuristic URL is correct"
+ );
+
+ // Check the other visit results.
+ await checkVisitResults(visitURLs);
+
+ // Press enter to verify the heuristic result is loaded.
+ await synthesizeEnterAndAwaitLoad(heuristicURL);
+
+ await PlacesUtils.bookmarks.eraseEverything();
+ await UrlbarTestUtils.formHistory.clear(window);
+ });
+ });
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_AUTOFILL should be hidden.
+add_task(async function autofill() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ await withVisits(async visitURLs => {
+ // Do a search that triggers autofill and check the hidden heuristic
+ // result.
+ let heuristic = await search({
+ value: "ex",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_AUTOFILL,
+ });
+ Assert.ok(heuristic.autofill, "Heuristic is autofill");
+ let heuristicURL = "http://example.com/";
+ Assert.equal(
+ heuristic.payload.url,
+ heuristicURL,
+ "Heuristic URL is correct"
+ );
+ Assert.equal(gURLBar.value, "example.com/", "Input has been autofilled");
+
+ // Check the other visit results.
+ await checkVisitResults(visitURLs);
+
+ // Press enter to verify the heuristic result is loaded.
+ await synthesizeEnterAndAwaitLoad(heuristicURL);
+ });
+ });
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK with an unknown URL should be
+// hidden.
+add_task(async function fallback_unknownURL() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ // Do a search for an unknown URL and check the hidden heuristic result.
+ let url = "http://example.com/unknown-url";
+ let heuristic = await search({
+ value: url,
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK,
+ });
+ Assert.equal(heuristic.payload.url, url, "Heuristic URL is correct");
+
+ // Press enter to verify the heuristic result is loaded.
+ await synthesizeEnterAndAwaitLoad(url);
+ });
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK with the search restriction token
+// should be hidden.
+add_task(async function fallback_searchRestrictionToken() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ await withVisits(async visitURLs => {
+ // Add a mock default engine so we don't hit the network.
+ await withEngine({ makeDefault: true }, async () => {
+ // Do a search with `?` and check the hidden heuristic result.
+ let heuristic = await search({
+ value: UrlbarTokenizer.RESTRICT.SEARCH + " foo",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK,
+ });
+ Assert.equal(
+ heuristic.payload.engine,
+ "Example",
+ "Heuristic engine is correct"
+ );
+ Assert.equal(
+ heuristic.payload.query,
+ "foo",
+ "Heuristic query is correct"
+ );
+ await UrlbarTestUtils.assertSearchMode(window, {
+ engineName: "Example",
+ entry: "typed",
+ });
+
+ // Check the other visit results.
+ await checkVisitResults(visitURLs);
+
+ // Press enter to verify the heuristic result is loaded.
+ await synthesizeEnterAndAwaitLoad("https://example.com/?q=foo");
+
+ await UrlbarTestUtils.formHistory.clear(window);
+ });
+ });
+ });
+});
+
+// UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK with a search string that falls
+// back to a search result should be hidden.
+add_task(async function fallback_search() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ await withVisits(async visitURLs => {
+ // Add a mock default engine so we don't hit the network.
+ await withEngine({ makeDefault: true }, async () => {
+ // Do a search and check the hidden heuristic result.
+ let heuristic = await search({
+ value: "foo",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK,
+ });
+ Assert.equal(
+ heuristic.payload.engine,
+ "Example",
+ "Heuristic engine is correct"
+ );
+ Assert.equal(
+ heuristic.payload.query,
+ "foo",
+ "Heuristic query is correct"
+ );
+
+ // Check the other visit results.
+ await checkVisitResults(visitURLs);
+
+ // Press enter to verify the heuristic result is loaded.
+ await synthesizeEnterAndAwaitLoad("https://example.com/?q=foo");
+
+ await UrlbarTestUtils.formHistory.clear(window);
+ });
+ });
+ });
+});
+
+// Picking a non-heuristic result should work correctly (and not pick the
+// heuristic).
+add_task(async function pickNonHeuristic() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ await withVisits(async visitURLs => {
+ // Do a search that triggers autofill and check the hidden heuristic
+ // result.
+ let heuristic = await search({
+ value: "ex",
+ expectedGroup: UrlbarUtils.RESULT_GROUP.HEURISTIC_AUTOFILL,
+ });
+ Assert.ok(heuristic.autofill, "Heuristic is autofill");
+ Assert.equal(
+ heuristic.payload.url,
+ "http://example.com/",
+ "Heuristic URL is correct"
+ );
+
+ // Pick the first visit result.
+ Assert.notEqual(
+ heuristic.payload.url,
+ visitURLs[0],
+ "Sanity check: Heuristic and first results have different URLs"
+ );
+ EventUtils.synthesizeKey("KEY_ArrowDown");
+ await synthesizeEnterAndAwaitLoad(visitURLs[0]);
+ });
+ });
+});
+
+/**
+ * Adds `maxRichResults` visits, calls your callback, and clears history. We add
+ * `maxRichResults` visits to verify that the view correctly contains the
+ * maximum number of results when the heuristic is hidden.
+ *
+ * @param {Function} callback
+ * The callback to call after adding visits. Can be async
+ */
+async function withVisits(callback) {
+ let urls = [];
+ for (let i = 0; i < UrlbarPrefs.get("maxRichResults"); i++) {
+ urls.push("http://example.com/foo/" + i);
+ }
+ await PlacesTestUtils.addVisits(urls);
+
+ // The URLs will appear in the view in reverse order so that newer visits are
+ // first. Reverse the array now so callers to `checkVisitResults` or
+ // `checkVisitResults` itself doesn't need to do it.
+ urls.reverse();
+
+ await callback(urls);
+ await PlacesUtils.history.clear();
+}
+
+/**
+ * Adds a search engine, calls your callback, and removes the engine.
+ *
+ * @param {object} options
+ * Options object
+ * @param {string} [options.keyword]
+ * The keyword/alias for the engine.
+ * @param {boolean} [options.makeDefault]
+ * Whether to make the engine default.
+ * @param {Function} callback
+ * The callback to call after changing the default search engine. Can be async
+ */
+async function withEngine(
+ { keyword = undefined, makeDefault = false },
+ callback
+) {
+ await SearchTestUtils.installSearchExtension({ keyword });
+ let engine = Services.search.getEngineByName("Example");
+ let originalEngine;
+ if (makeDefault) {
+ originalEngine = await Services.search.getDefault();
+ await Services.search.setDefault(
+ engine,
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+ }
+ await callback();
+ if (originalEngine) {
+ await Services.search.setDefault(
+ originalEngine,
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+ }
+ await Services.search.removeEngine(engine);
+}
+
+/**
+ * Asserts the view contains visit results with the given URLs.
+ *
+ * @param {Array} expectedURLs
+ * The expected urls.
+ */
+async function checkVisitResults(expectedURLs) {
+ Assert.equal(
+ UrlbarTestUtils.getResultCount(window),
+ expectedURLs.length,
+ "The view has other results"
+ );
+ for (let i = 0; i < expectedURLs.length; i++) {
+ let result = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
+ Assert.equal(
+ result.type,
+ UrlbarUtils.RESULT_TYPE.URL,
+ "Other result type is correct at index " + i
+ );
+ Assert.equal(
+ result.source,
+ UrlbarUtils.RESULT_SOURCE.HISTORY,
+ "Other result source is correct at index " + i
+ );
+ Assert.equal(
+ result.url,
+ expectedURLs[i],
+ "Other result URL is correct at index " + i
+ );
+ }
+}
+
+/**
+ * Performs a search and makes some basic assertions under the assumption that
+ * the heuristic should be hidden.
+ *
+ * @param {object} options
+ * Options object
+ * @param {string} options.value
+ * The search string.
+ * @param {UrlbarUtils.RESULT_GROUP} options.expectedGroup
+ * The expected result group of the hidden heuristic.
+ * @returns {UrlbarResult}
+ * The hidden heuristic result.
+ */
+async function search({ value, expectedGroup }) {
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ waitForFocus,
+ value,
+ fireInputEvent: true,
+ });
+
+ // _resultForCurrentValue should be the hidden heuristic result.
+ let { _resultForCurrentValue: result } = gURLBar;
+ Assert.ok(result, "_resultForCurrentValue is defined");
+ Assert.ok(result.heuristic, "_resultForCurrentValue.heuristic is true");
+ Assert.equal(
+ UrlbarUtils.getResultGroup(result),
+ expectedGroup,
+ "_resultForCurrentValue has expected group"
+ );
+
+ Assert.ok(!UrlbarTestUtils.getSelectedElement(window), "No selection exists");
+
+ return result;
+}
+
+/**
+ * Synthesizes the enter key and waits for a load in the current tab.
+ *
+ * @param {string} expectedURL
+ * The URL that should load.
+ */
+async function synthesizeEnterAndAwaitLoad(expectedURL) {
+ let loadPromise = BrowserTestUtils.browserLoaded(
+ gBrowser.selectedBrowser,
+ false,
+ expectedURL
+ );
+ EventUtils.synthesizeKey("KEY_Enter");
+ await loadPromise;
+ await PlacesUtils.history.clear();
+}