From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser/browser_searchMode_suggestions.js | 579 +++++++++++++++++++++ 1 file changed, 579 insertions(+) create mode 100644 browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js (limited to 'browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js') diff --git a/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js b/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js new file mode 100644 index 0000000000..5aa3412580 --- /dev/null +++ b/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js @@ -0,0 +1,579 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests search suggestions in search mode. + */ + +const DEFAULT_ENGINE_NAME = "Test"; +const SUGGESTIONS_ENGINE_NAME = "searchSuggestionEngine.xml"; +const MANY_SUGGESTIONS_ENGINE_NAME = "searchSuggestionEngineMany.xml"; +const MAX_RESULT_COUNT = UrlbarPrefs.get("maxRichResults"); + +let suggestionsEngine; +let expectedFormHistoryResults = []; + +add_setup(async function () { + suggestionsEngine = await SearchTestUtils.promiseNewSearchEngine({ + url: getRootDirectory(gTestPath) + SUGGESTIONS_ENGINE_NAME, + }); + + await SearchTestUtils.installSearchExtension( + { + name: DEFAULT_ENGINE_NAME, + keyword: "@test", + }, + { setAsDefault: true } + ); + await Services.search.moveEngine(suggestionsEngine, 0); + + async function cleanup() { + await PlacesUtils.history.clear(); + await PlacesUtils.bookmarks.eraseEverything(); + } + await cleanup(); + registerCleanupFunction(cleanup); + + // Add some form history for our test engine. + for (let i = 0; i < MAX_RESULT_COUNT; i++) { + let value = `hello formHistory ${i}`; + await UrlbarTestUtils.formHistory.add([ + { value, source: suggestionsEngine.name }, + ]); + expectedFormHistoryResults.push({ + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + searchParams: { + suggestion: value, + engine: suggestionsEngine.name, + }, + }); + } + + // Add other form history. + await UrlbarTestUtils.formHistory.add([ + { value: "hello formHistory global" }, + { value: "hello formHistory other", source: "other engine" }, + ]); + + registerCleanupFunction(async () => { + await UrlbarTestUtils.formHistory.clear(); + }); + + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.search.separatePrivateDefault.ui.enabled", false], + ["browser.urlbar.suggest.quickactions", false], + ], + }); +}); + +add_task(async function emptySearch() { + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.update2.emptySearchBehavior", 2]], + }); + 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 form history relative to + // the picked engine and no heuristic. + await checkResults(expectedFormHistoryResults); + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + await SpecialPowers.popPrefEnv(); + }); +}); + +add_task(async function emptySearch_withRestyledHistory() { + // URLs with the same host as the search engine. + await PlacesTestUtils.addVisits([ + `http://mochi.test/`, + `http://mochi.test/redirect`, + // Should not be returned because it's a redirect target. + { + uri: `http://mochi.test/target`, + transition: PlacesUtils.history.TRANSITIONS.REDIRECT_TEMPORARY, + referrer: `http://mochi.test/redirect`, + }, + // Can be restyled and dupes form history. + "http://mochi.test:8888/?terms=hello+formHistory+0", + // Can be restyled but does not dupe form history. + "http://mochi.test:8888/?terms=ciao", + ]); + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.update2.emptySearchBehavior", 2]], + }); + 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 form history relative to + // the picked engine, history without redirects, and no heuristic. + await checkResults([ + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + searchParams: { + suggestion: "ciao", + engine: suggestionsEngine.name, + }, + }, + ...expectedFormHistoryResults.slice(0, MAX_RESULT_COUNT - 3), + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/redirect`, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/`, + }, + ]); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + await SpecialPowers.popPrefEnv(); + }); + + await PlacesUtils.history.clear(); +}); + +add_task(async function emptySearch_withRestyledHistory_noSearchHistory() { + // URLs with the same host as the search engine. + await PlacesTestUtils.addVisits([ + `http://mochi.test/`, + `http://mochi.test/redirect`, + // Can be restyled but does not dupe form history. + "http://mochi.test:8888/?terms=ciao", + ]); + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.update2.emptySearchBehavior", 2], + ["browser.urlbar.maxHistoricalSearchSuggestions", 0], + ], + }); + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "", + }); + await UrlbarTestUtils.enterSearchMode(window); + Assert.equal(gURLBar.value, "", "Urlbar value should be cleared."); + // maxHistoricalSearchSuggestions == 0, so form history should not be + // present. + await checkResults([ + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/redirect`, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/`, + }, + ]); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + await SpecialPowers.popPrefEnv(); + }); + + await PlacesUtils.history.clear(); +}); + +add_task(async function emptySearch_behavior() { + // URLs with the same host as the search engine. + await PlacesTestUtils.addVisits([`http://mochi.test/`]); + + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.update2.emptySearchBehavior", 0]], + }); + 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 form history relative to + // the picked engine, history without redirects, and no heuristic. + await checkResults([]); + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + + // We should still show history for empty searches when not in search mode. + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: " ", + }); + await checkResults([ + { + heuristic: true, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query: " ", + engine: DEFAULT_ENGINE_NAME, + }, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/`, + }, + ]); + await UrlbarTestUtils.promisePopupClose(window); + await SpecialPowers.popPrefEnv(); + }); + + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.update2.emptySearchBehavior", 1]], + }); + 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 form history relative to + // the picked engine, history without redirects, and no heuristic. + await checkResults([...expectedFormHistoryResults]); + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + await SpecialPowers.popPrefEnv(); + }); + + await PlacesUtils.history.clear(); +}); + +add_task(async function emptySearch_local() { + await PlacesTestUtils.addVisits([`http://mochi.test/`]); + + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.update2.emptySearchBehavior", 0]], + }); + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "", + }); + await UrlbarTestUtils.enterSearchMode(window, { + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + }); + Assert.equal(gURLBar.value, "", "Urlbar value should be cleared."); + // Even when emptySearchBehavior is 0, we still show the user's most frecent + // history for an empty search. + await checkResults([ + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/`, + }, + ]); + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + await SpecialPowers.popPrefEnv(); + }); + + await PlacesUtils.history.clear(); +}); + +add_task(async function nonEmptySearch() { + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + let query = "hello"; + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: query, + }); + await UrlbarTestUtils.enterSearchMode(window); + Assert.equal(gURLBar.value, query, "Urlbar value should be set."); + // We expect to get the heuristic and all the suggestions. + await checkResults([ + { + heuristic: true, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + engine: suggestionsEngine.name, + }, + }, + ...expectedFormHistoryResults.slice(0, MAX_RESULT_COUNT - 3), + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + suggestion: `${query}foo`, + engine: suggestionsEngine.name, + }, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + suggestion: `${query}bar`, + engine: suggestionsEngine.name, + }, + }, + ]); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + }); +}); + +add_task(async function nonEmptySearch_nonMatching() { + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + let query = "ciao"; + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: query, + }); + await UrlbarTestUtils.enterSearchMode(window); + Assert.equal(gURLBar.value, query, "Urlbar value should be set."); + // We expect to get the heuristic and the remote suggestions since the local + // ones don't match. + await checkResults([ + { + heuristic: true, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + engine: suggestionsEngine.name, + }, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + suggestion: `${query}foo`, + engine: suggestionsEngine.name, + }, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + suggestion: `${query}bar`, + engine: suggestionsEngine.name, + }, + }, + ]); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + }); +}); + +add_task(async function nonEmptySearch_withHistory() { + let manySuggestionsEngine = await SearchTestUtils.promiseNewSearchEngine({ + url: getRootDirectory(gTestPath) + MANY_SUGGESTIONS_ENGINE_NAME, + }); + // URLs with the same host as the search engine. + let query = "ciao"; + await PlacesTestUtils.addVisits([ + `http://mochi.test/${query}`, + `http://mochi.test/${query}1`, + // Should not be returned because it has a different host, even if it + // matches the host in the path. + `http://example.com/mochi.test/${query}`, + ]); + + function makeSuggestionResult(suffix) { + return { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + suggestion: `${query}${suffix}`, + engine: manySuggestionsEngine.name, + }, + }; + } + + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: query, + }); + await UrlbarTestUtils.enterSearchMode(window, { + engineName: manySuggestionsEngine.name, + }); + Assert.equal(gURLBar.value, query, "Urlbar value should be set."); + + await checkResults([ + { + heuristic: true, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + engine: manySuggestionsEngine.name, + }, + }, + makeSuggestionResult("foo"), + makeSuggestionResult("bar"), + makeSuggestionResult("1"), + makeSuggestionResult("2"), + makeSuggestionResult("3"), + makeSuggestionResult("4"), + makeSuggestionResult("5"), + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/${query}1`, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/${query}`, + }, + ]); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + + info("Test again with history before suggestions"); + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.showSearchSuggestionsFirst", false]], + }); + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: query, + }); + await UrlbarTestUtils.enterSearchMode(window, { + engineName: manySuggestionsEngine.name, + }); + Assert.equal(gURLBar.value, query, "Urlbar value should be set."); + + await checkResults([ + { + heuristic: true, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + engine: manySuggestionsEngine.name, + }, + }, + makeSuggestionResult("foo"), + makeSuggestionResult("bar"), + makeSuggestionResult("1"), + makeSuggestionResult("2"), + makeSuggestionResult("3"), + makeSuggestionResult("4"), + makeSuggestionResult("5"), + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/${query}1`, + }, + { + heuristic: false, + type: UrlbarUtils.RESULT_TYPE.URL, + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + url: `http://mochi.test/${query}`, + }, + ]); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + await SpecialPowers.popPrefEnv(); + }); + + await PlacesUtils.history.clear(); +}); + +add_task(async function nonEmptySearch_url() { + await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + let query = "http://www.example.com/"; + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: query, + }); + await UrlbarTestUtils.enterSearchMode(window); + + // The heuristic result for a search that's a valid URL should be a search + // result, not a URL result. + await checkResults([ + { + heuristic: true, + type: UrlbarUtils.RESULT_TYPE.SEARCH, + source: UrlbarUtils.RESULT_SOURCE.SEARCH, + searchParams: { + query, + engine: suggestionsEngine.name, + }, + }, + ]); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + }); +}); + +async function checkResults(expectedResults) { + Assert.equal( + UrlbarTestUtils.getResultCount(window), + expectedResults.length, + "Check results count." + ); + for (let i = 0; i < expectedResults.length; ++i) { + info(`Checking result at index ${i}`); + let expected = expectedResults[i]; + let actual = await UrlbarTestUtils.getDetailsOfResultAt(window, i); + + // Check each property defined in the expected result against the property + // in the actual result. + for (let key of Object.keys(expected)) { + // For searchParams, remove undefined properties in the actual result so + // that the expected result doesn't need to include them. + if (key == "searchParams") { + let actualSearchParams = actual.searchParams; + for (let spKey of Object.keys(actualSearchParams)) { + if (actualSearchParams[spKey] === undefined) { + delete actualSearchParams[spKey]; + } + } + } + Assert.deepEqual( + actual[key], + expected[key], + `${key} should match at result index ${i}.` + ); + } + } +} -- cgit v1.2.3