From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- .../urlbar/tests/UrlbarTestUtils.sys.mjs | 7 +- .../browser-tips/browser_searchTips_interaction.js | 2 +- .../browser_appendSpanCount.js | 2 +- .../urlbar/tests/browser-updateResults/head.js | 2 +- .../components/urlbar/tests/browser/browser.toml | 3 +- .../browser_acknowledgeFeedbackAndDismissal.js | 162 ++++-- .../tests/browser/browser_add_search_engine.js | 5 +- .../urlbar/tests/browser/browser_autoOpen.js | 2 +- .../urlbar/tests/browser/browser_bestMatch.js | 6 +- .../urlbar/tests/browser/browser_blanking.js | 2 +- .../urlbar/tests/browser/browser_clipboard.js | 43 +- .../tests/browser/browser_copy_during_load.js | 2 +- .../urlbar/tests/browser/browser_copying.js | 2 +- .../urlbar/tests/browser/browser_dragdropURL.js | 4 +- .../urlbar/tests/browser/browser_dynamicResults.js | 6 +- .../urlbar/tests/browser/browser_groupLabels.js | 4 +- .../tests/browser/browser_locationBarCommand.js | 2 +- .../browser/browser_locationBarExternalLoad.js | 4 +- .../browser_locationchange_urlbar_edit_dos.js | 2 +- .../browser/browser_oneOffs_heuristicRestyle.js | 2 +- .../tests/browser/browser_oneOffs_settings.js | 2 +- .../urlbar/tests/browser/browser_recentsearches.js | 94 +++- .../urlbar/tests/browser/browser_redirect_error.js | 2 +- .../urlbar/tests/browser/browser_remove_match.js | 2 +- .../tests/browser/browser_result_onSelection.js | 2 +- .../browser/browser_results_format_displayValue.js | 2 +- .../browser/browser_retainedResultsOnFocus.js | 2 +- .../urlbar/tests/browser/browser_revert.js | 2 +- .../tests/browser/browser_searchMode_indicator.js | 4 +- .../browser_searchMode_indicator_clickthrough.js | 4 +- .../browser_searchMode_localOneOffs_actionText.js | 2 +- .../browser/browser_searchMode_suggestions.js | 20 +- .../browser_searchSingleWordNotification.js | 10 +- .../tests/browser/browser_search_continuation.js | 64 ++- .../tests/browser/browser_selectStaleResults.js | 2 +- .../browser/browser_shortcuts_add_search_engine.js | 2 +- ...ser_speculative_connect_not_with_client_cert.js | 2 +- .../urlbar/tests/browser/browser_stop.js | 2 +- .../urlbar/tests/browser/browser_strip_on_share.js | 4 +- .../browser/browser_strip_on_share_telemetry.js | 2 +- .../browser/browser_switchTab_inputHistory.js | 69 ++- .../tests/browser/browser_switchTab_override.js | 2 +- .../browser/browser_tabMatchesInAwesomebar.js | 2 +- .../urlbar/tests/browser/browser_tabToSearch.js | 6 +- .../tests/browser/browser_top_sites_switchtab.js | 209 +++++++ .../browser/browser_urlbar_telemetry_dynamic.js | 2 +- .../tests/browser/browser_urlbar_telemetry_tip.js | 4 +- .../tests/browser/browser_valueOnTabSwitch.js | 2 +- .../browser/browser_view_removedSelectedElement.js | 2 +- .../tests/browser/browser_view_selectionByMouse.js | 7 +- browser/components/urlbar/tests/browser/head.js | 2 +- .../tests/engagementTelemetry/browser/browser.toml | 22 +- .../browser_glean_telemetry_abandonment_tips.js | 2 +- .../browser_glean_telemetry_abandonment_type.js | 109 ++++ ...rowser_glean_telemetry_engagement_edge_cases.js | 8 +- .../browser_glean_telemetry_engagement_groups.js | 8 +- ...owser_glean_telemetry_engagement_interaction.js | 8 +- ...r_glean_telemetry_engagement_selected_result.js | 269 ++++++--- .../browser_glean_telemetry_engagement_tips.js | 4 +- .../browser_glean_telemetry_engagement_type.js | 16 +- .../browser_glean_telemetry_exposure_edge_cases.js | 626 +++++++++++++++++++-- .../browser_glean_telemetry_impression_groups.js | 258 --------- ...owser_glean_telemetry_impression_interaction.js | 68 --- ..._interaction_persisted_search_terms_disabled.js | 57 -- ...n_interaction_persisted_search_terms_enabled.js | 61 -- ...r_glean_telemetry_impression_n_chars_n_words.js | 40 -- ...owser_glean_telemetry_impression_preferences.js | 41 -- .../browser_glean_telemetry_impression_sap.js | 38 -- ...elemetry_impression_search_engine_default_id.js | 28 - ...owser_glean_telemetry_impression_search_mode.js | 72 --- .../browser_glean_telemetry_impression_timing.js | 91 --- .../engagementTelemetry/browser/head-groups.js | 32 +- .../browser/head-interaction.js | 23 +- .../browser/head-n_chars_n_words.js | 8 +- .../tests/engagementTelemetry/browser/head-sap.js | 5 +- .../browser/head-search_engine_default_id.js | 4 +- .../browser/head-search_mode.js | 12 +- .../tests/engagementTelemetry/browser/head.js | 28 +- .../tests/quicksuggest/MerinoTestUtils.sys.mjs | 18 +- .../quicksuggest/RemoteSettingsServer.sys.mjs | 30 +- .../browser_quicksuggest_onboardingDialog.js | 3 - .../browser_telemetry_impressionEdgeCases.js | 2 +- .../tests/quicksuggest/browser/browser_weather.js | 107 +++- .../urlbar/tests/quicksuggest/browser/head.js | 82 ++- .../urlbar/tests/quicksuggest/unit/head.js | 113 +++- .../tests/quicksuggest/unit/test_quicksuggest.js | 58 +- .../quicksuggest/unit/test_quicksuggest_addons.js | 12 +- .../quicksuggest/unit/test_quicksuggest_pocket.js | 4 +- .../tests/quicksuggest/unit/test_rust_ingest.js | 33 +- .../urlbar/tests/quicksuggest/unit/test_weather.js | 200 +++---- .../quicksuggest/unit/test_weather_keywords.js | 139 +---- .../urlbar/tests/quicksuggest/unit/xpcshell.toml | 1 + browser/components/urlbar/tests/unit/head.js | 33 +- .../urlbar/tests/unit/test_UrlbarPrefs.js | 8 +- .../urlbar/tests/unit/test_UrlbarSearchUtils.js | 24 +- .../urlbar/tests/unit/test_about_urls.js | 6 + .../tests/unit/test_autofill_originsAndQueries.js | 12 +- .../urlbar/tests/unit/test_heuristic_cancel.js | 2 +- .../urlbar/tests/unit/test_hideSponsoredHistory.js | 2 +- .../urlbar/tests/unit/test_match_javascript.js | 5 +- .../tests/unit/test_providerHistoryUrlHeuristic.js | 2 + .../urlbar/tests/unit/test_providerOpenTabs.js | 99 +++- .../urlbar/tests/unit/test_providerTabToSearch.js | 4 +- .../tests/unit/test_providersManager_filtering.js | 6 +- .../urlbar/tests/unit/test_remote_tabs.js | 4 +- .../urlbar/tests/unit/test_search_suggestions.js | 4 +- browser/components/urlbar/tests/unit/xpcshell.toml | 4 - 107 files changed, 2226 insertions(+), 1526 deletions(-) create mode 100644 browser/components/urlbar/tests/browser/browser_top_sites_switchtab.js create mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_type.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_groups.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_disabled.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_enabled.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_n_chars_n_words.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_preferences.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_sap.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_engine_default_id.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_mode.js delete mode 100644 browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_timing.js (limited to 'browser/components/urlbar/tests') diff --git a/browser/components/urlbar/tests/UrlbarTestUtils.sys.mjs b/browser/components/urlbar/tests/UrlbarTestUtils.sys.mjs index a8e422526c..cfc9ecb3d8 100644 --- a/browser/components/urlbar/tests/UrlbarTestUtils.sys.mjs +++ b/browser/components/urlbar/tests/UrlbarTestUtils.sys.mjs @@ -545,6 +545,7 @@ export var UrlbarTestUtils = { details.title = result.title; details.tags = "tags" in result.payload ? result.payload.tags : []; details.isSponsored = result.payload.isSponsored; + details.userContextId = result.payload.userContextId; let actions = element.getElementsByClassName("urlbarView-action"); let urls = element.getElementsByClassName("urlbarView-url"); let typeIcon = element.querySelector(".urlbarView-type-icon"); @@ -1536,11 +1537,11 @@ class TestProvider extends UrlbarProvider { return this._type; } - getPriority(context) { + getPriority(_context) { return this.priority; } - isActive(context) { + isActive(_context) { return true; } @@ -1565,7 +1566,7 @@ class TestProvider extends UrlbarProvider { } } - cancelQuery(context) { + cancelQuery(_context) { this._onCancel?.(); } diff --git a/browser/components/urlbar/tests/browser-tips/browser_searchTips_interaction.js b/browser/components/urlbar/tests/browser-tips/browser_searchTips_interaction.js index a5cee02dae..72d05cf632 100644 --- a/browser/components/urlbar/tests/browser-tips/browser_searchTips_interaction.js +++ b/browser/components/urlbar/tests/browser-tips/browser_searchTips_interaction.js @@ -680,7 +680,7 @@ add_task(async function noActionWhenDisabled() { ], }); - await withDNSRedirect("www.bing.com", "/", async url => { + await withDNSRedirect("www.bing.com", "/", async () => { Assert.ok( !UrlbarTestUtils.isPopupOpen(window), "The UrlbarView should not be open." diff --git a/browser/components/urlbar/tests/browser-updateResults/browser_appendSpanCount.js b/browser/components/urlbar/tests/browser-updateResults/browser_appendSpanCount.js index 60838d0c8b..ccea889a9c 100644 --- a/browser/components/urlbar/tests/browser-updateResults/browser_appendSpanCount.js +++ b/browser/components/urlbar/tests/browser-updateResults/browser_appendSpanCount.js @@ -99,7 +99,7 @@ add_task(async function viewUpdateAppendHidden() { // The `- 2` subtracts the heuristic and tip result. let newExpectedRowCount = 2 * expectedRowCount - 2; let mutationPromise = new Promise(resolve => { - let observer = new MutationObserver(mutations => { + let observer = new MutationObserver(() => { let childCount = UrlbarTestUtils.getResultCount(window); info(`Rows mutation observer called, childCount now ${childCount}`); if (newExpectedRowCount <= childCount) { diff --git a/browser/components/urlbar/tests/browser-updateResults/head.js b/browser/components/urlbar/tests/browser-updateResults/head.js index 3d46d83018..77b110990e 100644 --- a/browser/components/urlbar/tests/browser-updateResults/head.js +++ b/browser/components/urlbar/tests/browser-updateResults/head.js @@ -386,7 +386,7 @@ async function doSuggestedIndexTest({ search1, search2, duringUpdate }) { // update and delaying resolving the provider's finishQueryPromise. let mutationPromise = new Promise(resolve => { let lastRowState = duringUpdate[duringUpdate.length - 1]; - let observer = new MutationObserver(mutations => { + let observer = new MutationObserver(() => { observer.disconnect(); resolve(); }); diff --git a/browser/components/urlbar/tests/browser/browser.toml b/browser/components/urlbar/tests/browser/browser.toml index a77a831fab..b9934aa838 100644 --- a/browser/components/urlbar/tests/browser/browser.toml +++ b/browser/components/urlbar/tests/browser/browser.toml @@ -314,7 +314,6 @@ support-files = [ ["browser_oneOffs_heuristicRestyle.js"] skip-if = [ "os == 'linux' && bits == 64 && !debug", # Bug 1775811 - "a11y_checks", # Bugs 1858041 and 1854661 to investigate intermittent a11y_checks results ] ["browser_oneOffs_keyModifiers.js"] @@ -596,6 +595,8 @@ https_first_disabled = true ["browser_top_sites_private.js"] https_first_disabled = true +["browser_top_sites_switchtab.js"] + ["browser_typed_value.js"] ["browser_unitConversion.js"] diff --git a/browser/components/urlbar/tests/browser/browser_acknowledgeFeedbackAndDismissal.js b/browser/components/urlbar/tests/browser/browser_acknowledgeFeedbackAndDismissal.js index 5ad8dfc75d..8c4b05501e 100644 --- a/browser/components/urlbar/tests/browser/browser_acknowledgeFeedbackAndDismissal.js +++ b/browser/components/urlbar/tests/browser/browser_acknowledgeFeedbackAndDismissal.js @@ -7,6 +7,10 @@ "use strict"; +// See the comment in the setup task for the expected index of the main test +// result. +const RESULT_INDEX = 2; + // The command that dismisses a single result. const DISMISS_ONE_COMMAND = "dismiss-one"; @@ -20,18 +24,40 @@ const FEEDBACK_COMMAND = "show_less_frequently"; let gTestProvider; add_setup(async function () { + // This test expects the following results in the following order: + // + // 1. The heuristic + // 2. A history result + // 3. A result from our test provider. This will be the main result we'll use + // during this test. + // 4. Another history result + // + // This ensures a couple things: + // + // * The main test result has rows above and below it. Feedback and dismissal + // acknowledgments in the main result row should not affect adjacent rows, + // except that when the dismissal acknowledgment itself is dismissed, it + // should be replaced by the row below it. + // * The main result does not have a row label (a.k.a. group label). There's a + // separate task that specifically checks the row label, and that way this + // test covers both cases, where the row does and does not have a row label. gTestProvider = new TestProvider({ results: [ - new UrlbarResult( - UrlbarUtils.RESULT_TYPE.URL, - UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, - { - url: "https://example.com/", - isBlockable: true, - blockL10n: { - id: "urlbar-result-menu-dismiss-firefox-suggest", - }, - } + Object.assign( + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.URL, + UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, + { + url: "https://example.com/", + isBlockable: true, + blockL10n: { + id: "urlbar-result-menu-dismiss-firefox-suggest", + }, + } + ), + // This ensures the result is sandwiched between the two history results + // in the Firefox Suggest group. + { suggestedIndex: 1, isSuggestedIndexRelativeToGroup: true } ), ], }); @@ -39,13 +65,15 @@ add_setup(async function () { gTestProvider.commandCount = {}; UrlbarProvidersManager.registerProvider(gTestProvider); - // Add a visit so that there's one result above the test result (the - // heuristic) and one below (the visit) just to make sure removing the test - // result doesn't mess up adjacent results. await PlacesUtils.history.clear(); await PlacesUtils.bookmarks.eraseEverything(); await UrlbarTestUtils.formHistory.clear(); - await PlacesTestUtils.addVisits("https://example.com/aaa"); + + // Add visits for the two history results. + await PlacesTestUtils.addVisits([ + "https://example.com/aaa", + "https://example.com/bbb", + ]); registerCleanupFunction(() => { UrlbarProvidersManager.unregisterProvider(gTestProvider); @@ -72,13 +100,9 @@ add_task(async function acknowledgeDismissal_rowSelected() { }); // Select the row. - let resultIndex = await getTestResultIndex(); - while (gURLBar.view.selectedRowIndex != resultIndex) { - this.EventUtils.synthesizeKey("KEY_ArrowDown"); - } + gURLBar.view.selectedRowIndex = RESULT_INDEX; await doDismissTest({ - resultIndex, command: DISMISS_ONE_COMMAND, shouldBeSelected: true, }); @@ -95,12 +119,14 @@ add_task(async function acknowledgeFeedbackAndDismissal() { value: "test", }); - let resultIndex = await getTestResultIndex(); - let details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex); + let details = await UrlbarTestUtils.getDetailsOfResultAt( + window, + RESULT_INDEX + ); // Click the feedback command. await UrlbarTestUtils.openResultMenuAndClickItem(window, FEEDBACK_COMMAND, { - resultIndex, + resultIndex: RESULT_INDEX, }); Assert.equal( @@ -121,7 +147,6 @@ add_task(async function acknowledgeFeedbackAndDismissal() { info("Doing dismissal"); await doDismissTest({ - resultIndex, command: DISMISS_ONE_COMMAND, shouldBeSelected: true, }); @@ -139,6 +164,29 @@ add_task(async function acknowledgeDismissal_all() { }); }); +// When a row with a row label (a.k.a. group label) is dismissed, the dismissal +// acknowledgment tip should retain the label. When the tip is then dismissed, +// the row that replaces it should also retain the label. +add_task(async function acknowledgeDismissal_rowLabel() { + // Show the result as the first row in the Firefox Suggest section so that it + // has the "Firefox Suggest" group label. + let { suggestedIndex } = gTestProvider.results[0]; + gTestProvider.results[0].suggestedIndex = 0; + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test", + }); + await doDismissTest({ + resultIndex: 1, + command: DISMISS_ALL_COMMAND, + shouldBeSelected: false, + expectedLabel: "Firefox Suggest", + }); + + gTestProvider.results[0].suggestedIndex = suggestedIndex; +}); + /** * Does a dismissal test: * @@ -158,10 +206,25 @@ add_task(async function acknowledgeDismissal_all() { * @param {number} options.resultIndex * The index of the test result, if known beforehand. Leave -1 to find it * automatically. + * @param {string} options.expectedLabel + * The row label (a.k.a. group label) the row is expected to have. This should + * be the expected translated en-US string, not an l10n object. If null, the + * row is expected not to have a row label at all. */ -async function doDismissTest({ command, shouldBeSelected, resultIndex = -1 }) { - if (resultIndex < 0) { - resultIndex = await getTestResultIndex(); +async function doDismissTest({ + command, + shouldBeSelected, + resultIndex = 2, + expectedLabel = null, +}) { + let details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex); + Assert.equal( + details.result.providerName, + gTestProvider.name, + "The test result should be at the expected index" + ); + if (details.result.providerName != gTestProvider.name) { + return; } let selectedElement = gURLBar.view.selectedElement; @@ -181,6 +244,9 @@ async function doDismissTest({ command, shouldBeSelected, resultIndex = -1 }) { ); } + info("Checking the row label on the original row"); + await checkRowLabel(resultIndex, expectedLabel); + let resultCount = UrlbarTestUtils.getResultCount(window); // Click the command. @@ -204,7 +270,7 @@ async function doDismissTest({ command, shouldBeSelected, resultIndex = -1 }) { "The result count should not haved changed after dismissal" ); - let details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex); + details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex); Assert.equal( details.type, UrlbarUtils.RESULT_TYPE.TIP, @@ -235,6 +301,9 @@ async function doDismissTest({ command, shouldBeSelected, resultIndex = -1 }) { "Row should not have feedback acknowledgment after dismissal" ); + info("Checking the row label on the dismissal acknowledgment tip"); + await checkRowLabel(resultIndex, expectedLabel); + // Get the dismissal acknowledgment's "Got it" button. let gotItButton = UrlbarTestUtils.getButtonForResultIndex( window, @@ -284,6 +353,11 @@ async function doDismissTest({ command, shouldBeSelected, resultIndex = -1 }) { ); } + info( + "Checking the row label on the row that replaced the dismissal acknowledgment tip" + ); + await checkRowLabel(resultIndex, expectedLabel); + await UrlbarTestUtils.promisePopupClose(window); } @@ -291,7 +365,7 @@ async function doDismissTest({ command, shouldBeSelected, resultIndex = -1 }) { * A provider that acknowledges feedback and dismissals. */ class TestProvider extends UrlbarTestUtils.TestProvider { - getResultCommands(result) { + getResultCommands(_result) { // The l10n values aren't important. return [ { @@ -347,15 +421,27 @@ class TestProvider extends UrlbarTestUtils.TestProvider { } } -async function getTestResultIndex() { - let index = 0; - let resultCount = UrlbarTestUtils.getResultCount(window); - for (; index < resultCount; index++) { - let details = await UrlbarTestUtils.getDetailsOfResultAt(window, index); - if (details.result.providerName == gTestProvider.name) { - break; - } +async function checkRowLabel(resultIndex, expectedLabel) { + let details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex); + let { row } = details.element; + let before = getComputedStyle(row, "::before"); + + if (expectedLabel) { + Assert.equal( + before.content, + "attr(label)", + "::before content should use the row label" + ); + Assert.equal( + row.getAttribute("label"), + expectedLabel, + "Row should have the expected label attribute" + ); + } else { + Assert.equal(before.content, "none", "::before content should be 'none'"); + Assert.ok( + !row.hasAttribute("label"), + "Row should not have a label attribute" + ); } - Assert.less(index, resultCount, "The test result should be present"); - return index; } diff --git a/browser/components/urlbar/tests/browser/browser_add_search_engine.js b/browser/components/urlbar/tests/browser/browser_add_search_engine.js index cfcaccfdd5..5ee41649ba 100644 --- a/browser/components/urlbar/tests/browser/browser_add_search_engine.js +++ b/browser/components/urlbar/tests/browser/browser_add_search_engine.js @@ -85,9 +85,6 @@ add_task(async function context_one() { add_task(async function context_invalid() { info("Checks the context menu with a page that offers an invalid engine."); - await SpecialPowers.pushPrefEnv({ - set: [["prompts.contentPromptSubDialog", false]], - }); let url = getRootDirectory(gTestPath) + "add_search_engine_invalid.html"; await BrowserTestUtils.withNewTab(url, async tab => { @@ -321,5 +318,5 @@ function promiseEngine(expectedData, expectedEngineName) { expectedEngineName == engine.wrappedJSObject.name ); } - ).then(([engine, data]) => engine); + ).then(([engine]) => engine); } diff --git a/browser/components/urlbar/tests/browser/browser_autoOpen.js b/browser/components/urlbar/tests/browser/browser_autoOpen.js index bfe491fc61..19035e4149 100644 --- a/browser/components/urlbar/tests/browser/browser_autoOpen.js +++ b/browser/components/urlbar/tests/browser/browser_autoOpen.js @@ -41,7 +41,7 @@ add_setup(async function () { add_task(async function test() { await BrowserTestUtils.withNewTab( { gBrowser, url: "about:blank" }, - async browser => { + async () => { await checkOpensOnFocus(); } ); diff --git a/browser/components/urlbar/tests/browser/browser_bestMatch.js b/browser/components/urlbar/tests/browser/browser_bestMatch.js index 21c97405a6..a21f81dfee 100644 --- a/browser/components/urlbar/tests/browser/browser_bestMatch.js +++ b/browser/components/urlbar/tests/browser/browser_bestMatch.js @@ -117,11 +117,7 @@ add_task(async function keySelection() { }); }); -async function checkBestMatchRow({ - result, - isSponsored = false, - hasHelpUrl = false, -}) { +async function checkBestMatchRow({ result, hasHelpUrl = false }) { Assert.equal( UrlbarTestUtils.getResultCount(window), 1, diff --git a/browser/components/urlbar/tests/browser/browser_blanking.js b/browser/components/urlbar/tests/browser/browser_blanking.js index f68c4d894a..b5ec976eac 100644 --- a/browser/components/urlbar/tests/browser/browser_blanking.js +++ b/browser/components/urlbar/tests/browser/browser_blanking.js @@ -46,7 +46,7 @@ add_task(async function () { await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { // This is sync, so by the time we return we should have changed the URL bar. content.location.reload(); - }).catch(e => { + }).catch(() => { // Ignore expected exception. }); is( diff --git a/browser/components/urlbar/tests/browser/browser_clipboard.js b/browser/components/urlbar/tests/browser/browser_clipboard.js index f6127ef8d9..2332f595cc 100644 --- a/browser/components/urlbar/tests/browser/browser_clipboard.js +++ b/browser/components/urlbar/tests/browser/browser_clipboard.js @@ -19,8 +19,10 @@ add_setup(async function () { ["browser.urlbar.suggest.clipboard", true], ], }); - registerCleanupFunction(() => { + + registerCleanupFunction(async () => { SpecialPowers.clipboardCopyString(""); + await PlacesUtils.history.clear(); }); }); @@ -52,7 +54,7 @@ add_task(async function testFormattingOfClipboardSuggestion() { await BrowserTestUtils.withNewTab( { gBrowser, url: "about:home" }, - async browser => { + async () => { let { result } = await searchEmptyStringAndGetFirstRow(); Assert.equal( @@ -73,6 +75,7 @@ add_task(async function testFormattingOfClipboardSuggestion() { } ); }); + // Verifies that a valid URL copied to the clipboard results in the // display of a corresponding suggestion in the URL bar as the first // suggestion with accurate URL and icon. Also ensures that engaging @@ -121,6 +124,7 @@ add_task(async function testUserEngagementWithClipboardSuggestion() { await checkClipboardSuggestionAbsent(0); } ); + await PlacesUtils.history.clear(); }); // This test confirms that dismissing the result from the result menu @@ -347,3 +351,38 @@ add_task(async function testScalarAndStopWatchTelemetry() { } ); }); + +add_task(async function emptySearch_withClipboardEntry() { + SpecialPowers.clipboardCopyString("https://example.com/1"); + const MAX_RESULTS = 3; + let expectedHistoryResults = []; + + for (let i = 0; i < MAX_RESULTS; i++) { + await PlacesTestUtils.addVisits([`http://mochi.test/${i}`]); + expectedHistoryResults.push(`http://mochi.test/${i}`); + } + + await BrowserTestUtils.withNewTab("about:robots", async function () { + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "", + }); + await UrlbarTestUtils.enterSearchMode(window, { + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + }); + + let urls = []; + + for (let i = 0; i < UrlbarTestUtils.getResultCount(window); i++) { + let url = (await UrlbarTestUtils.getDetailsOfResultAt(window, i)).url; + urls.push(url); + } + + urls.reverse(); + Assert.deepEqual(expectedHistoryResults, urls); + + await UrlbarTestUtils.exitSearchMode(window, { clickClose: true }); + await UrlbarTestUtils.promisePopupClose(window); + }); + await PlacesUtils.history.clear(); +}); diff --git a/browser/components/urlbar/tests/browser/browser_copy_during_load.js b/browser/components/urlbar/tests/browser/browser_copy_during_load.js index 4a81ff08be..3eaa53bcda 100644 --- a/browser/components/urlbar/tests/browser/browser_copy_during_load.js +++ b/browser/components/urlbar/tests/browser/browser_copy_during_load.js @@ -13,7 +13,7 @@ add_task(async function () { "http://www.example.com" ) + "slow-page.sjs"; - await BrowserTestUtils.withNewTab(gBrowser, async tab => { + await BrowserTestUtils.withNewTab(gBrowser, async () => { gURLBar.focus(); gURLBar.value = SLOW_PAGE; let promise = TestUtils.waitForCondition( diff --git a/browser/components/urlbar/tests/browser/browser_copying.js b/browser/components/urlbar/tests/browser/browser_copying.js index 111df58fd1..d9ad6ebaaf 100644 --- a/browser/components/urlbar/tests/browser/browser_copying.js +++ b/browser/components/urlbar/tests/browser/browser_copying.js @@ -727,7 +727,7 @@ add_task(async function loadingPageInBlank() { async function waitForNewTabWithLoadRequest() { return new Promise(resolve => gBrowser.addTabsProgressListener({ - onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { + onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags) { if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) { gBrowser.removeTabsProgressListener(this); resolve(gBrowser.getTabForBrowser(aBrowser)); diff --git a/browser/components/urlbar/tests/browser/browser_dragdropURL.js b/browser/components/urlbar/tests/browser/browser_dragdropURL.js index 52c19e8965..1e194ee6af 100644 --- a/browser/components/urlbar/tests/browser/browser_dragdropURL.js +++ b/browser/components/urlbar/tests/browser/browser_dragdropURL.js @@ -43,7 +43,7 @@ function simulateURLBarDrop(content) { } add_task(async function checkDragURL() { - await BrowserTestUtils.withNewTab(TEST_URL, function (browser) { + await BrowserTestUtils.withNewTab(TEST_URL, function () { info("Check dragging a normal url to the urlbar"); const DRAG_URL = "http://www.example.com/"; simulateURLBarDrop({ type: "text/plain", data: DRAG_URL }); @@ -61,7 +61,7 @@ add_task(async function checkDragURL() { }); add_task(async function checkDragForbiddenURL() { - await BrowserTestUtils.withNewTab(TEST_URL, function (browser) { + await BrowserTestUtils.withNewTab(TEST_URL, function () { // See also browser_removeUnsafeProtocolsFromURLBarPaste.js for other // examples. In general we trust that function, we pick some testcases to // ensure we disallow dropping trimmed text. diff --git a/browser/components/urlbar/tests/browser/browser_dynamicResults.js b/browser/components/urlbar/tests/browser/browser_dynamicResults.js index 976ae3b9cb..aad15e0145 100644 --- a/browser/components/urlbar/tests/browser/browser_dynamicResults.js +++ b/browser/components/urlbar/tests/browser/browser_dynamicResults.js @@ -580,7 +580,7 @@ add_task(async function highlighting() { addCallback(this, result); } - getViewUpdate(result, idsByName) { + getViewUpdate(_result, _idsByName) { return {}; } } @@ -617,7 +617,7 @@ add_task(async function highlighting() { * Provides a dynamic result with highlighted text that is then overridden. */ class TestHighlightProviderOveridden extends TestHighlightProvider { - getViewUpdate(result, idsByName) { + getViewUpdate(_result, _idsByName) { return { text: { textContent: "Test title", @@ -904,7 +904,7 @@ class TestProvider extends UrlbarTestUtils.TestProvider { }; } - onEngagement(state, queryContext, details, controller) { + onEngagement(state, queryContext, details, _controller) { if (this._pickPromiseResolve) { let { result, element } = details; this._pickPromiseResolve([result, element]); diff --git a/browser/components/urlbar/tests/browser/browser_groupLabels.js b/browser/components/urlbar/tests/browser/browser_groupLabels.js index 2b43990b77..d04b6bc194 100644 --- a/browser/components/urlbar/tests/browser/browser_groupLabels.js +++ b/browser/components/urlbar/tests/browser/browser_groupLabels.js @@ -139,7 +139,7 @@ add_task(async function generalBeforeSuggestions() { add_task(async function generalBeforeSuggestions_suggestionsOnly() { await PlacesUtils.history.clear(); - await withSuggestions(async engine => { + await withSuggestions(async () => { await SpecialPowers.pushPrefEnv({ set: [[SUGGESTIONS_FIRST_PREF, false]], }); @@ -196,7 +196,7 @@ add_task(async function suggestedIndex_only() { let provider = new SuggestedIndexProvider(index); UrlbarProvidersManager.registerProvider(provider); - await withSuggestions(async engine => { + await withSuggestions(async () => { await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, value: "test", diff --git a/browser/components/urlbar/tests/browser/browser_locationBarCommand.js b/browser/components/urlbar/tests/browser/browser_locationBarCommand.js index 670b9741f4..84c45e586a 100644 --- a/browser/components/urlbar/tests/browser/browser_locationBarCommand.js +++ b/browser/components/urlbar/tests/browser/browser_locationBarCommand.js @@ -299,7 +299,7 @@ async function triggerCommand(eventType, details = {}) { function promiseLoadStarted() { return new Promise(resolve => { gBrowser.addTabsProgressListener({ - onStateChange(browser, webProgress, req, flags, status) { + onStateChange(browser, webProgress, req, flags) { if (flags & Ci.nsIWebProgressListener.STATE_START) { gBrowser.removeTabsProgressListener(this); resolve(); diff --git a/browser/components/urlbar/tests/browser/browser_locationBarExternalLoad.js b/browser/components/urlbar/tests/browser/browser_locationBarExternalLoad.js index 5a44db54ce..13457db52e 100644 --- a/browser/components/urlbar/tests/browser/browser_locationBarExternalLoad.js +++ b/browser/components/urlbar/tests/browser/browser_locationBarExternalLoad.js @@ -52,7 +52,7 @@ function promiseLoaded(browser) { }); } -async function testURL(url, loadFunc, endFunc) { +async function testURL(url, loadFunc) { let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); let browser = tab.linkedBrowser; @@ -70,7 +70,7 @@ async function testURL(url, loadFunc, endFunc) { await SpecialPowers.spawn( browser, [{ isRemote: gMultiProcessBrowser }], - async function (arg) { + async function () { Assert.equal( Services.focus.focusedElement, null, diff --git a/browser/components/urlbar/tests/browser/browser_locationchange_urlbar_edit_dos.js b/browser/components/urlbar/tests/browser/browser_locationchange_urlbar_edit_dos.js index b50446a4c9..4e91069b4a 100644 --- a/browser/components/urlbar/tests/browser/browser_locationchange_urlbar_edit_dos.js +++ b/browser/components/urlbar/tests/browser/browser_locationchange_urlbar_edit_dos.js @@ -5,7 +5,7 @@ const TEST_URL = `${TEST_BASE_URL}file_urlbar_edit_dos.html`; -async function checkURLBarValueStays(browser) { +async function checkURLBarValueStays() { gURLBar.select(); EventUtils.sendString("a"); is(gURLBar.value, "a", "URL bar value should match after sending a key"); diff --git a/browser/components/urlbar/tests/browser/browser_oneOffs_heuristicRestyle.js b/browser/components/urlbar/tests/browser/browser_oneOffs_heuristicRestyle.js index 8f7f058dd8..6badfca72e 100644 --- a/browser/components/urlbar/tests/browser/browser_oneOffs_heuristicRestyle.js +++ b/browser/components/urlbar/tests/browser/browser_oneOffs_heuristicRestyle.js @@ -188,7 +188,7 @@ async function heuristicIsRestyled( if (engine) { Assert.equal( resultDetails.image, - engine.getIconURL() || UrlbarUtils.ICON.SEARCH_GLASS, + (await engine.getIconURL()) || UrlbarUtils.ICON.SEARCH_GLASS, "The restyled result's icon should be the engine's icon." ); } else if (source) { diff --git a/browser/components/urlbar/tests/browser/browser_oneOffs_settings.js b/browser/components/urlbar/tests/browser/browser_oneOffs_settings.js index b4b1e7006e..2def88b5f9 100644 --- a/browser/components/urlbar/tests/browser/browser_oneOffs_settings.js +++ b/browser/components/urlbar/tests/browser/browser_oneOffs_settings.js @@ -36,7 +36,7 @@ add_setup(async function () { async function selectSettings(win, activateFn) { await BrowserTestUtils.withNewTab( { gBrowser: win.gBrowser, url: "about:blank" }, - async browser => { + async () => { await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "example.com", diff --git a/browser/components/urlbar/tests/browser/browser_recentsearches.js b/browser/components/urlbar/tests/browser/browser_recentsearches.js index e0ba5f684f..d2b91a3a53 100644 --- a/browser/components/urlbar/tests/browser/browser_recentsearches.js +++ b/browser/components/urlbar/tests/browser/browser_recentsearches.js @@ -6,10 +6,51 @@ const CONFIG_DEFAULT = [ { webExtension: { id: "basic@search.mozilla.org" }, appliesTo: [{ included: { everywhere: true } }], + urls: { + trending: { + fullPath: + "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs", + query: "", + }, + }, default: "yes", }, ]; +const CONFIG_DEFAULT_V2 = [ + { + recordType: "engine", + identifier: "basic", + base: { + name: "basic", + urls: { + search: { + base: "https://example.com", + searchTermParamName: "q", + }, + trending: { + base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs", + method: "GET", + }, + }, + }, + variants: [ + { + environment: { allRegionsAndLocales: true }, + }, + ], + }, + { + recordType: "defaultEngines", + globalDefault: "basic", + specificDefaults: [], + }, + { + recordType: "engineOrders", + orders: [], + }, +]; + const TOP_SITES = [ "https://example-1.com/", "https://example-2.com/", @@ -38,7 +79,9 @@ add_setup(async () => { }); SearchTestUtils.useMockIdleService(); - await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_DEFAULT); + await SearchTestUtils.updateRemoteSettingsConfig( + SearchUtils.newSearchConfigEnabled ? CONFIG_DEFAULT_V2 : CONFIG_DEFAULT + ); Services.telemetry.clearScalars(); registerCleanupFunction(async () => { @@ -135,4 +178,53 @@ add_task(async () => { Assert.equal(result.providerName, "RecentSearches"); await BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +// Test that triggering the help menu of trending suggestions does not +// record that selection as a search. +add_task(async () => { + await UrlbarTestUtils.formHistory.clear(); + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.suggest.topsites", false], + ["browser.urlbar.suggest.trending", true], + ["browser.urlbar.trending.featureGate", true], + ["browser.urlbar.trending.requireSearchMode", false], + ["app.support.baseURL", "https://example.com"], + ], + }); + + let tab = await BrowserTestUtils.openNewForegroundTab( + window.gBrowser, + "data:text/html," + ); + + info("Open the urlbar and pick the help menu of a trending result."); + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "", + }); + + await UrlbarTestUtils.openResultMenuAndClickItem(window, "help", { + resultIndex: 1, + openByMouse: true, + }); + + info("Open the urlbar and check that a recent search has not been added."); + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "", + }); + + let { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 0); + Assert.notEqual( + result.providerName, + "RecentSearches", + "Click on help URL did not record a search" + ); + + await BrowserTestUtils.removeTab(gBrowser.selectedTab); + await BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); }); diff --git a/browser/components/urlbar/tests/browser/browser_redirect_error.js b/browser/components/urlbar/tests/browser/browser_redirect_error.js index ae8dec3da6..5f5194e5fc 100644 --- a/browser/components/urlbar/tests/browser/browser_redirect_error.js +++ b/browser/components/urlbar/tests/browser/browser_redirect_error.js @@ -67,7 +67,7 @@ var gWebProgressListener = { // onSecurityChange: function() {}, // ---------------------------------------------------------------------------- - onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { + onLocationChange(aWebProgress, aRequest, aLocation) { if (!aRequest) { // This is bug 673752, or maybe initial "about:blank". return; diff --git a/browser/components/urlbar/tests/browser/browser_remove_match.js b/browser/components/urlbar/tests/browser/browser_remove_match.js index b9e97044e4..503f01875c 100644 --- a/browser/components/urlbar/tests/browser/browser_remove_match.js +++ b/browser/components/urlbar/tests/browser/browser_remove_match.js @@ -186,7 +186,7 @@ add_task(async function test_searchMode_removeRestyledHistory() { let url = `https://example.com/?q=${query}bar`; await PlacesTestUtils.addVisits(url); - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, value: query, diff --git a/browser/components/urlbar/tests/browser/browser_result_onSelection.js b/browser/components/urlbar/tests/browser/browser_result_onSelection.js index 2a5f8c3760..04f2847591 100644 --- a/browser/components/urlbar/tests/browser/browser_result_onSelection.js +++ b/browser/components/urlbar/tests/browser/browser_result_onSelection.js @@ -48,7 +48,7 @@ add_task(async function test() { let provider = new UrlbarTestUtils.TestProvider({ results, priority: 1, - onSelection: (result, element) => { + onSelection: () => { selectionCount++; }, }); diff --git a/browser/components/urlbar/tests/browser/browser_results_format_displayValue.js b/browser/components/urlbar/tests/browser/browser_results_format_displayValue.js index d0ec3d3818..5575293d06 100644 --- a/browser/components/urlbar/tests/browser/browser_results_format_displayValue.js +++ b/browser/components/urlbar/tests/browser/browser_results_format_displayValue.js @@ -22,7 +22,7 @@ add_task(async function test_receive_punycode_result() { addCallback(this, result); } - getViewUpdate(result, idsByName) { + getViewUpdate(_result, _idsByName) { return {}; } } diff --git a/browser/components/urlbar/tests/browser/browser_retainedResultsOnFocus.js b/browser/components/urlbar/tests/browser/browser_retainedResultsOnFocus.js index 3cc26a5757..fe3b24a675 100644 --- a/browser/components/urlbar/tests/browser/browser_retainedResultsOnFocus.js +++ b/browser/components/urlbar/tests/browser/browser_retainedResultsOnFocus.js @@ -95,7 +95,7 @@ async function test_window(win) { // we just wait for the expected currentURI value. await BrowserTestUtils.withNewTab( { gBrowser: win.gBrowser, url, waitForLoad: false }, - async browser => { + async () => { await TestUtils.waitForCondition( () => win.gBrowser.currentURI.spec == url, "Ensure we're on the expected page" diff --git a/browser/components/urlbar/tests/browser/browser_revert.js b/browser/components/urlbar/tests/browser/browser_revert.js index b68ad0ff91..faa2d92366 100644 --- a/browser/components/urlbar/tests/browser/browser_revert.js +++ b/browser/components/urlbar/tests/browser/browser_revert.js @@ -7,7 +7,7 @@ add_task(async function () { gBrowser, url: "http://example.com", }, - async function (browser) { + async function () { let originalValue = gURLBar.value; let tab = gBrowser.selectedTab; info("Put a typed value."); diff --git a/browser/components/urlbar/tests/browser/browser_searchMode_indicator.js b/browser/components/urlbar/tests/browser/browser_searchMode_indicator.js index 707a4ea38e..f86b1527bf 100644 --- a/browser/components/urlbar/tests/browser/browser_searchMode_indicator.js +++ b/browser/components/urlbar/tests/browser/browser_searchMode_indicator.js @@ -196,7 +196,7 @@ add_task(async function escapeOnInitialPage() { add_task(async function escapeOnBrowsingPage() { info("Tests the indicator's interaction with the ESC key on browsing page"); - await BrowserTestUtils.withNewTab("http://example.com", async browser => { + await BrowserTestUtils.withNewTab("http://example.com", async () => { await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, value: TEST_QUERY, @@ -355,7 +355,7 @@ add_task(async function menubar_item() { // 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 BrowserTestUtils.withNewTab("about:robots", async function () { await UrlbarTestUtils.promisePopupOpen(window, () => { EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {}); }); diff --git a/browser/components/urlbar/tests/browser/browser_searchMode_indicator_clickthrough.js b/browser/components/urlbar/tests/browser/browser_searchMode_indicator_clickthrough.js index 214448ee61..f53417834e 100644 --- a/browser/components/urlbar/tests/browser/browser_searchMode_indicator_clickthrough.js +++ b/browser/components/urlbar/tests/browser/browser_searchMode_indicator_clickthrough.js @@ -14,7 +14,7 @@ add_task(async function test() { set: [["browser.search.suggest.enabled", false]], }); - await BrowserTestUtils.withNewTab("about:robots", async browser => { + await BrowserTestUtils.withNewTab("about:robots", async () => { // View open, with string. await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, @@ -69,7 +69,7 @@ add_task(async function test() { Assert.ok(!BrowserTestUtils.isVisible(labelBox)); }); - await BrowserTestUtils.withNewTab("about:robots", async browser => { + await BrowserTestUtils.withNewTab("about:robots", async () => { await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, value: "test", diff --git a/browser/components/urlbar/tests/browser/browser_searchMode_localOneOffs_actionText.js b/browser/components/urlbar/tests/browser/browser_searchMode_localOneOffs_actionText.js index 2068d4c1d5..7b045e517c 100644 --- a/browser/components/urlbar/tests/browser/browser_searchMode_localOneOffs_actionText.js +++ b/browser/components/urlbar/tests/browser/browser_searchMode_localOneOffs_actionText.js @@ -94,7 +94,7 @@ add_task(async function localOneOff() { ); Assert.equal( result.image, - oneOffButtons.selectedButton.engine.getIconURL(), + await oneOffButtons.selectedButton.engine.getIconURL(), "Check the heuristic icon" ); diff --git a/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js b/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js index 6e9b3c1031..607cd220a1 100644 --- a/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js +++ b/browser/components/urlbar/tests/browser/browser_searchMode_suggestions.js @@ -74,7 +74,7 @@ add_setup(async function () { }); add_task(async function emptySearch() { - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.update2.emptySearchBehavior", 2]], }); @@ -109,7 +109,7 @@ add_task(async function emptySearch_withRestyledHistory() { // Can be restyled but does not dupe form history. "http://mochi.test:8888/?terms=ciao", ]); - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.update2.emptySearchBehavior", 2]], }); @@ -162,7 +162,7 @@ add_task(async function emptySearch_withRestyledHistory_noSearchHistory() { // Can be restyled but does not dupe form history. "http://mochi.test:8888/?terms=ciao", ]); - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { await SpecialPowers.pushPrefEnv({ set: [ ["browser.urlbar.update2.emptySearchBehavior", 2], @@ -204,7 +204,7 @@ 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 BrowserTestUtils.withNewTab("about:robots", async function () { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.update2.emptySearchBehavior", 0]], }); @@ -245,7 +245,7 @@ add_task(async function emptySearch_behavior() { await SpecialPowers.popPrefEnv(); }); - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.update2.emptySearchBehavior", 1]], }); @@ -269,7 +269,7 @@ add_task(async function emptySearch_behavior() { add_task(async function emptySearch_local() { await PlacesTestUtils.addVisits([`http://mochi.test/`]); - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.update2.emptySearchBehavior", 0]], }); @@ -300,7 +300,7 @@ add_task(async function emptySearch_local() { }); add_task(async function nonEmptySearch() { - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { let query = "hello"; await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, @@ -348,7 +348,7 @@ add_task(async function nonEmptySearch() { }); add_task(async function nonEmptySearch_nonMatching() { - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { let query = "ciao"; await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, @@ -422,7 +422,7 @@ add_task(async function nonEmptySearch_withHistory() { }; } - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, value: query, @@ -520,7 +520,7 @@ add_task(async function nonEmptySearch_withHistory() { }); add_task(async function nonEmptySearch_url() { - await BrowserTestUtils.withNewTab("about:robots", async function (browser) { + await BrowserTestUtils.withNewTab("about:robots", async function () { let query = "http://www.example.com/"; await UrlbarTestUtils.promiseAutocompleteResultPopup({ window, diff --git a/browser/components/urlbar/tests/browser/browser_searchSingleWordNotification.js b/browser/components/urlbar/tests/browser/browser_searchSingleWordNotification.js index 36a065d58e..f217915939 100644 --- a/browser/components/urlbar/tests/browser/browser_searchSingleWordNotification.js +++ b/browser/components/urlbar/tests/browser/browser_searchSingleWordNotification.js @@ -62,7 +62,7 @@ async function runURLBarSearchTest({ for (let i = 0; i < setValueFns.length; ++i) { await setValueFns[i](valueToOpen); let topic = "uri-fixup-check-dns"; - let observer = (aSubject, aTopicInner, aData) => { + let observer = (aSubject, aTopicInner) => { if (aTopicInner == topic) { gDNSResolved = true; } @@ -248,7 +248,7 @@ function get_test_function_for_localhost_with_hostname( gBrowser: win.gBrowser, url: "about:blank", }, - browser => + () => runURLBarSearchTest({ valueToOpen: hostName, expectSearch: true, @@ -268,7 +268,7 @@ function get_test_function_for_localhost_with_hostname( gBrowser: win.gBrowser, url: "about:blank", }, - browser => + () => runURLBarSearchTest({ valueToOpen: hostName, expectSearch: true, @@ -289,7 +289,7 @@ function get_test_function_for_localhost_with_hostname( gBrowser: win.gBrowser, url: "about:blank", }, - browser => + () => runURLBarSearchTest({ valueToOpen: hostName, expectSearch: isPrivate, @@ -325,7 +325,7 @@ add_task(async function test_dnsResolveSingleWordsAfterSearch() { gBrowser, url: "about:blank", }, - browser => + () => runURLBarSearchTest({ valueToOpen: "localhost", expectSearch: true, diff --git a/browser/components/urlbar/tests/browser/browser_search_continuation.js b/browser/components/urlbar/tests/browser/browser_search_continuation.js index 8a24d57856..19c853c2e5 100644 --- a/browser/components/urlbar/tests/browser/browser_search_continuation.js +++ b/browser/components/urlbar/tests/browser/browser_search_continuation.js @@ -21,6 +21,65 @@ const CONFIG_DEFAULT = [ }, ]; +const CONFIG_V2 = [ + { + recordType: "engine", + identifier: "basic", + base: { + name: "basic", + urls: { + search: { + base: "https://example.com", + searchTermParamName: "q", + }, + trending: { + base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs", + method: "GET", + }, + }, + aliases: ["basic"], + }, + variants: [ + { + environment: { allRegionsAndLocales: true }, + }, + ], + }, + { + recordType: "engine", + identifier: "private", + base: { + name: "private", + urls: { + search: { + base: "https://example.com", + searchTermParamName: "q", + }, + suggestions: { + base: "https://example.com", + method: "GET", + searchTermParamName: "search", + }, + }, + aliases: ["private"], + }, + variants: [ + { + environment: { allRegionsAndLocales: true }, + }, + ], + }, + { + recordType: "defaultEngines", + globalDefault: "basic", + specificDefaults: [], + }, + { + recordType: "engineOrders", + orders: [], + }, +]; + add_setup(async () => { await SpecialPowers.pushPrefEnv({ set: [ @@ -39,7 +98,10 @@ add_setup(async () => { }); await UrlbarTestUtils.formHistory.clear(); - await SearchTestUtils.setupTestEngines("search-engines", CONFIG_DEFAULT); + await SearchTestUtils.setupTestEngines( + "search-engines", + SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT + ); registerCleanupFunction(async () => { await UrlbarTestUtils.formHistory.clear(); diff --git a/browser/components/urlbar/tests/browser/browser_selectStaleResults.js b/browser/components/urlbar/tests/browser/browser_selectStaleResults.js index c381478712..97f3768881 100644 --- a/browser/components/urlbar/tests/browser/browser_selectStaleResults.js +++ b/browser/components/urlbar/tests/browser/browser_selectStaleResults.js @@ -258,7 +258,7 @@ add_task(async function staleReplacedWithFresh() { // test2 // test1 let mutationPromise = new Promise(resolve => { - let observer = new MutationObserver(mutations => { + let observer = new MutationObserver(() => { let row = UrlbarTestUtils.getRowAt(window, maxResults - 2); if (row && row._elements.get("title").textContent == "test2") { observer.disconnect(); diff --git a/browser/components/urlbar/tests/browser/browser_shortcuts_add_search_engine.js b/browser/components/urlbar/tests/browser/browser_shortcuts_add_search_engine.js index 92eebf1997..43a3f7de9f 100644 --- a/browser/components/urlbar/tests/browser/browser_shortcuts_add_search_engine.js +++ b/browser/components/urlbar/tests/browser/browser_shortcuts_add_search_engine.js @@ -206,7 +206,7 @@ function promiseEngine(expectedData, expectedEngineName) { expectedEngineName == engine.wrappedJSObject.name ); } - ).then(([engine, data]) => engine); + ).then(([engine]) => engine); } add_task(async function shortcuts_without_other_engines() { diff --git a/browser/components/urlbar/tests/browser/browser_speculative_connect_not_with_client_cert.js b/browser/components/urlbar/tests/browser/browser_speculative_connect_not_with_client_cert.js index 62aec6f67a..36c8c23330 100644 --- a/browser/components/urlbar/tests/browser/browser_speculative_connect_not_with_client_cert.js +++ b/browser/components/urlbar/tests/browser/browser_speculative_connect_not_with_client_cert.js @@ -57,7 +57,7 @@ class SecurityObserver { this.output = output; } - onHandshakeDone(socket, status) { + onHandshakeDone() { info("TLS handshake done"); handshakeDone = true; diff --git a/browser/components/urlbar/tests/browser/browser_stop.js b/browser/components/urlbar/tests/browser/browser_stop.js index 285071a3ff..84667eaa53 100644 --- a/browser/components/urlbar/tests/browser/browser_stop.js +++ b/browser/components/urlbar/tests/browser/browser_stop.js @@ -57,7 +57,7 @@ async function typeAndSubmitAndStop(url) { // urlbar value has been updated, add our own progress listener here. let progressPromise = new Promise(resolve => { let listener = { - onStateChange(browser, webProgress, request, stateFlags, status) { + onStateChange(browser, webProgress, request, stateFlags) { if ( webProgress.isTopLevel && stateFlags & Ci.nsIWebProgressListener.STATE_STOP diff --git a/browser/components/urlbar/tests/browser/browser_strip_on_share.js b/browser/components/urlbar/tests/browser/browser_strip_on_share.js index 508106ccdc..9e045cee9c 100644 --- a/browser/components/urlbar/tests/browser/browser_strip_on_share.js +++ b/browser/components/urlbar/tests/browser/browser_strip_on_share.js @@ -112,7 +112,7 @@ async function testMenuItemDisabled(url, prefEnabled, selection) { await SpecialPowers.pushPrefEnv({ set: [["privacy.query_stripping.strip_on_share.enabled", prefEnabled]], }); - await BrowserTestUtils.withNewTab(url, async function (browser) { + await BrowserTestUtils.withNewTab(url, async function () { gURLBar.focus(); if (selection) { //select only part of the url @@ -175,7 +175,7 @@ async function testMenuItemEnabled({ await listService.testSetList(testJson); } - await BrowserTestUtils.withNewTab(validUrl, async function (browser) { + await BrowserTestUtils.withNewTab(validUrl, async function () { gURLBar.focus(); if (selectWholeUrl) { gURLBar.select(); diff --git a/browser/components/urlbar/tests/browser/browser_strip_on_share_telemetry.js b/browser/components/urlbar/tests/browser/browser_strip_on_share_telemetry.js index 48a8b6c729..7b6fb53e3b 100644 --- a/browser/components/urlbar/tests/browser/browser_strip_on_share_telemetry.js +++ b/browser/components/urlbar/tests/browser/browser_strip_on_share_telemetry.js @@ -80,7 +80,7 @@ add_task(async function testMultiQueryParams() { }); async function testStripOnShare(validUrl, strippedUrl) { - await BrowserTestUtils.withNewTab(validUrl, async function (browser) { + await BrowserTestUtils.withNewTab(validUrl, async function () { gURLBar.focus(); gURLBar.select(); let menuitem = await promiseContextualMenuitem("strip-on-share"); diff --git a/browser/components/urlbar/tests/browser/browser_switchTab_inputHistory.js b/browser/components/urlbar/tests/browser/browser_switchTab_inputHistory.js index 0da3161d0e..3dab8e7e64 100644 --- a/browser/components/urlbar/tests/browser/browser_switchTab_inputHistory.js +++ b/browser/components/urlbar/tests/browser/browser_switchTab_inputHistory.js @@ -25,16 +25,15 @@ add_task(async function test_adaptive_with_search_term_and_switch_tab() { info(`Load tabs in same order as urls`); let tabs = []; + let waitForVisits = PlacesTestUtils.waitForNotification( + "page-visited", + events => events.some(e => e.url === urls[3]) + ); for (let url of urls) { - let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, url, false, true); - gBrowser.loadTabs([url], { - inBackground: true, - triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), - }); - - let tab = await tabPromise; - tabs.push(tab); + tabs.push(await BrowserTestUtils.openNewForegroundTab({ gBrowser, url })); } + // Ensure visits have been added. + await waitForVisits; info(`Switch to tab 0`); await BrowserTestUtils.switchTab(gBrowser, tabs[0]); @@ -89,3 +88,57 @@ add_task(async function test_adaptive_with_search_term_and_switch_tab() { BrowserTestUtils.removeTab(tab); } }); + +add_task( + async function test_adaptive_nonadaptive_container_dedupe_switch_tab() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.userContext.enabled", true], + ["browser.urlbar.switchTabs.searchAllContainers", true], + ], + }); + // Add a url both to history and input history, ensure that the Muxer will + // properly dedupe the 2 entries, also with containers involved. + await PlacesUtils.history.clear(); + const url = "https://example.com/"; + + let promiseVisited = PlacesTestUtils.waitForNotification( + "page-visited", + events => events.some(e => e.url === url) + ); + let tab = BrowserTestUtils.addTab(gBrowser, url, { userContextId: 1 }); + await promiseVisited; + + async function queryAndCheckOneSwitchTabResult() { + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "xampl", + }); + Assert.equal( + 2, + UrlbarTestUtils.getResultCount(window), + "Check number of results" + ); + let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1); + Assert.equal(url, result.url, `Url is the first non-heuristic result`); + Assert.equal( + UrlbarUtils.RESULT_TYPE.TAB_SWITCH, + result.type, + "Should be a switch tab result" + ); + Assert.equal( + 1, + result.result.payload.userContextId, + "Should use the expected container" + ); + } + info("Check the tab is returned as history by a search."); + await queryAndCheckOneSwitchTabResult(); + info("Add the same url to input history."); + await UrlbarUtils.addToInputHistory(url, "xampl"); + info("Repeat the query."); + await queryAndCheckOneSwitchTabResult(); + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); + } +); diff --git a/browser/components/urlbar/tests/browser/browser_switchTab_override.js b/browser/components/urlbar/tests/browser/browser_switchTab_override.js index 66426a154b..507c975cba 100644 --- a/browser/components/urlbar/tests/browser/browser_switchTab_override.js +++ b/browser/components/urlbar/tests/browser/browser_switchTab_override.js @@ -54,7 +54,7 @@ add_task(async function test_switchtab_override() { info("Override switch-to-tab"); let deferred = Promise.withResolvers(); // In case of failure this would switch tab. - let onTabSelect = event => { + let onTabSelect = () => { deferred.reject(new Error("Should have overridden switch to tab")); }; gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect); diff --git a/browser/components/urlbar/tests/browser/browser_tabMatchesInAwesomebar.js b/browser/components/urlbar/tests/browser/browser_tabMatchesInAwesomebar.js index 354cd3a802..94d46b3b81 100644 --- a/browser/components/urlbar/tests/browser/browser_tabMatchesInAwesomebar.js +++ b/browser/components/urlbar/tests/browser/browser_tabMatchesInAwesomebar.js @@ -138,7 +138,7 @@ function loadTab(tab, url) { // Because adding visits is async, we will not be notified immediately. let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser); let visited = new Promise(resolve => { - Services.obs.addObserver(function observer(aSubject, aTopic, aData) { + Services.obs.addObserver(function observer(aSubject, aTopic) { if (url != aSubject.QueryInterface(Ci.nsIURI).spec) { return; } diff --git a/browser/components/urlbar/tests/browser/browser_tabToSearch.js b/browser/components/urlbar/tests/browser/browser_tabToSearch.js index a336980583..deba60ea1e 100644 --- a/browser/components/urlbar/tests/browser/browser_tabToSearch.js +++ b/browser/components/urlbar/tests/browser/browser_tabToSearch.js @@ -284,14 +284,14 @@ add_task(async function tab_key_race() { get type() { return UrlbarUtils.PROVIDER_TYPE.PROFILE; } - isActive(context) { + isActive(_context) { executeSoon(resolve); return false; } - isRestricting(context) { + isRestricting(_context) { return false; } - async startQuery(context, addCallback) { + async startQuery(_context, _addCallback) { // Nothing to do. } } diff --git a/browser/components/urlbar/tests/browser/browser_top_sites_switchtab.js b/browser/components/urlbar/tests/browser/browser_top_sites_switchtab.js new file mode 100644 index 0000000000..d4edce0f11 --- /dev/null +++ b/browser/components/urlbar/tests/browser/browser_top_sites_switchtab.js @@ -0,0 +1,209 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Test that TopSites are showing an appropriate Switch-tab status, depending + * on the state of the `browser.urlbar.switchTabs.searchAllContainers` pref. + * When the feature is enabled, in a normal window they should show the + * tab container, otherwise it's only possible to switch to a tab in the same + * container. + * In private windows it's only possible to switch to private tabs in the + * private container. Similarly non-private windows don't see private tabs. + * This test is not checking that switching to the appropriate tab works as that + * is already covered by other tests. + */ + +ChromeUtils.defineESModuleGetters(this, { + AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", + NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs", +}); + +const EN_US_TOPSITES = + "https://www.youtube.com/,https://www.facebook.com/,https://www.amazon.com/,https://www.reddit.com/"; +const OUR_TOPSITE_URL = "https://example.com/"; +const REF_TOPSITE_URL = OUR_TOPSITE_URL + "#someref"; +const TOPSITES_COUNT = EN_US_TOPSITES.split(",").length + 1; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.suggest.topsites", true], + ["browser.urlbar.suggest.quickactions", false], + ["browser.newtabpage.activity-stream.default.sites", EN_US_TOPSITES], + ], + }); + registerCleanupFunction(PlacesUtils.history.clear); +}); + +add_task(async function test_ignoreRef() { + info("Add some visits to a URL."); + await addAsFirstTopSite(REF_TOPSITE_URL); + + for (let val of [true, false]) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.switchTabs.searchAllContainers", val]], + }); + info("Test with searchAllContainer set to " + val.toString()); + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + REF_TOPSITE_URL + ); + // Switch back to the originating tab, to check for switch to the current tab. + await BrowserTestUtils.switchTab(gBrowser, gBrowser.tabs[0]); + await openAddressBarAndCheckResults(window, TOPSITES_COUNT, new Set([0])); + await BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); + } + await PlacesUtils.history.remove(REF_TOPSITE_URL); +}); + +add_task(async function test_topSitesTabSwitch() { + await addAsFirstTopSite(OUR_TOPSITE_URL); + + for (let val of [true, false]) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.switchTabs.searchAllContainers", val]], + }); + info("Test with searchAllContainer set to " + val.toString()); + await doTest(); + await SpecialPowers.popPrefEnv(); + } + await PlacesUtils.history.remove(OUR_TOPSITE_URL); +}); + +async function doTest() { + info("Non-private window"); + // Add a normal tab and a container tab. + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + OUR_TOPSITE_URL + ); + let containerTab = await loadNewForegroundContainerTab(OUR_TOPSITE_URL, 1); + // Switch back to the originating tab, to check for switch to the current tab. + await BrowserTestUtils.switchTab(gBrowser, gBrowser.tabs[0]); + let expectedUserContextIds = UrlbarPrefs.get("switchTabs.searchAllContainers") + ? new Set([0, 1]) + : new Set([0]); + await openAddressBarAndCheckResults( + window, + TOPSITES_COUNT + expectedUserContextIds.size - 1, + expectedUserContextIds + ); + + info("Private window"); + let pbWin = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + await openAddressBarAndCheckResults(pbWin, TOPSITES_COUNT, new Set()); + + info("Close the original tab and open the url in the private window instead"); + await BrowserTestUtils.removeTab(tab); + await BrowserTestUtils.openNewForegroundTab(pbWin.gBrowser, OUR_TOPSITE_URL); + // Switch back to the originating tab, to check for switch to the current tab. + await BrowserTestUtils.switchTab(pbWin.gBrowser, pbWin.gBrowser.tabs[0]); + await openAddressBarAndCheckResults( + window, + TOPSITES_COUNT, + UrlbarPrefs.get("switchTabs.searchAllContainers") ? new Set([1]) : new Set() + ); + await openAddressBarAndCheckResults(pbWin, TOPSITES_COUNT, new Set([-1])); + + // We're done with the private window. + await BrowserTestUtils.closeWindow(pbWin); + + info("Check Top sites in the same container tab"); + let blankSameContainerTab = await loadNewForegroundContainerTab( + "about:blank", + 1 + ); + await openAddressBarAndCheckResults(window, TOPSITES_COUNT, new Set([1])); + await BrowserTestUtils.removeTab(blankSameContainerTab); + + info("Check Top sites in a different container tab"); + let blankDiffContainerTab = await loadNewForegroundContainerTab( + "about:blank", + 2 + ); + await openAddressBarAndCheckResults( + window, + TOPSITES_COUNT, + UrlbarPrefs.get("switchTabs.searchAllContainers") ? new Set([1]) : new Set() + ); + await BrowserTestUtils.removeTab(blankDiffContainerTab); + + await BrowserTestUtils.removeTab(containerTab); +} + +async function openAddressBarAndCheckResults( + win, + expectedResultCount, + expectedTabSwitchUserContextIds +) { + info("Open zero-prefix results."); + await UrlbarTestUtils.promisePopupOpen(win, () => { + win.gURLBar.blur(); + if (win.gURLBar.getAttribute("pageproxystate") == "invalid") { + win.gURLBar.handleRevert(); + } + EventUtils.synthesizeMouseAtCenter(win.gURLBar.inputField, {}, win); + }); + await UrlbarTestUtils.promiseSearchComplete(win); + let resultCount = UrlbarTestUtils.getResultCount(win); + Assert.equal(expectedResultCount, resultCount, "Check number of results."); + + for (let i = 0; i < resultCount; ++i) { + let result = await UrlbarTestUtils.getDetailsOfResultAt(win, i); + + if (result.url != "https://example.com/") { + // We don't care about other top sites. + continue; + } + + if (!expectedTabSwitchUserContextIds.size) { + // No more tab switch results expected. + Assert.notEqual( + UrlbarUtils.RESULT_TYPE.TAB_SWITCH, + result.type, + "Should not be a tab switch result." + ); + continue; + } + + // Must be a tab switch result with an expected userContextId. + Assert.equal( + UrlbarUtils.RESULT_TYPE.TAB_SWITCH, + result.type, + "Should be a tab switch result." + ); + let hasUserContextId = expectedTabSwitchUserContextIds.delete( + result.userContextId + ); + Assert.ok( + hasUserContextId, + `UserContextId ${result.userContextId} tab switch was expected in + ${expectedTabSwitchUserContextIds}` + ); + } +} + +async function addAsFirstTopSite(url) { + info("Add some visits to a URL."); + await PlacesTestUtils.addVisits(Array(10).fill(url)); + info("Add top sites and await for our page to be the first"); + await updateTopSites(sites => { + return sites && sites.length == TOPSITES_COUNT && sites[0].url == url; + }); +} + +async function loadNewForegroundContainerTab(url, userContextId, win = window) { + let tab = BrowserTestUtils.addTab(win.gBrowser, url, { + userContextId, + }); + await Promise.all([ + BrowserTestUtils.browserLoaded(tab.linkedBrowser), + BrowserTestUtils.switchTab(win.gBrowser, tab), + ]); + return tab; +} diff --git a/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_dynamic.js b/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_dynamic.js index d4f4e77d57..1eef6fc0e0 100644 --- a/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_dynamic.js +++ b/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_dynamic.js @@ -39,7 +39,7 @@ class TestProvider extends UrlbarTestUtils.TestProvider { }); } - getViewUpdate(result, idsByName) { + getViewUpdate(_result, _idsByName) { return { title: { textContent: "This is a dynamic result.", diff --git a/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_tip.js b/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_tip.js index 345b063441..66ddb225fb 100644 --- a/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_tip.js +++ b/browser/components/urlbar/tests/browser/browser_urlbar_telemetry_tip.js @@ -115,10 +115,10 @@ class TipProvider extends UrlbarProvider { get type() { return UrlbarUtils.PROVIDER_TYPE.PROFILE; } - isActive(context) { + isActive(_context) { return true; } - getPriority(context) { + getPriority(_context) { return 1; } async startQuery(context, addCallback) { diff --git a/browser/components/urlbar/tests/browser/browser_valueOnTabSwitch.js b/browser/components/urlbar/tests/browser/browser_valueOnTabSwitch.js index ba249adb3b..03afeb3410 100644 --- a/browser/components/urlbar/tests/browser/browser_valueOnTabSwitch.js +++ b/browser/components/urlbar/tests/browser/browser_valueOnTabSwitch.js @@ -90,7 +90,7 @@ add_task(async function () { } function urlbarBackspace(removeAll) { - return new Promise((resolve, reject) => { + return new Promise(resolve => { gBrowser.selectedBrowser.focus(); gURLBar.addEventListener( "input", diff --git a/browser/components/urlbar/tests/browser/browser_view_removedSelectedElement.js b/browser/components/urlbar/tests/browser/browser_view_removedSelectedElement.js index 532f9e10a2..8ccb49d4ae 100644 --- a/browser/components/urlbar/tests/browser/browser_view_removedSelectedElement.js +++ b/browser/components/urlbar/tests/browser/browser_view_removedSelectedElement.js @@ -25,7 +25,7 @@ add_task(async function () { let firstSelectedElement; let delayResultsPromise = new Promise(resolve => { gURLBar.controller.addQueryListener({ - async onQueryResults(queryContext) { + async onQueryResults() { Assert.ok(!receivedResults, "Should execute only once"); gURLBar.controller.removeQueryListener(this); receivedResults = true; diff --git a/browser/components/urlbar/tests/browser/browser_view_selectionByMouse.js b/browser/components/urlbar/tests/browser/browser_view_selectionByMouse.js index fc617220b6..10110a8928 100644 --- a/browser/components/urlbar/tests/browser/browser_view_selectionByMouse.js +++ b/browser/components/urlbar/tests/browser/browser_view_selectionByMouse.js @@ -324,6 +324,9 @@ add_task(async function withDnsFirstForSingleWordsPref() { url: "https://example.org/", title: "example", }); + // An unvisited bookmark may have a lower ranking than a page visited many + // times, so let's clear history to ensure our bookmark is autofilled. + await PlacesUtils.history.clear(); await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); await UrlbarTestUtils.promiseAutocompleteResultPopup({ @@ -333,13 +336,13 @@ add_task(async function withDnsFirstForSingleWordsPref() { const details = await UrlbarTestUtils.getDetailsOfResultAt(window, 0); const target = details.element.action; - EventUtils.synthesizeMouseAtCenter(target, { type: "mousedown" }); + const onLoaded = BrowserTestUtils.browserLoaded( gBrowser.selectedBrowser, false, "https://example.org/" ); - EventUtils.synthesizeMouseAtCenter(target, { type: "mouseup" }); + EventUtils.synthesizeMouseAtCenter(target, {}); await onLoaded; Assert.ok(true, "Expected page is opened"); diff --git a/browser/components/urlbar/tests/browser/head.js b/browser/components/urlbar/tests/browser/head.js index a81e8e4811..f78624e68e 100644 --- a/browser/components/urlbar/tests/browser/head.js +++ b/browser/components/urlbar/tests/browser/head.js @@ -67,7 +67,7 @@ function waitForLoadStartOrTimeout(win = window, timeoutMs = 1000) { return Promise.race([ new Promise(resolve => { listener = { - onStateChange(browser, webprogress, request, flags, status) { + onStateChange(browser, webprogress, request, flags) { if (flags & Ci.nsIWebProgressListener.STATE_START) { resolve(request.QueryInterface(Ci.nsIChannel).URI); } diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser.toml b/browser/components/urlbar/tests/engagementTelemetry/browser/browser.toml index 68a7881399..cf6bc80318 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser.toml +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser.toml @@ -26,6 +26,8 @@ prefs = ["browser.bookmarks.testing.skipDefaultBookmarksImport=true"] ["browser_glean_telemetry_abandonment_n_chars_n_words.js"] +["browser_glean_telemetry_abandonment_type.js"] + ["browser_glean_telemetry_abandonment_sap.js"] ["browser_glean_telemetry_abandonment_search_engine_default_id.js"] @@ -64,24 +66,4 @@ skip-if = ["verify"] # Bug 1852375 - MerinoTestUtils.initWeather() doesn't play ["browser_glean_telemetry_exposure_edge_cases.js"] -["browser_glean_telemetry_impression_groups.js"] - -["browser_glean_telemetry_impression_interaction.js"] - -["browser_glean_telemetry_impression_interaction_persisted_search_terms_disabled.js"] - -["browser_glean_telemetry_impression_interaction_persisted_search_terms_enabled.js"] - -["browser_glean_telemetry_impression_n_chars_n_words.js"] - -["browser_glean_telemetry_impression_preferences.js"] - -["browser_glean_telemetry_impression_sap.js"] - -["browser_glean_telemetry_impression_search_engine_default_id.js"] - -["browser_glean_telemetry_impression_search_mode.js"] - -["browser_glean_telemetry_impression_timing.js"] - ["browser_glean_telemetry_record_preferences.js"] diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_tips.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_tips.js index 71087d03d0..ca21ca476c 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_tips.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_tips.js @@ -38,7 +38,7 @@ add_setup(async function () { }); add_task(async function tip_persist() { - await doTest(async browser => { + await doTest(async () => { await showPersistSearchTip("test"); gURLBar.focus(); await UrlbarTestUtils.promisePopupClose(window, () => { diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_type.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_type.js new file mode 100644 index 0000000000..99145d7cc3 --- /dev/null +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_type.js @@ -0,0 +1,109 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test for the following data of abandonment telemetry. +// - reason + +function checkUrlbarFocus(win, focusState) { + let urlbar = win.gURLBar; + is( + focusState ? win.document.activeElement : !win.document.activeElement, + focusState ? urlbar.inputField : !urlbar.inputField, + `URL Bar should ${focusState ? "" : "not "}be focused` + ); +} + +// Tests that a tab switch from a focused URL bar to another tab with a focused +// URL bar records the correct abandonment telemetry with abandonment type +// "tab_swtich". +add_task(async function tabSwitchFocusedToFocused() { + await doTest(async browser => { + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test search", + }); + checkUrlbarFocus(window, true); + + let promiseTabOpened = BrowserTestUtils.waitForEvent( + gBrowser.tabContainer, + "TabOpen" + ); + EventUtils.synthesizeMouseAtCenter(gBrowser.tabContainer.newTabButton, {}); + let openEvent = await promiseTabOpened; + let tab2 = openEvent.target; + checkUrlbarFocus(window, true); + + await assertAbandonmentTelemetry([{ abandonment_type: "tab_switch" }]); + + await BrowserTestUtils.removeTab(tab2); + }); +}); + +// Verifies that switching from a tab with a focused URL bar to a tab where the +// URL bar loses focus logs abandonment telemetry with abandonment type +// "blur". +add_task(async function tabSwitchFocusedToUnfocused() { + await doTest(async browser => { + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test search", + }); + checkUrlbarFocus(window, true); + + let tab2 = await BrowserTestUtils.openNewForegroundTab(window.gBrowser); + checkUrlbarFocus(window, false); + + await assertAbandonmentTelemetry([{ abandonment_type: "blur" }]); + + await BrowserTestUtils.removeTab(tab2); + }); +}); + +// Ensures that switching from a tab with an unfocused URL bar to a tab where +// the URL bar gains focus does not record any abandonment telemetry, reflecting +// no change in focus state relevant to abandonment. +add_task(async function tabSwitchUnFocusedToFocused() { + await doTest(async browser => { + checkUrlbarFocus(window, false); + + let promiseTabOpened = BrowserTestUtils.waitForEvent( + gBrowser.tabContainer, + "TabOpen" + ); + EventUtils.synthesizeMouseAtCenter(gBrowser.tabContainer.newTabButton, {}); + let openEvent = await promiseTabOpened; + let tab2 = openEvent.target; + checkUrlbarFocus(window, true); + + const telemetries = Glean.urlbar.abandonment.testGetValue() ?? []; + Assert.equal( + telemetries.length, + 0, + "Telemetry event length matches expected event length." + ); + + await BrowserTestUtils.removeTab(tab2); + }); +}); + +// Checks that switching between two tabs, both with unfocused URL bars, does +// not trigger any abandonment telmetry. +add_task(async function tabSwitchUnFocusedToUnFocused() { + await doTest(async browser => { + checkUrlbarFocus(window, false); + + let tab2 = await BrowserTestUtils.openNewForegroundTab(window.gBrowser); + checkUrlbarFocus(window, false); + + const telemetries = Glean.urlbar.abandonment.testGetValue() ?? []; + Assert.equal( + telemetries.length, + 0, + "Telemetry event length matches expected event length." + ); + + await BrowserTestUtils.removeTab(tab2); + }); +}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_edge_cases.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_edge_cases.js index fcac924879..04ef7e9757 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_edge_cases.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_edge_cases.js @@ -22,7 +22,7 @@ class NoResponseTestProvider extends UrlbarTestUtils.TestProvider { return UrlbarUtils.PROVIDER_TYPE.HEURISTIC; } - async startQuery(context, addCallback) { + async startQuery(_context, _addCallback) { await this.#deferred.promise; } @@ -98,7 +98,7 @@ add_task(async function engagement_before_showing_results() { }; registerCleanupFunction(cleanup); - await doTest(async browser => { + await doTest(async () => { // Try to show the results. await UrlbarTestUtils.inputIntoURLBar(window, "exam"); @@ -156,7 +156,7 @@ add_task(async function engagement_after_closing_results() { ]; for (const trigger of TRIGGERS) { - await doTest(async browser => { + await doTest(async () => { await openPopup("test"); await UrlbarTestUtils.promisePopupClose(window, () => { trigger(); @@ -186,7 +186,7 @@ add_task(async function engagement_after_closing_results() { }); add_task(async function enter_to_reload_current_url() { - await doTest(async browser => { + await doTest(async () => { // Open a URL once. await openPopup("https://example.com"); await doEnter(); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_groups.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_groups.js index 8779487960..d46c874403 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_groups.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_groups.js @@ -247,13 +247,13 @@ add_task(async function always_empty_if_drop_go() { }, ]; - await doTest(async browser => { + await doTest(async () => { await doDropAndGo("example.com"); assertEngagementTelemetry(expected); }); - await doTest(async browser => { + await doTest(async () => { // Open the results view once. await showResultByArrowDown(); await UrlbarTestUtils.promisePopupClose(window); @@ -274,13 +274,13 @@ add_task(async function always_empty_if_paste_go() { }, ]; - await doTest(async browser => { + await doTest(async () => { await doPasteAndGo("example.com"); assertEngagementTelemetry(expected); }); - await doTest(async browser => { + await doTest(async () => { // Open the results view once. await showResultByArrowDown(); await UrlbarTestUtils.promisePopupClose(window); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_interaction.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_interaction.js index f4880d2205..2866186c30 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_interaction.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_interaction.js @@ -35,13 +35,13 @@ add_task(async function typed() { }); add_task(async function dropped() { - await doTest(async browser => { + await doTest(async () => { await doDropAndGo("example.com"); assertEngagementTelemetry([{ interaction: "dropped" }]); }); - await doTest(async browser => { + await doTest(async () => { await showResultByArrowDown(); await doDropAndGo("example.com"); @@ -60,13 +60,13 @@ add_task(async function pasted() { assert: () => assertEngagementTelemetry([{ interaction: "pasted" }]), }); - await doTest(async browser => { + await doTest(async () => { await doPasteAndGo("www.example.com"); assertEngagementTelemetry([{ interaction: "pasted" }]); }); - await doTest(async browser => { + await doTest(async () => { await showResultByArrowDown(); await doPasteAndGo("www.example.com"); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_selected_result.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_selected_result.js index 6a3422d939..bea266dbf4 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_selected_result.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_selected_result.js @@ -13,6 +13,7 @@ ChromeUtils.defineESModuleGetters(this, { UrlbarProviderClipboard: "resource:///modules/UrlbarProviderClipboard.sys.mjs", + SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs", }); // This test has many subtests and can time out in verify mode. @@ -23,7 +24,7 @@ add_setup(async function () { }); add_task(async function selected_result_autofill_about() { - await doTest(async browser => { + await doTest(async () => { await openPopup("about:about"); await doEnter(); @@ -44,7 +45,7 @@ add_task(async function selected_result_autofill_adaptive() { set: [["browser.urlbar.autoFill.adaptiveHistory.enabled", true]], }); - await doTest(async browser => { + await doTest(async () => { await PlacesTestUtils.addVisits("https://example.com/test"); await UrlbarUtils.addToInputHistory("https://example.com/test", "exa"); await openPopup("exa"); @@ -65,7 +66,7 @@ add_task(async function selected_result_autofill_adaptive() { }); add_task(async function selected_result_autofill_origin() { - await doTest(async browser => { + await doTest(async () => { await PlacesTestUtils.addVisits("https://example.com/test"); await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); await openPopup("exa"); @@ -84,7 +85,7 @@ add_task(async function selected_result_autofill_origin() { }); add_task(async function selected_result_autofill_url() { - await doTest(async browser => { + await doTest(async () => { await PlacesTestUtils.addVisits("https://example.com/test"); await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); await openPopup("https://example.com/test"); @@ -103,7 +104,7 @@ add_task(async function selected_result_autofill_url() { }); add_task(async function selected_result_bookmark() { - await doTest(async browser => { + await doTest(async () => { await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: "https://example.com/bookmark", @@ -131,7 +132,7 @@ add_task(async function selected_result_history() { set: [["browser.urlbar.autoFill", false]], }); - await doTest(async browser => { + await doTest(async () => { await PlacesTestUtils.addVisits("https://example.com/test"); await openPopup("example"); @@ -153,7 +154,7 @@ add_task(async function selected_result_history() { }); add_task(async function selected_result_keyword() { - await doTest(async browser => { + await doTest(async () => { await PlacesUtils.keywords.insert({ keyword: "keyword", url: "https://example.com/?q=%s", @@ -177,7 +178,7 @@ add_task(async function selected_result_keyword() { }); add_task(async function selected_result_search_engine() { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await doEnter(); @@ -201,7 +202,7 @@ add_task(async function selected_result_search_suggest() { ], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("foo"); await selectRowByURL("http://mochi.test:8888/?terms=foofoo"); await doEnter(); @@ -228,7 +229,7 @@ add_task(async function selected_result_search_history() { ], }); - await doTest(async browser => { + await doTest(async () => { await UrlbarTestUtils.formHistory.add(["foofoo", "foobar"]); await openPopup("foo"); @@ -250,7 +251,7 @@ add_task(async function selected_result_search_history() { }); add_task(async function selected_result_url() { - await doTest(async browser => { + await doTest(async () => { await openPopup("https://example.com/"); await doEnter(); @@ -267,7 +268,7 @@ add_task(async function selected_result_url() { }); add_task(async function selected_result_action() { - await doTest(async browser => { + await doTest(async () => { await showResultByArrowDown(); await selectRowByProvider("quickactions"); const onLoad = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); @@ -289,7 +290,7 @@ add_task(async function selected_result_action() { add_task(async function selected_result_tab() { const tab = BrowserTestUtils.addTab(gBrowser, "https://example.com/"); - await doTest(async browser => { + await doTest(async () => { await openPopup("example"); await selectRowByProvider("Places"); EventUtils.synthesizeKey("KEY_Enter"); @@ -312,7 +313,7 @@ add_task(async function selected_result_tab() { add_task(async function selected_result_remote_tab() { const remoteTab = await loadRemoteTab("https://example.com"); - await doTest(async browser => { + await doTest(async () => { await openPopup("example"); await selectRowByProvider("RemoteTabs"); await doEnter(); @@ -335,7 +336,7 @@ add_task(async function selected_result_addon() { const addon = loadOmniboxAddon({ keyword: "omni" }); await addon.startup(); - await doTest(async browser => { + await doTest(async () => { await openPopup("omni test"); await doEnter(); @@ -363,7 +364,7 @@ add_task(async function selected_result_tab_to_search() { search_url: "https://mozengine/", }); - await doTest(async browser => { + await doTest(async () => { for (let i = 0; i < 3; i++) { await PlacesTestUtils.addVisits(["https://mozengine/"]); } @@ -389,7 +390,7 @@ add_task(async function selected_result_tab_to_search() { }); add_task(async function selected_result_top_site() { - await doTest(async browser => { + await doTest(async () => { await addTopSites("https://example.com/"); await showResultByArrowDown(); await selectRowByURL("https://example.com/"); @@ -412,7 +413,7 @@ add_task(async function selected_result_calc() { set: [["browser.urlbar.suggest.calculator", true]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("8*8"); await selectRowByProvider("calculator"); await SimpleTest.promiseClipboardChange("64", () => { @@ -444,7 +445,7 @@ add_task(async function selected_result_clipboard() { "https://example.com/selected_result_clipboard" ); - await doTest(async browser => { + await doTest(async () => { await openPopup(""); await selectRowByProvider("UrlbarProviderClipboard"); await doEnter(); @@ -470,7 +471,7 @@ add_task(async function selected_result_unit() { set: [["browser.urlbar.unitConversion.enabled", true]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("1m to cm"); await selectRowByProvider("UnitConversion"); await SimpleTest.promiseClipboardChange("100 cm", () => { @@ -496,7 +497,7 @@ add_task(async function selected_result_site_specific_contextual_search() { set: [["browser.urlbar.contextualSearch.enabled", true]], }); - await doTest(async browser => { + await doTest(async () => { const extension = await SearchTestUtils.installSearchExtension( { name: "Contextual", @@ -540,7 +541,7 @@ add_task(async function selected_result_rs_adm_sponsored() { prefs: [["quicksuggest.rustEnabled", false]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("sponsored"); await selectRowByURL("https://example.com/sponsored"); await doEnter(); @@ -564,7 +565,7 @@ add_task(async function selected_result_rs_adm_nonsponsored() { prefs: [["quicksuggest.rustEnabled", false]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("nonsponsored"); await selectRowByURL("https://example.com/nonsponsored"); await doEnter(); @@ -594,13 +595,13 @@ add_task(async function selected_result_input_field() { }, ]; - await doTest(async browser => { + await doTest(async () => { await doDropAndGo("example.com"); assertEngagementTelemetry(expected); }); - await doTest(async browser => { + await doTest(async () => { await doPasteAndGo("example.com"); assertEngagementTelemetry(expected); @@ -618,7 +619,7 @@ add_task(async function selected_result_weather() { let provider = UrlbarPrefs.get("quickSuggestRustEnabled") ? "UrlbarProviderQuickSuggest" : "Weather"; - await doTest(async browser => { + await doTest(async () => { await openPopup(MerinoTestUtils.WEATHER_KEYWORD); await selectRowByProvider(provider); await doEnter(); @@ -653,7 +654,7 @@ add_task(async function selected_result_navigational() { ], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("only match the Merino suggestion"); await selectRowByProvider("UrlbarProviderQuickSuggest"); await doEnter(); @@ -688,7 +689,7 @@ add_task(async function selected_result_dynamic_wikipedia() { ], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("only match the Merino suggestion"); await selectRowByProvider("UrlbarProviderQuickSuggest"); await doEnter(); @@ -708,7 +709,7 @@ add_task(async function selected_result_dynamic_wikipedia() { }); add_task(async function selected_result_search_shortcut_button() { - await doTest(async browser => { + await doTest(async () => { const oneOffSearchButtons = UrlbarTestUtils.getOneOffSearchButtons(window); await openPopup("x"); Assert.ok(!oneOffSearchButtons.selectedButton); @@ -756,31 +757,78 @@ add_task(async function selected_result_trending() { }); let defaultEngine = await Services.search.getDefault(); - let extension = await SearchTestUtils.installSearchExtension( - { - name: "mozengine", - search_url: "https://example.org/", - }, - { setAsDefault: true, skipUnload: true } - ); + let extension; + if (!SearchUtils.newSearchConfigEnabled) { + extension = await SearchTestUtils.installSearchExtension( + { + name: "mozengine", + search_url: "https://example.org/", + }, + { setAsDefault: true, skipUnload: true } + ); + } SearchTestUtils.useMockIdleService(); - await SearchTestUtils.updateRemoteSettingsConfig([ - { - webExtension: { id: "mozengine@tests.mozilla.org" }, - urls: { - trending: { - fullPath: - "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs", - query: "", - }, - }, - appliesTo: [{ included: { everywhere: true } }], - default: "yes", - }, - ]); + await SearchTestUtils.updateRemoteSettingsConfig( + SearchUtils.newSearchConfigEnabled + ? [ + { + recordType: "engine", + identifier: "mozengine", + base: { + name: "mozengine", + urls: { + search: { + base: "https://example.org/", + searchTermParamName: "q", + }, + trending: { + base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs", + method: "GET", + }, + }, + }, + variants: [ + { + environment: { allRegionsAndLocales: true }, + }, + ], + }, + { + recordType: "defaultEngines", + globalDefault: "mozengine", + specificDefaults: [], + }, + { + recordType: "engineOrders", + orders: [], + }, + ] + : [ + { + webExtension: { id: "mozengine@tests.mozilla.org" }, + urls: { + trending: { + fullPath: + "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs", + query: "", + }, + }, + appliesTo: [{ included: { everywhere: true } }], + default: "yes", + }, + ] + ); - await doTest(async browser => { + if (SearchUtils.newSearchConfigEnabled) { + let engine = Services.search.getEngineByName("mozengine"); + await Services.search.setDefault( + engine, + Ci.nsISearchService.CHANGE_REASON_UNKNOWN + ); + } + + await doTest(async () => { await openPopup(""); await selectRowByProvider("SearchSuggestions"); await doEnter(); @@ -796,7 +844,13 @@ add_task(async function selected_result_trending() { ]); }); - await extension.unload(); + if (SearchUtils.newSearchConfigEnabled) { + let engine = Services.search.getEngineByName("mozengine"); + await Services.search.removeEngine(engine); + } else { + await extension.unload(); + } + await Services.search.setDefault( defaultEngine, Ci.nsISearchService.CHANGE_REASON_UNKNOWN @@ -823,31 +877,84 @@ add_task(async function selected_result_trending_rich() { }); let defaultEngine = await Services.search.getDefault(); - let extension = await SearchTestUtils.installSearchExtension( - { - name: "mozengine", - search_url: "https://example.org/", - }, - { setAsDefault: true, skipUnload: true } - ); + let extension; + if (!SearchUtils.newSearchConfigEnabled) { + extension = await SearchTestUtils.installSearchExtension( + { + name: "mozengine", + search_url: "https://example.org/", + }, + { setAsDefault: true, skipUnload: true } + ); + } SearchTestUtils.useMockIdleService(); - await SearchTestUtils.updateRemoteSettingsConfig([ - { - webExtension: { id: "mozengine@tests.mozilla.org" }, - urls: { - trending: { - fullPath: - "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs?richsuggestions=true", - query: "", - }, - }, - appliesTo: [{ included: { everywhere: true } }], - default: "yes", - }, - ]); + await SearchTestUtils.updateRemoteSettingsConfig( + SearchUtils.newSearchConfigEnabled + ? [ + { + recordType: "engine", + identifier: "mozengine", + base: { + name: "mozengine", + urls: { + search: { + base: "https://example.org/", + searchTermParamName: "q", + }, + trending: { + base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs", + method: "GET", + params: [ + { + name: "richsuggestions", + value: "true", + }, + ], + }, + }, + }, + variants: [ + { + environment: { allRegionsAndLocales: true }, + }, + ], + }, + { + recordType: "defaultEngines", + globalDefault: "mozengine", + specificDefaults: [], + }, + { + recordType: "engineOrders", + orders: [], + }, + ] + : [ + { + webExtension: { id: "mozengine@tests.mozilla.org" }, + urls: { + trending: { + fullPath: + "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs?richsuggestions=true", + query: "", + }, + }, + appliesTo: [{ included: { everywhere: true } }], + default: "yes", + }, + ] + ); - await doTest(async browser => { + if (SearchUtils.newSearchConfigEnabled) { + let engine = Services.search.getEngineByName("mozengine"); + await Services.search.setDefault( + engine, + Ci.nsISearchService.CHANGE_REASON_UNKNOWN + ); + } + + await doTest(async () => { await openPopup(""); await selectRowByProvider("SearchSuggestions"); await doEnter(); @@ -863,7 +970,13 @@ add_task(async function selected_result_trending_rich() { ]); }); - await extension.unload(); + if (SearchUtils.newSearchConfigEnabled) { + let engine = Services.search.getEngineByName("mozengine"); + await Services.search.removeEngine(engine); + } else { + await extension.unload(); + } + await Services.search.setDefault( defaultEngine, Ci.nsISearchService.CHANGE_REASON_UNKNOWN @@ -905,7 +1018,7 @@ add_task(async function selected_result_addons() { ], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("only match the Merino suggestion"); await selectRowByProvider("UrlbarProviderQuickSuggest"); await doEnter(); @@ -930,7 +1043,7 @@ add_task(async function selected_result_rust_adm_sponsored() { prefs: [["quicksuggest.rustEnabled", true]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("sponsored"); await selectRowByURL("https://example.com/sponsored"); await doEnter(); @@ -954,7 +1067,7 @@ add_task(async function selected_result_rust_adm_nonsponsored() { prefs: [["quicksuggest.rustEnabled", true]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("nonsponsored"); await selectRowByURL("https://example.com/nonsponsored"); await doEnter(); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_tips.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_tips.js index 2b38631747..ff31bdc52a 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_tips.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_tips.js @@ -69,7 +69,7 @@ add_task(async function selected_result_tip() { }); UrlbarProvidersManager.registerProvider(provider); - await doTest(async browser => { + await doTest(async () => { await openPopup("example"); await selectRowByType(type); EventUtils.synthesizeKey("VK_RETURN"); @@ -159,7 +159,7 @@ add_task(async function selected_result_intervention_update() { }); async function doInterventionTest(keyword, type, dialog, expectedTelemetry) { - await doTest(async browser => { + await doTest(async () => { await openPopup(keyword); await selectRowByType(type); const onDialog = BrowserTestUtils.promiseAlertDialog("cancel", dialog, { diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_type.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_type.js index 5972dd331d..6b1dedbce2 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_type.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_type.js @@ -14,7 +14,7 @@ add_setup(async function () { }); add_task(async function engagement_type_click() { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await doClick(); @@ -23,7 +23,7 @@ add_task(async function engagement_type_click() { }); add_task(async function engagement_type_enter() { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await doEnter(); @@ -32,7 +32,7 @@ add_task(async function engagement_type_enter() { }); add_task(async function engagement_type_go_button() { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); EventUtils.synthesizeMouseAtCenter(gURLBar.goButton, {}); @@ -41,7 +41,7 @@ add_task(async function engagement_type_go_button() { }); add_task(async function engagement_type_drop_go() { - await doTest(async browser => { + await doTest(async () => { await doDropAndGo("example.com"); assertEngagementTelemetry([{ engagement_type: "drop_go" }]); @@ -49,7 +49,7 @@ add_task(async function engagement_type_drop_go() { }); add_task(async function engagement_type_paste_go() { - await doTest(async browser => { + await doTest(async () => { await doPasteAndGo("www.example.com"); assertEngagementTelemetry([{ engagement_type: "paste_go" }]); @@ -59,7 +59,7 @@ add_task(async function engagement_type_paste_go() { add_task(async function engagement_type_dismiss() { const cleanupQuickSuggest = await ensureQuickSuggestInit(); - await doTest(async browser => { + await doTest(async () => { await openPopup("sponsored"); const originalResultCount = UrlbarTestUtils.getResultCount(window); @@ -84,7 +84,7 @@ add_task(async function engagement_type_dismiss() { ]); }); - await doTest(async browser => { + await doTest(async () => { await openPopup("sponsored"); const originalResultCount = UrlbarTestUtils.getResultCount(window); @@ -103,7 +103,7 @@ add_task(async function engagement_type_dismiss() { add_task(async function engagement_type_help() { const cleanupQuickSuggest = await ensureQuickSuggestInit(); - await doTest(async browser => { + await doTest(async () => { await openPopup("sponsored"); await selectRowByURL("https://example.com/sponsored"); const onTabOpened = BrowserTestUtils.waitForNewTab(gBrowser); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_exposure_edge_cases.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_exposure_edge_cases.js index d28352b417..725240c9b1 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_exposure_edge_cases.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_exposure_edge_cases.js @@ -38,8 +38,12 @@ add_setup(async function () { gProvider = new TestProvider(); UrlbarProvidersManager.registerProvider(gProvider); - // Increase the timeout of the stale-rows timer so it doesn't interfere with - // this test, which specifically tests what happens before the timer fires. + // This test specifically checks the view's behavior before and after it + // removes stale rows, so it needs to control when that occurs. There are two + // times the view removes stale rows: (1) when the stale-rows timer fires, (2) + // when a query finishes. We prevent (1) from occuring by increasing the + // timer's timeout so it never fires during the test. We'll rely on (2) to + // trigger stale rows removal. let originalRemoveStaleRowsTimeout = UrlbarView.removeStaleRowsTimeout; UrlbarView.removeStaleRowsTimeout = 30000; @@ -49,11 +53,17 @@ add_setup(async function () { }); }); -// Does one query that fills up the view with search suggestions, starts a -// second query that returns a history result, and cancels it before it can -// finish but after the view is updated. Regardless of `showExposureResults`, -// the history result should not trigger an exposure since it never had a chance -// to be visible in the view. +// Does the following: +// +// 1. Starts and finishes a query that fills up the view +// 2. Starts a second query with results that cannot replace rows from the first +// query and that therefore must be appended and hidden +// 3. Cancels the second query before it finishes (so that stale rows are not +// removed) +// +// Results in the second query should not trigger an exposure. They can never be +// visible in the view since the second query is canceled before stale rows are +// removed. add_task(async function noExposure() { for (let showExposureResults of [true, false]) { await do_noExposure(showExposureResults); @@ -116,7 +126,7 @@ async function do_noExposure(showExposureResults) { // When the provider's `startQuery()` is called, let it add its results but // don't let it return. That will cause the view to be updated with the new // results but prevent it from showing hidden rows since the query won't - // finish. + // finish (so stale rows won't be removed). let queryResolver = Promise.withResolvers(); gProvider.finishQueryPromise = queryResolver.promise; @@ -147,14 +157,24 @@ async function do_noExposure(showExposureResults) { // Make sure the view is full of visible rows as expected, plus the one or two // hidden rows for the history and/or bookmark results. - let rows = UrlbarTestUtils.getResultsContainer(window); - let expectedCount = MAX_RESULT_COUNT + 1; + let expected = [ + { + source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS, + type: UrlbarUtils.RESULT_TYPE.URL, + url: bookmarkUrl, + }, + ]; if (showExposureResults) { - expectedCount++; + expected.unshift({ + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + type: UrlbarUtils.RESULT_TYPE.URL, + url: historyUrl, + }); } + let rows = UrlbarTestUtils.getResultsContainer(window); Assert.equal( rows.children.length, - expectedCount, + MAX_RESULT_COUNT + expected.length, "The view has the expected number of rows" ); @@ -176,24 +196,15 @@ async function do_noExposure(showExposureResults) { } // Check the hidden history and/or bookmark rows. - let expected = [ - { source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS, url: bookmarkUrl }, - ]; - if (showExposureResults) { - expected.unshift({ - source: UrlbarUtils.RESULT_SOURCE.HISTORY, - url: historyUrl, - }); - } for (let i = 0; i < expected.length; i++) { - let { source, url } = expected[i]; + let { source, type, url } = expected[i]; let row = rows.children[MAX_RESULT_COUNT + i]; Assert.ok(row, `rows[${i}] should exist`); Assert.ok(BrowserTestUtils.isHidden(row), `rows[${i}] should be hidden`); Assert.equal( row.result.type, - UrlbarUtils.RESULT_TYPE.URL, - `rows[${i}].result.type should be URL` + type, + `rows[${i}].result.type should be as expected` ); Assert.equal( row.result.source, @@ -212,8 +223,8 @@ async function do_noExposure(showExposureResults) { await UrlbarTestUtils.promisePopupClose(window); gURLBar.blur(); - // No exposure should have been recorded since the history result was never - // visible. + // No exposure should have been recorded since the history result could never + // be visible. assertExposureTelemetry([]); // Clean up. @@ -221,17 +232,24 @@ async function do_noExposure(showExposureResults) { await queryPromise; await SpecialPowers.popPrefEnv(); Services.fog.testResetFOG(); + gProvider.finishQueryPromise = null; } -// Does one query that underfills the view and then a second query that returns -// a search suggestion. The search suggestion should be appended and trigger an -// exposure. When `showExposureResults` is true, it should also be shown. After -// the view is updated, it shouldn't matter whether or not the second query is -// canceled. -add_task(async function exposure_append() { +// Does the following: +// +// 1. Starts and finishes a query that underfills the view +// 2. Starts a second query +// 3. Waits for rows from the second query to be appended. They will be +// immediately visible since the first query underfilled the view. +// 4. Either cancels the second query (so stale rows are not removed) or waits +// for it to finish (so stale rows are removed) +// +// Results in the second query should trigger an exposure since they are made +// visible in step 3. Step 4 should not actually matter. +add_task(async function exposure_append_underfilled() { for (let showExposureResults of [true, false]) { for (let cancelSecondQuery of [true, false]) { - await do_exposure_append({ + await do_exposure_append_underfilled({ showExposureResults, cancelSecondQuery, }); @@ -239,7 +257,10 @@ add_task(async function exposure_append() { } }); -async function do_exposure_append({ showExposureResults, cancelSecondQuery }) { +async function do_exposure_append_underfilled({ + showExposureResults, + cancelSecondQuery, +}) { info( "Starting do_exposure_append: " + JSON.stringify({ showExposureResults, cancelSecondQuery }) @@ -287,7 +308,8 @@ async function do_exposure_append({ showExposureResults, cancelSecondQuery }) { // When the provider's `startQuery()` is called, let it add its results but // don't let it return. That will cause the view to be updated with the new - // results but let us test the specific case where the query doesn't finish. + // results but let us test the specific case where the query doesn't finish + // (so stale rows are not removed). let queryResolver = Promise.withResolvers(); gProvider.finishQueryPromise = queryResolver.promise; @@ -357,13 +379,19 @@ async function do_exposure_append({ showExposureResults, cancelSecondQuery }) { await queryPromise; await SpecialPowers.popPrefEnv(); Services.fog.testResetFOG(); + gProvider.finishQueryPromise = null; } -// Does one query that returns a search suggestion and then a second query that -// returns a new search suggestion. The new search suggestion can replace the -// old one, so it should trigger an exposure. When `showExposureResults` is -// true, it should actually replace it. After the view is updated, it shouldn't -// matter whether or not the second query is canceled. +// Does the following: +// +// 1. Starts and finishes a query +// 2. Starts a second query with a result that can replace an existing row from +// the previous query +// 3. Either cancels the second query (so stale rows are not removed) or waits +// for it to finish (so stale rows are removed) +// +// The result in the second query should trigger an exposure since it's made +// visible in step 2. Step 3 should not actually matter. add_task(async function exposure_replace() { for (let showExposureResults of [true, false]) { for (let cancelSecondQuery of [true, false]) { @@ -433,7 +461,8 @@ async function do_exposure_replace({ showExposureResults, cancelSecondQuery }) { // When the provider's `startQuery()` is called, let it add its results but // don't let it return. That will cause the view to be updated with the new - // results but let us test the specific case where the query doesn't finish. + // results but let us test the specific case where the query doesn't finish + // (so stale rows are not removed). let queryResolver = Promise.withResolvers(); gProvider.finishQueryPromise = queryResolver.promise; @@ -503,6 +532,519 @@ async function do_exposure_replace({ showExposureResults, cancelSecondQuery }) { await queryPromise; await SpecialPowers.popPrefEnv(); Services.fog.testResetFOG(); + gProvider.finishQueryPromise = null; +} + +// Does the following: +// +// 1. Starts and finishes a query that fills up the view +// 2. Starts a second query with a result that cannot replace any rows from the +// first query and that therefore must be appended and hidden +// 3. Finishes the second query +// +// The result in the second query should trigger an exposure since it's made +// visible in step 3. +add_task(async function exposure_append_full() { + for (let showExposureResults of [true, false]) { + await do_exposure_append_full(showExposureResults); + } +}); + +async function do_exposure_append_full(showExposureResults) { + info( + "Starting do_exposure_append_full: " + + JSON.stringify({ showExposureResults }) + ); + + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.exposureResults", "history"], + ["browser.urlbar.showExposureResults", showExposureResults], + ], + }); + + // Make the provider return enough search suggestions to fill the view. + gProvider.results = []; + for (let i = 0; i < MAX_RESULT_COUNT; i++) { + gProvider.results.push( + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.SEARCH, + UrlbarUtils.RESULT_SOURCE.SEARCH, + { + suggestion: "suggestion " + i, + engine: Services.search.defaultEngine.name, + } + ) + ); + } + + // Do the first query to fill the view with search suggestions. + info("Doing first query"); + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test 1", + }); + + // Now make the provider return a history result and bookmark. If + // `showExposureResults` is true, the history result will be added to the view + // but it should be hidden since the view is already full. If it's false, it + // shouldn't be added at all. The bookmark will always be added, which will + // tell us when the view has been updated either way. (It also will be hidden + // since the view is already full.) + let historyUrl = "https://example.com/history"; + let bookmarkUrl = "https://example.com/bookmark"; + gProvider.results = [ + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.URL, + UrlbarUtils.RESULT_SOURCE.HISTORY, + { url: historyUrl } + ), + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.URL, + UrlbarUtils.RESULT_SOURCE.BOOKMARKS, + { url: bookmarkUrl } + ), + ]; + + // When the provider's `startQuery()` is called, let it add its results but + // don't let it return. That will cause the view to be updated with the new + // results but prevent it from showing hidden rows since the query won't + // finish (so stale rows won't be removed). + let queryResolver = Promise.withResolvers(); + gProvider.finishQueryPromise = queryResolver.promise; + + // Observe when the view appends the bookmark row. This will tell us when the + // view has been updated with the provider's new results. The bookmark row + // will be hidden since the view is already full with search suggestions. + let lastRowPromise = promiseLastRowAppended( + row => row.result.payload.url == bookmarkUrl + ); + + // Now start the second query but don't await it. + info("Starting second query"); + let queryPromise = UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test 2", + reopenOnBlur: false, + }); + + // Wait for the view to be updated. + info("Waiting for last row"); + let lastRow = await lastRowPromise; + info("Done waiting for last row"); + + Assert.ok( + BrowserTestUtils.isHidden(lastRow), + "The new bookmark row should be hidden since the view is full" + ); + + // Make sure the view is full of visible rows as expected, plus the one or two + // hidden rows for the history and bookmark results. + let expected = [ + { + source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS, + type: UrlbarUtils.RESULT_TYPE.URL, + url: bookmarkUrl, + }, + ]; + if (showExposureResults) { + expected.unshift({ + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + type: UrlbarUtils.RESULT_TYPE.URL, + url: historyUrl, + }); + } + let rows = UrlbarTestUtils.getResultsContainer(window); + Assert.equal( + rows.children.length, + MAX_RESULT_COUNT + expected.length, + "The view has the expected number of rows" + ); + + // Check the visible rows. + for (let i = 0; i < MAX_RESULT_COUNT; i++) { + let row = rows.children[i]; + Assert.ok(BrowserTestUtils.isVisible(row), `rows[${i}] should be visible`); + Assert.ok( + row.result.type == UrlbarUtils.RESULT_TYPE.SEARCH, + `rows[${i}].result.type should be SEARCH` + ); + // The heuristic won't have a suggestion so skip it. + if (i > 0) { + Assert.ok( + row.result.payload.suggestion, + `rows[${i}] should have a suggestion` + ); + } + } + + // Check the hidden history and bookmark rows. + for (let i = 0; i < expected.length; i++) { + let { source, type, url } = expected[i]; + let row = rows.children[MAX_RESULT_COUNT + i]; + Assert.ok(row, `rows[${i}] should exist`); + Assert.ok(BrowserTestUtils.isHidden(row), `rows[${i}] should be hidden`); + Assert.equal( + row.result.type, + type, + `rows[${i}].result.type should be as expected` + ); + Assert.equal( + row.result.source, + source, + `rows[${i}].result.source should be as expected` + ); + Assert.equal( + row.result.payload.url, + url, + `rows[${i}] URL should be as expected` + ); + } + + // Now let the query finish (so stale rows are removed). + queryResolver.resolve(); + info("Waiting for second query to finish"); + await queryPromise; + info("Second query finished"); + + rows = UrlbarTestUtils.getResultsContainer(window); + Assert.equal( + rows.children.length, + // + 1 for the heurustic. + 1 + expected.length, + "The view has the expected number of rows" + ); + + // Check the visible rows (except the heuristic). + for (let i = 0; i < expected.length; i++) { + let { source, type, url } = expected[i]; + let index = i + 1; + let row = rows.children[index]; + Assert.ok(row, `rows[${index}] should exist`); + Assert.ok( + BrowserTestUtils.isVisible(row), + `rows[${index}] should be visible` + ); + Assert.equal( + row.result.type, + type, + `rows[${index}].result.type should be as expected` + ); + Assert.equal( + row.result.source, + source, + `rows[${index}].result.source should be as expected` + ); + Assert.equal( + row.result.payload.url, + url, + `rows[${index}] URL should be as expected` + ); + } + + // Close the view. Blur the urlbar to end the session. + info("Closing view and blurring"); + await UrlbarTestUtils.promisePopupClose(window); + gURLBar.blur(); + + // An exposure for the history result should have been recorded. + assertExposureTelemetry([{ results: "history" }]); + + // Clean up. + await SpecialPowers.popPrefEnv(); + Services.fog.testResetFOG(); + gProvider.finishQueryPromise = null; +} + +// Does the following: +// +// 1. Starts and finishes a query that fills up the view +// 2. Starts a second query with results that cannot replace rows from the first +// query and that therefore must be appended and hidden +// 3. Before the second query finishes (i.e., before stale rows are removed), +// starts and finishes a third query (after which stale rows are removed) +// +// Results in the third query should trigger an exposure since they become +// visible when the query finishes (and stale rows are removed) in step 3. +// Results in the second query should not trigger an exposure since they could +// never be visible since the query is canceled before stale rows are removed. +add_task(async function exposure_append_full_twice() { + for (let showExposureResults of [true, false]) { + await do_exposure_append_full_twice(showExposureResults); + } +}); + +async function do_exposure_append_full_twice(showExposureResults) { + info( + "Starting do_exposure_append_full_twice: " + + JSON.stringify({ showExposureResults }) + ); + + // Exposure results are history and tab. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.exposureResults", "history,tab"], + ["browser.urlbar.showExposureResults", showExposureResults], + ], + }); + + // Make the provider return enough search suggestions to fill the view. + gProvider.results = []; + for (let i = 0; i < MAX_RESULT_COUNT; i++) { + gProvider.results.push( + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.SEARCH, + UrlbarUtils.RESULT_SOURCE.SEARCH, + { + suggestion: "suggestion " + i, + engine: Services.search.defaultEngine.name, + } + ) + ); + } + + // Do the first query to fill the view with search suggestions. + info("Doing first query"); + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test 1", + }); + + // Now make the provider return a history result, tab, and bookmark. If + // `showExposureResults` is true, the history and tab results will be added to + // the view but they should be hidden since the view is already full. If it's + // false, they shouldn't be added at all. The bookmark will always be added, + // which will tell us when the view has been updated either way. (It also will + // be hidden since the view is already full.) + let historyUrl = "https://example.com/history"; + let tabUrl = "https://example.com/tab"; + let bookmarkUrl = "https://example.com/bookmark"; + gProvider.results = [ + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.URL, + UrlbarUtils.RESULT_SOURCE.HISTORY, + { url: historyUrl } + ), + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.TAB_SWITCH, + UrlbarUtils.RESULT_SOURCE.TABS, + { url: tabUrl } + ), + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.URL, + UrlbarUtils.RESULT_SOURCE.BOOKMARKS, + { url: bookmarkUrl } + ), + ]; + + // When the provider's `startQuery()` is called, let it add its results but + // don't let it return. That will cause the view to be updated with the new + // results but prevent it from showing hidden rows since the query won't + // finish (so stale rows won't be removed). + let secondQueryResolver = Promise.withResolvers(); + gProvider.finishQueryPromise = secondQueryResolver.promise; + + // Observe when the view appends the bookmark row. This will tell us when the + // view has been updated with the provider's new results. The bookmark row + // will be hidden since the view is already full with search suggestions. + let lastRowPromise = promiseLastRowAppended( + row => row.result.payload.url == bookmarkUrl + ); + + // Now start the second query but don't await it. + info("Starting second query"); + let secondQueryPromise = UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test 2", + reopenOnBlur: false, + }); + + // Wait for the view to be updated. + info("Waiting for last row"); + let lastRow = await lastRowPromise; + info("Done waiting for last row"); + + Assert.ok( + BrowserTestUtils.isHidden(lastRow), + "The new bookmark row should be hidden since the view is full" + ); + + // Make sure the view is full of visible rows as expected, plus the one or + // three hidden rows for the history, tab, and bookmark results. + let expected = [ + { + source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS, + type: UrlbarUtils.RESULT_TYPE.URL, + url: bookmarkUrl, + }, + ]; + if (showExposureResults) { + expected.unshift( + { + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + type: UrlbarUtils.RESULT_TYPE.URL, + url: historyUrl, + }, + { + source: UrlbarUtils.RESULT_SOURCE.TABS, + type: UrlbarUtils.RESULT_TYPE.TAB_SWITCH, + url: tabUrl, + } + ); + } + let rows = UrlbarTestUtils.getResultsContainer(window); + Assert.equal( + rows.children.length, + MAX_RESULT_COUNT + expected.length, + "The view has the expected number of rows" + ); + + // Check the visible rows. + for (let i = 0; i < MAX_RESULT_COUNT; i++) { + let row = rows.children[i]; + Assert.ok(BrowserTestUtils.isVisible(row), `rows[${i}] should be visible`); + Assert.ok( + row.result.type == UrlbarUtils.RESULT_TYPE.SEARCH, + `rows[${i}].result.type should be SEARCH` + ); + // The heuristic won't have a suggestion so skip it. + if (i > 0) { + Assert.ok( + row.result.payload.suggestion, + `rows[${i}] should have a suggestion` + ); + } + } + + // Check the hidden history, tab, and bookmark rows. + for (let i = 0; i < expected.length; i++) { + let { source, type, url } = expected[i]; + let row = rows.children[MAX_RESULT_COUNT + i]; + Assert.ok(row, `rows[${i}] should exist`); + Assert.ok(BrowserTestUtils.isHidden(row), `rows[${i}] should be hidden`); + Assert.equal( + row.result.type, + type, + `rows[${i}].result.type should be as expected` + ); + Assert.equal( + row.result.source, + source, + `rows[${i}].result.source should be as expected` + ); + Assert.equal( + row.result.payload.url, + url, + `rows[${i}] URL should be as expected` + ); + } + + // Now make the provider return only a history result. + gProvider.results = [ + new UrlbarResult( + UrlbarUtils.RESULT_TYPE.URL, + UrlbarUtils.RESULT_SOURCE.HISTORY, + { url: historyUrl } + ), + ]; + + // Without waiting for the second query to finish (i.e., before stale rows are + // removed), do a third query and allow it to finish (so stale rows are + // removed). An exposure should be recorded for the history result since it's + // present in the third query. An exposure should not be recorded for the tab + // result because it could not have been visible since the second query did + // not finish. + + let thirdQueryStartedPromise = new Promise(resolve => { + let queryListener = { + onQueryStarted: () => { + gURLBar.controller.removeQueryListener(queryListener); + resolve(); + }, + }; + gURLBar.controller.addQueryListener(queryListener); + }); + + info("Starting third query"); + let thirdQueryPromise = UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "test 3", + reopenOnBlur: false, + }); + + // The test provider's `startQuery()` is still awaiting its + // `finishQueryPromise`, so we need to resolve it so the provider can respond + // to the third query. But before we do that, we need to make sure the third + // query has started and canceled the second query because otherwise the + // second query could finish and cause stale rows to be removed. + info("Waiting for third query to start"); + await thirdQueryStartedPromise; + info("Resolving provider's finishQueryPromise"); + secondQueryResolver.resolve(); + + // Now wait for the third query to finish. + info("Waiting for third query to finish"); + await thirdQueryPromise; + + expected = []; + if (showExposureResults) { + expected.unshift({ + source: UrlbarUtils.RESULT_SOURCE.HISTORY, + type: UrlbarUtils.RESULT_TYPE.URL, + url: historyUrl, + }); + } + + rows = UrlbarTestUtils.getResultsContainer(window); + Assert.equal( + rows.children.length, + // + 1 for the heurustic. + 1 + expected.length, + "The view has the expected number of rows" + ); + + // Check the history row. + for (let i = 0; i < expected.length; i++) { + let { source, type, url } = expected[i]; + let index = i + 1; + let row = rows.children[index]; + Assert.ok(row, `rows[${index}] should exist`); + Assert.ok( + BrowserTestUtils.isVisible(row), + `rows[${index}] should be visible` + ); + Assert.equal( + row.result.type, + type, + `rows[${index}].result.type should be as expected` + ); + Assert.equal( + row.result.source, + source, + `rows[${index}].result.source should be as expected` + ); + Assert.equal( + row.result.payload.url, + url, + `rows[${index}] URL should be as expected` + ); + } + + // Close the view. Blur the urlbar to end the session. + info("Closing view and blurring"); + await UrlbarTestUtils.promisePopupClose(window); + gURLBar.blur(); + + // An exposure only for the history result should have been recorded. If an + // exposure was also incorrectly recorded for the tab result, this will fail + // with "history,tab" instead of only "history". + assertExposureTelemetry([{ results: "history" }]); + + // Clean up. + await secondQueryPromise; + await SpecialPowers.popPrefEnv(); + Services.fog.testResetFOG(); + gProvider.finishQueryPromise = null; } /** @@ -523,7 +1065,7 @@ class TestProvider extends UrlbarTestUtils.TestProvider { function promiseLastRowAppended(predicate) { return new Promise(resolve => { let rows = UrlbarTestUtils.getResultsContainer(window); - let observer = new MutationObserver(mutations => { + let observer = new MutationObserver(() => { let lastRow = rows.children[rows.children.length - 1]; info( "Observed mutation, lastRow.result is: " + diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_groups.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_groups.js deleted file mode 100644 index 354876e512..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_groups.js +++ /dev/null @@ -1,258 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test for the following data of impression telemetry. -// - groups -// - results -// - n_results - -// This test has many subtests and can time out in verify mode. -requestLongerTimeout(5); - -add_setup(async function () { - await initGroupTest(); - // Increase the pausing time to ensure to ready for all suggestions. - await SpecialPowers.pushPrefEnv({ - set: [ - [ - "browser.urlbar.searchEngagementTelemetry.pauseImpressionIntervalMs", - 500, - ], - ], - }); -}); - -add_task(async function heuristics() { - await doHeuristicsTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { reason: "pause", groups: "heuristic", results: "search_engine" }, - ]), - }); -}); - -add_task(async function adaptive_history() { - await doAdaptiveHistoryTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,adaptive_history", - results: "search_engine,history", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function search_history() { - await doSearchHistoryTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,search_history,search_history", - results: "search_engine,search_history,search_history", - n_results: 3, - }, - ]), - }); -}); - -add_task(async function recent_search() { - await doRecentSearchTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "recent_search,suggested_index", - results: "recent_search,action", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function search_suggest() { - await doSearchSuggestTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,search_suggest,search_suggest", - results: "search_engine,search_suggest,search_suggest", - n_results: 3, - }, - ]), - }); - - await doTailSearchSuggestTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,search_suggest", - results: "search_engine,search_suggest", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function top_pick() { - await doTopPickTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,top_pick,search_suggest,search_suggest", - results: - "search_engine,merino_top_picks,search_suggest,search_suggest", - n_results: 4, - }, - ]), - }); -}); - -add_task(async function top_site() { - await doTopSiteTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "top_site,suggested_index", - results: "top_site,action", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function clipboard() { - await doClipboardTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "general,suggested_index", - results: "clipboard,action", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function remote_tab() { - await doRemoteTabTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,remote_tab", - results: "search_engine,remote_tab", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function addon() { - await doAddonTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "addon", - results: "addon", - n_results: 1, - }, - ]), - }); -}); - -add_task(async function general() { - await doGeneralBookmarkTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,suggested_index,general", - results: "search_engine,action,bookmark", - n_results: 3, - }, - ]), - }); - - await doGeneralHistoryTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,general", - results: "search_engine,history", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function suggest() { - await doSuggestTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - groups: "heuristic,suggest", - results: UrlbarPrefs.get("quickSuggestRustEnabled") - ? "search_engine,rust_adm_nonsponsored" - : "search_engine,rs_adm_nonsponsored", - n_results: 2, - }, - ]), - }); -}); - -add_task(async function about_page() { - await doAboutPageTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,about_page,about_page", - results: "search_engine,history,history", - n_results: 3, - }, - ]), - }); -}); - -add_task(async function suggested_index() { - await doSuggestedIndexTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { - reason: "pause", - groups: "heuristic,suggested_index", - results: "search_engine,unit", - n_results: 2, - }, - ]), - }); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction.js deleted file mode 100644 index a16b55cac6..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction.js +++ /dev/null @@ -1,68 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test for the following data of impression telemetry. -// - interaction - -add_setup(async function () { - await initInteractionTest(); -}); - -add_task(async function topsites() { - await doTopsitesTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", interaction: "topsites" }]), - }); -}); - -add_task(async function typed() { - await doTypedTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", interaction: "typed" }]), - }); - - await doTypedWithResultsPopupTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", interaction: "typed" }]), - }); -}); - -add_task(async function pasted() { - await doPastedTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", interaction: "pasted" }]), - }); - - await doPastedWithResultsPopupTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", interaction: "pasted" }]), - }); -}); - -add_task(async function topsite_search() { - await doTopsitesSearchTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { reason: "pause", interaction: "topsite_search" }, - ]), - }); -}); - -add_task(async function returned_restarted_refined() { - await doReturnedRestartedRefinedTest({ - trigger: () => waitForPauseImpression(), - assert: expected => - assertImpressionTelemetry([ - { reason: "pause" }, - { reason: "pause", interaction: expected }, - ]), - }); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_disabled.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_disabled.js deleted file mode 100644 index af7134b3a0..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_disabled.js +++ /dev/null @@ -1,57 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test impression telemetry with persisted search terms disabled. - -// 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 initInteractionTest(); - - await SpecialPowers.pushPrefEnv({ - set: [["browser.urlbar.showSearchTerms.featureGate", false]], - }); -}); - -add_task(async function persisted_search_terms() { - await doPersistedSearchTermsTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { reason: "pause" }, - { reason: "pause", interaction: "typed" }, - ]), - }); -}); - -add_task(async function persisted_search_terms_restarted_refined() { - await doPersistedSearchTermsRestartedRefinedTest({ - enabled: false, - trigger: () => waitForPauseImpression(), - assert: expected => - assertImpressionTelemetry([ - { reason: "pause" }, - { reason: "pause", interaction: expected }, - ]), - }); -}); - -add_task( - async function persisted_search_terms_restarted_refined_via_abandonment() { - await doPersistedSearchTermsRestartedRefinedViaAbandonmentTest({ - enabled: false, - trigger: () => waitForPauseImpression(), - assert: expected => - assertImpressionTelemetry([ - { reason: "pause" }, - { reason: "pause" }, - { reason: "pause", interaction: expected }, - ]), - }); - } -); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_enabled.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_enabled.js deleted file mode 100644 index a29ff98b78..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_interaction_persisted_search_terms_enabled.js +++ /dev/null @@ -1,61 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test impression telemetry with persisted search terms enabled. - -// 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 initInteractionTest(); - - await SpecialPowers.pushPrefEnv({ - set: [ - ["browser.urlbar.showSearchTerms.featureGate", true], - ["browser.urlbar.showSearchTerms.enabled", true], - ["browser.search.widget.inNavBar", false], - ], - }); -}); - -add_task(async function interaction_persisted_search_terms() { - await doPersistedSearchTermsTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { reason: "pause" }, - { reason: "pause", interaction: "persisted_search_terms" }, - ]), - }); -}); - -add_task(async function interaction_persisted_search_terms_restarted_refined() { - await doPersistedSearchTermsRestartedRefinedTest({ - enabled: true, - trigger: () => waitForPauseImpression(), - assert: expected => - assertImpressionTelemetry([ - { reason: "pause" }, - { reason: "pause", interaction: expected }, - ]), - }); -}); - -add_task( - async function interaction_persisted_search_terms_restarted_refined_via_abandonment() { - await doPersistedSearchTermsRestartedRefinedViaAbandonmentTest({ - enabled: true, - trigger: () => waitForPauseImpression(), - assert: expected => - assertImpressionTelemetry([ - { reason: "pause" }, - { reason: "pause" }, - { reason: "pause", interaction: expected }, - ]), - }); - } -); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_n_chars_n_words.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_n_chars_n_words.js deleted file mode 100644 index 528cc318e0..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_n_chars_n_words.js +++ /dev/null @@ -1,40 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test for the following data of impression telemetry. -// - n_chars -// - n_words - -add_setup(async function () { - await initNCharsAndNWordsTest(); -}); - -add_task(async function n_chars() { - await doNCharsTest({ - trigger: () => waitForPauseImpression(), - assert: nChars => - assertImpressionTelemetry([{ reason: "pause", n_chars: nChars }]), - }); - - await doNCharsWithOverMaxTextLengthCharsTest({ - trigger: () => waitForPauseImpression(), - assert: nChars => - assertImpressionTelemetry([{ reason: "pause", n_chars: nChars }]), - }); -}); - -add_task(async function n_words() { - await doNWordsTest({ - trigger: () => waitForPauseImpression(), - assert: nWords => - assertImpressionTelemetry([{ reason: "pause", n_words: nWords }]), - }); - - await doNWordsWithOverMaxTextLengthCharsTest({ - trigger: () => waitForPauseImpression(), - assert: nWords => - assertImpressionTelemetry([{ reason: "pause", n_words: nWords }]), - }); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_preferences.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_preferences.js deleted file mode 100644 index 344e238e24..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_preferences.js +++ /dev/null @@ -1,41 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test the impression telemetry behavior with its preferences. - -add_setup(async function () { - await setup(); -}); - -add_task(async function pauseImpressionIntervalMs() { - const additionalInterval = 1000; - const originalInterval = UrlbarPrefs.get( - "searchEngagementTelemetry.pauseImpressionIntervalMs" - ); - await SpecialPowers.pushPrefEnv({ - set: [ - [ - "browser.urlbar.searchEngagementTelemetry.pauseImpressionIntervalMs", - originalInterval + additionalInterval, - ], - ], - }); - - await doTest(async browser => { - await openPopup("https://example.com"); - - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(r => setTimeout(r, originalInterval)); - await Services.fog.testFlushAllChildren(); - assertImpressionTelemetry([]); - - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(r => setTimeout(r, additionalInterval)); - await Services.fog.testFlushAllChildren(); - assertImpressionTelemetry([{ sap: "urlbar_newtab" }]); - }); - - await SpecialPowers.popPrefEnv(); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_sap.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_sap.js deleted file mode 100644 index 482b906024..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_sap.js +++ /dev/null @@ -1,38 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test for the following data of impression telemetry. -// - sap - -add_setup(async function () { - await initSapTest(); -}); - -add_task(async function urlbar() { - await doUrlbarTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { reason: "pause", sap: "urlbar_newtab" }, - { reason: "pause", sap: "urlbar" }, - ]), - }); -}); - -add_task(async function handoff() { - await doHandoffTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", sap: "handoff" }]), - }); -}); - -add_task(async function urlbar_addonpage() { - await doUrlbarAddonpageTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", sap: "urlbar_addonpage" }]), - }); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_engine_default_id.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_engine_default_id.js deleted file mode 100644 index c5bd983d7f..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_engine_default_id.js +++ /dev/null @@ -1,28 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test for the following data of impression telemetry. -// - search_engine_default_id - -add_setup(async function () { - await initSearchEngineDefaultIdTest(); - // Increase the pausing time to ensure to ready for all suggestions. - await SpecialPowers.pushPrefEnv({ - set: [ - [ - "browser.urlbar.searchEngagementTelemetry.pauseImpressionIntervalMs", - 500, - ], - ], - }); -}); - -add_task(async function basic() { - await doSearchEngineDefaultIdTest({ - trigger: () => waitForPauseImpression(), - assert: engineId => - assertImpressionTelemetry([{ search_engine_default_id: engineId }]), - }); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_mode.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_mode.js deleted file mode 100644 index 727afa3cef..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_search_mode.js +++ /dev/null @@ -1,72 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test for the following data of impression telemetry. -// - search_mode - -add_setup(async function () { - await initSearchModeTest(); - // Increase the pausing time to ensure entering search mode. - await SpecialPowers.pushPrefEnv({ - set: [ - [ - "browser.urlbar.searchEngagementTelemetry.pauseImpressionIntervalMs", - 1000, - ], - ], - }); -}); - -add_task(async function not_search_mode() { - await doNotSearchModeTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", search_mode: "" }]), - }); -}); - -add_task(async function search_engine() { - await doSearchEngineTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { reason: "pause", search_mode: "search_engine" }, - ]), - }); -}); - -add_task(async function bookmarks() { - await doBookmarksTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([ - { reason: "pause", search_mode: "bookmarks" }, - ]), - }); -}); - -add_task(async function history() { - await doHistoryTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", search_mode: "history" }]), - }); -}); - -add_task(async function tabs() { - await doTabTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", search_mode: "tabs" }]), - }); -}); - -add_task(async function actions() { - await doActionsTest({ - trigger: () => waitForPauseImpression(), - assert: () => - assertImpressionTelemetry([{ reason: "pause", search_mode: "actions" }]), - }); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_timing.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_timing.js deleted file mode 100644 index 31f64996f3..0000000000 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_impression_timing.js +++ /dev/null @@ -1,91 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test for the taking timing for the impression telemetry. - -add_setup(async function () { - await setup(); -}); - -add_task(async function cancelImpressionTimerByEngagementEvent() { - const additionalInterval = 1000; - const originalInterval = UrlbarPrefs.get( - "searchEngagementTelemetry.pauseImpressionIntervalMs" - ); - await SpecialPowers.pushPrefEnv({ - set: [ - [ - "browser.urlbar.searchEngagementTelemetry.pauseImpressionIntervalMs", - originalInterval + additionalInterval, - ], - ], - }); - - for (const trigger of [doEnter, doBlur]) { - await doTest(async browser => { - await openPopup("https://example.com"); - await trigger(); - - // Check whether the impression timer was canceled. - await new Promise(r => - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - setTimeout(r, originalInterval + additionalInterval) - ); - assertImpressionTelemetry([]); - }); - } - - await SpecialPowers.popPrefEnv(); -}); - -add_task(async function cancelInpressionTimerByType() { - const originalInterval = UrlbarPrefs.get( - "searchEngagementTelemetry.pauseImpressionIntervalMs" - ); - - await doTest(async browser => { - await openPopup("x"); - await new Promise(r => - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - setTimeout(r, originalInterval / 10) - ); - assertImpressionTelemetry([]); - - EventUtils.synthesizeKey(" "); - EventUtils.synthesizeKey("z"); - await UrlbarTestUtils.promiseSearchComplete(window); - assertImpressionTelemetry([]); - await waitForPauseImpression(); - - assertImpressionTelemetry([{ n_chars: 3 }]); - }); -}); - -add_task(async function oneImpressionInOneSession() { - await doTest(async browser => { - await openPopup("x"); - await waitForPauseImpression(); - - // Sanity check. - assertImpressionTelemetry([{ n_chars: 1 }]); - - // Add a keyword to start new query. - EventUtils.synthesizeKey(" "); - EventUtils.synthesizeKey("z"); - await UrlbarTestUtils.promiseSearchComplete(window); - await waitForPauseImpression(); - - // No more taking impression telemetry. - assertImpressionTelemetry([{ n_chars: 1 }]); - - // Finish the current session. - await doEnter(); - - // Should take pause impression since new session started. - await openPopup("x z y"); - await waitForPauseImpression(); - assertImpressionTelemetry([{ n_chars: 1 }, { n_chars: 5 }]); - }); -}); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js index e86c664b46..cc73c7509f 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js @@ -11,7 +11,7 @@ ChromeUtils.defineESModuleGetters(this, { }); async function doHeuristicsTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await trigger(); @@ -24,7 +24,7 @@ async function doAdaptiveHistoryTest({ trigger, assert }) { set: [["browser.urlbar.autoFill", false]], }); - await doTest(async browser => { + await doTest(async () => { await PlacesTestUtils.addVisits(["https://example.com/test"]); await UrlbarUtils.addToInputHistory("https://example.com/test", "examp"); @@ -46,7 +46,7 @@ async function doSearchHistoryTest({ trigger, assert }) { ], }); - await doTest(async browser => { + await doTest(async () => { await UrlbarTestUtils.formHistory.add(["foofoo", "foobar"]); await openPopup("foo"); @@ -64,7 +64,7 @@ async function doRecentSearchTest({ trigger, assert }) { set: [["browser.urlbar.recentsearches.featureGate", true]], }); - await doTest(async browser => { + await doTest(async () => { await UrlbarTestUtils.formHistory.add([ { value: "foofoo", source: Services.search.defaultEngine.name }, ]); @@ -87,7 +87,7 @@ async function doSearchSuggestTest({ trigger, assert }) { ], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("foo"); await selectRowByURL("http://mochi.test:8888/?terms=foofoo"); @@ -101,7 +101,7 @@ async function doSearchSuggestTest({ trigger, assert }) { async function doTailSearchSuggestTest({ trigger, assert }) { const cleanup = await _useTailSuggestionsEngine(); - await doTest(async browser => { + await doTest(async () => { await openPopup("hello"); await selectRowByProvider("SearchSuggestions"); @@ -127,7 +127,7 @@ async function doTopPickTest({ trigger, assert }) { ], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("navigational"); await selectRowByURL("https://example.com/navigational-suggestion"); @@ -139,7 +139,7 @@ async function doTopPickTest({ trigger, assert }) { } async function doTopSiteTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await addTopSites("https://example.com/"); await showResultByArrowDown(); @@ -158,7 +158,7 @@ async function doClipboardTest({ trigger, assert }) { ], }); SpecialPowers.clipboardCopyString("https://example.com/clipboard"); - await doTest(async browser => { + await doTest(async () => { await showResultByArrowDown(); await selectRowByURL("https://example.com/clipboard"); @@ -173,7 +173,7 @@ async function doClipboardTest({ trigger, assert }) { async function doRemoteTabTest({ trigger, assert }) { const remoteTab = await loadRemoteTab("https://example.com"); - await doTest(async browser => { + await doTest(async () => { await openPopup("example"); await selectRowByProvider("RemoteTabs"); @@ -188,7 +188,7 @@ async function doAddonTest({ trigger, assert }) { const addon = loadOmniboxAddon({ keyword: "omni" }); await addon.startup(); - await doTest(async browser => { + await doTest(async () => { await openPopup("omni test"); await trigger(); @@ -199,7 +199,7 @@ async function doAddonTest({ trigger, assert }) { } async function doGeneralBookmarkTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: "https://example.com/bookmark", @@ -219,7 +219,7 @@ async function doGeneralHistoryTest({ trigger, assert }) { set: [["browser.urlbar.autoFill", false]], }); - await doTest(async browser => { + await doTest(async () => { await PlacesTestUtils.addVisits("https://example.com/test"); await openPopup("example"); @@ -235,7 +235,7 @@ async function doGeneralHistoryTest({ trigger, assert }) { async function doSuggestTest({ trigger, assert }) { const cleanupQuickSuggest = await ensureQuickSuggestInit(); - await doTest(async browser => { + await doTest(async () => { await openPopup("nonsponsored"); await selectRowByURL("https://example.com/nonsponsored"); @@ -251,7 +251,7 @@ async function doAboutPageTest({ trigger, assert }) { set: [["browser.urlbar.maxRichResults", 3]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("about:"); await selectRowByURL("about:robots"); @@ -267,7 +267,7 @@ async function doSuggestedIndexTest({ trigger, assert }) { set: [["browser.urlbar.unitConversion.enabled", true]], }); - await doTest(async browser => { + await doTest(async () => { await openPopup("1m to cm"); await selectRowByProvider("UnitConversion"); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head-interaction.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head-interaction.js index 244e27d272..58c55b416f 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/head-interaction.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/head-interaction.js @@ -14,7 +14,7 @@ ChromeUtils.defineESModuleGetters(this, { }); async function doTopsitesTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await addTopSites("https://example.com/"); await showResultByArrowDown(); @@ -120,7 +120,7 @@ async function doTopsitesSearchTest({ trigger, assert }) { } async function doTypedTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await trigger(); @@ -129,7 +129,7 @@ async function doTypedTest({ trigger, assert }) { } async function doTypedWithResultsPopupTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await showResultByArrowDown(); EventUtils.synthesizeKey("x"); await UrlbarTestUtils.promiseSearchComplete(window); @@ -140,7 +140,7 @@ async function doTypedWithResultsPopupTest({ trigger, assert }) { } async function doPastedTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await doPaste("www.example.com"); await trigger(); @@ -149,7 +149,7 @@ async function doPastedTest({ trigger, assert }) { } async function doPastedWithResultsPopupTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await showResultByArrowDown(); await doPaste("x"); @@ -189,9 +189,8 @@ async function doReturnedRestartedRefinedTest({ trigger, assert }) { ]; for (const { firstInput, secondInput, expected } of testData) { - await doTest(async browser => { + await doTest(async () => { await openPopup(firstInput); - await waitForPauseImpression(); await doBlur(); await UrlbarTestUtils.promisePopupOpen(window, () => { @@ -211,9 +210,8 @@ async function doReturnedRestartedRefinedTest({ trigger, assert }) { } async function doPersistedSearchTermsTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); - await waitForPauseImpression(); await doEnter(); await openPopup("x"); @@ -258,9 +256,8 @@ async function doPersistedSearchTermsRestartedRefinedTest({ ]; for (const { firstInput, secondInput, expected } of testData) { - await doTest(async browser => { + await doTest(async () => { await openPopup(firstInput); - await waitForPauseImpression(); await doEnter(); await UrlbarTestUtils.promisePopupOpen(window, () => { @@ -314,13 +311,11 @@ async function doPersistedSearchTermsRestartedRefinedViaAbandonmentTest({ ]; for (const { firstInput, secondInput, expected } of testData) { - await doTest(async browser => { + await doTest(async () => { await openPopup("any search"); - await waitForPauseImpression(); await doEnter(); await openPopup(firstInput); - await waitForPauseImpression(); await doBlur(); await UrlbarTestUtils.promisePopupOpen(window, () => { diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head-n_chars_n_words.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head-n_chars_n_words.js index 6d4c61c7f0..154f3ec11c 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/head-n_chars_n_words.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/head-n_chars_n_words.js @@ -7,7 +7,7 @@ async function doNCharsTest({ trigger, assert }) { for (const input of ["x", "xx", "xx x", "xx x "]) { - await doTest(async browser => { + await doTest(async () => { await openPopup(input); await trigger(); @@ -17,7 +17,7 @@ async function doNCharsTest({ trigger, assert }) { } async function doNCharsWithOverMaxTextLengthCharsTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { let input = ""; for (let i = 0; i < UrlbarUtils.MAX_TEXT_LENGTH * 2; i++) { input += "x"; @@ -31,7 +31,7 @@ async function doNCharsWithOverMaxTextLengthCharsTest({ trigger, assert }) { async function doNWordsTest({ trigger, assert }) { for (const input of ["x", "xx", "xx x", "xx x "]) { - await doTest(async browser => { + await doTest(async () => { await openPopup(input); await trigger(); @@ -42,7 +42,7 @@ async function doNWordsTest({ trigger, assert }) { } async function doNWordsWithOverMaxTextLengthCharsTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { const word = "1234 "; let input = ""; while (input.length < UrlbarUtils.MAX_TEXT_LENGTH * 2) { diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head-sap.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head-sap.js index ef95873813..ee74136b22 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/head-sap.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/head-sap.js @@ -6,7 +6,7 @@ /* import-globals-from head.js */ async function doUrlbarNewTabTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await trigger(); @@ -15,9 +15,8 @@ async function doUrlbarNewTabTest({ trigger, assert }) { } async function doUrlbarTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); - await waitForPauseImpression(); await doEnter(); await openPopup("y"); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_engine_default_id.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_engine_default_id.js index c0af764e7f..5bf8cc3735 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_engine_default_id.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_engine_default_id.js @@ -6,7 +6,7 @@ /* import-globals-from head.js */ async function doSearchEngineDefaultIdTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { info("Test with current engine"); const defaultEngine = await Services.search.getDefault(); @@ -15,7 +15,7 @@ async function doSearchEngineDefaultIdTest({ trigger, assert }) { await assert(defaultEngine.telemetryId); }); - await doTest(async browser => { + await doTest(async () => { info("Test with new engine"); const defaultEngine = await Services.search.getDefault(); const newEngineName = "NewDummyEngine"; diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_mode.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_mode.js index 5c877da05f..86151e1ba3 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_mode.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_mode.js @@ -6,7 +6,7 @@ /* import-globals-from head.js */ async function doNotSearchModeTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await trigger(); @@ -15,7 +15,7 @@ async function doNotSearchModeTest({ trigger, assert }) { } async function doSearchEngineTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("x"); await UrlbarTestUtils.enterSearchMode(window); @@ -25,7 +25,7 @@ async function doSearchEngineTest({ trigger, assert }) { } async function doBookmarksTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: "https://example.com/bookmark", @@ -47,7 +47,7 @@ async function doHistoryTest({ trigger, assert }) { set: [["browser.urlbar.autoFill", false]], }); - await doTest(async browser => { + await doTest(async () => { await PlacesTestUtils.addVisits("https://example.com/test"); await openPopup("example"); await UrlbarTestUtils.enterSearchMode(window, { @@ -65,7 +65,7 @@ async function doHistoryTest({ trigger, assert }) { async function doTabTest({ trigger, assert }) { const tab = BrowserTestUtils.addTab(gBrowser, "https://example.com/"); - await doTest(async browser => { + await doTest(async () => { await openPopup("example"); await UrlbarTestUtils.enterSearchMode(window, { source: UrlbarUtils.RESULT_SOURCE.TABS, @@ -80,7 +80,7 @@ async function doTabTest({ trigger, assert }) { } async function doActionsTest({ trigger, assert }) { - await doTest(async browser => { + await doTest(async () => { await openPopup("add"); await UrlbarTestUtils.enterSearchMode(window, { source: UrlbarUtils.RESULT_SOURCE.ACTIONS, diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head.js index 367387b0e8..4317a50930 100644 --- a/browser/components/urlbar/tests/engagementTelemetry/browser/head.js +++ b/browser/components/urlbar/tests/engagementTelemetry/browser/head.js @@ -58,10 +58,6 @@ function assertEngagementTelemetry(expectedExtraList) { _assertGleanTelemetry("engagement", expectedExtraList); } -function assertImpressionTelemetry(expectedExtraList) { - _assertGleanTelemetry("impression", expectedExtraList); -} - function assertExposureTelemetry(expectedExtraList) { _assertGleanTelemetry("exposure", expectedExtraList); } @@ -204,12 +200,6 @@ async function doPasteAndGo(data) { async function doTest(testFn) { await Services.fog.testFlushAllChildren(); Services.fog.testResetFOG(); - // Enable recording telemetry for impression, as it is disabled by default. - Services.fog.setMetricsFeatureConfig( - JSON.stringify({ - "urlbar.impression": true, - }) - ); gURLBar.controller.engagementEvent.reset(); await PlacesUtils.history.clear(); @@ -223,8 +213,8 @@ async function doTest(testFn) { try { await BrowserTestUtils.withNewTab(gBrowser, testFn); - } finally { - Services.fog.setMetricsFeatureConfig("{}"); + } catch (e) { + console.error(e); } } @@ -423,10 +413,6 @@ async function setup() { ["browser.urlbar.quickactions.minimumSearchString", 0], ["browser.urlbar.suggest.quickactions", true], ["browser.urlbar.shortcuts.quickactions", true], - [ - "browser.urlbar.searchEngagementTelemetry.pauseImpressionIntervalMs", - 100, - ], ], }); @@ -461,13 +447,3 @@ async function showResultByArrowDown() { }); await UrlbarTestUtils.promiseSearchComplete(window); } - -async function waitForPauseImpression() { - await new Promise(r => - setTimeout( - r, - UrlbarPrefs.get("searchEngagementTelemetry.pauseImpressionIntervalMs") - ) - ); - await Services.fog.testFlushAllChildren(); -} diff --git a/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs b/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs index 6cda9bb9a7..1828ddbceb 100644 --- a/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs +++ b/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs @@ -355,20 +355,16 @@ class _MerinoTestUtils { lazy.QuickSuggest.weather._test_fetchIntervalMs = WEATHER_FETCH_INTERVAL_MS; - // Enabling weather will trigger a fetch. Wait for it to finish so the - // suggestion is ready when this function returns. - this.info("MockMerinoServer initializing weather, waiting for fetch"); - let fetchPromise = lazy.QuickSuggest.weather.waitForFetches(); + // Enabling weather will trigger a fetch. Queue another fetch and await it + // so no fetches are ongoing when this function returns. + this.info("MockMerinoServer initializing weather, setting prefs"); lazy.UrlbarPrefs.set("weather.featureGate", true); lazy.UrlbarPrefs.set("suggest.weather", true); - await fetchPromise; - this.info("MockMerinoServer initializing weather, got fetch"); - - this.Assert.equal( - lazy.QuickSuggest.weather._test_pendingFetchCount, - 0, - "No pending fetches after awaiting initial fetch" + this.info( + "MockMerinoServer initializing weather, done setting prefs, starting fetch" ); + await lazy.QuickSuggest.weather._test_fetch(); + this.info("MockMerinoServer initializing weather, done awaiting fetch"); this.registerCleanupFunction?.(async () => { lazy.UrlbarPrefs.clear("weather.featureGate"); diff --git a/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs b/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs index 32b42198c3..c2aeca1991 100644 --- a/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs +++ b/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs @@ -9,7 +9,6 @@ ChromeUtils.defineESModuleGetters(lazy, { HttpError: "resource://testing-common/httpd.sys.mjs", HttpServer: "resource://testing-common/httpd.sys.mjs", HTTP_404: "resource://testing-common/httpd.sys.mjs", - Log: "resource://gre/modules/Log.sys.mjs", }); const SERVER_PREF = "services.settings.server"; @@ -23,23 +22,16 @@ export class RemoteSettingsServer { * The server must be started by calling `start()`. * * @param {object} options - * @param {number} options.logLevel - * A `Log.Level` value from `Log.sys.mjs`. `Log.Level.Info` logs basic info - * on requests and responses like paths and status codes. Pass - * `Log.Level.Debug` to log more info like headers, response bodies, and - * added and removed records. + * @param {number} options.maxLogLevel + * A log level value as defined by ConsoleInstance. `Info` logs basic info + * on requests and responses like paths and status codes. Pass `Debug` to + * log more info like headers, response bodies, added and removed records. */ - constructor({ logLevel = lazy.Log.Level.Info } = {}) { - this.#log = lazy.Log.repository.getLogger("RemoteSettingsServer"); - this.#log.level = logLevel; - - // Use `DumpAppender` instead of `ConsoleAppender`. The xpcshell and browser - // test harnesses buffer console messages and log them later, which makes it - // really hard to debug problems. `DumpAppender` logs to stdout, which the - // harnesses log immediately. - this.#log.addAppender( - new lazy.Log.DumpAppender(new lazy.Log.BasicFormatter()) - ); + constructor({ maxLogLevel = "Info" } = {}) { + this.#log = console.createInstance({ + prefix: "RemoteSettingsServer", + maxLogLevel, + }); } /** @@ -587,14 +579,12 @@ export class RemoteSettingsServer { * The associated request. * @param {integer} options.status * The HTTP status code of the response. - * @param {string} options.statusText - * The description of the status code. * @param {object} options.headers * An object mapping from response header names to values. * @param {object} options.body * The response body, if any. */ - #logResponse({ request, status, statusText, headers, body }) { + #logResponse({ request, status, headers, body }) { this.#log.info(`> ${status} ${request.path}`); for (let [name, value] of Object.entries(headers)) { this.#log.debug(`${name}: ${value}`); diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js index 6256a5aec2..dbd8f59ade 100644 --- a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js +++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js @@ -373,7 +373,6 @@ const VARIATION_TEST_DATA = [ "onboardingNext", "onboardingAccept", "onboardingLearnMore", - "onboardingReject", "onboardingSkipLink", "onboardingDialog", "onboardingAccept", @@ -706,7 +705,6 @@ const VARIATION_TEST_DATA = [ "onboardingNext", "onboardingLearnMore", "onboardingAccept", - "onboardingReject", "onboardingSkipLink", "onboardingDialog", "onboardingLearnMore", @@ -762,7 +760,6 @@ const VARIATION_TEST_DATA = [ defaultFocusOrder: [ "onboardingLearnMore", "onboardingAccept", - "onboardingReject", "onboardingSkipLink", "onboardingDialog", "onboardingLearnMore", diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js index 8682f1f53a..821c5cf470 100644 --- a/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js +++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js @@ -172,7 +172,7 @@ add_task(async function hiddenRow() { // mutation listener to the view so we can tell when the quick suggest row is // added. let mutationPromise = new Promise(resolve => { - let observer = new MutationObserver(mutations => { + let observer = new MutationObserver(() => { let rows = UrlbarTestUtils.getResultsContainer(window).children; for (let row of rows) { if (row.result.providerName == "UrlbarProviderQuickSuggest") { diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js index 1c3f0e62e7..e10e87b516 100644 --- a/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js +++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js @@ -11,6 +11,11 @@ ChromeUtils.defineESModuleGetters(this, { UrlbarProviderWeather: "resource:///modules/UrlbarProviderWeather.sys.mjs", }); +// This test takes a while and can time out in verify mode. Each task is run +// twice, once with Rust enabled and once with it disabled. Once we remove the +// JS backend this should improve a lot, but for now request a longer timeout. +requestLongerTimeout(5); + add_setup(async function () { await QuickSuggestTestUtils.ensureQuickSuggestInit({ remoteSettingsRecords: [ @@ -21,6 +26,15 @@ add_setup(async function () { ], }); await MerinoTestUtils.initWeather(); + + // When `add_tasks_with_rust()` disables the Rust backend and forces sync, the + // JS backend will sync `Weather` with remote settings. Since keywords are + // present in remote settings at that point (we added them above), `Weather` + // will then start fetching. The fetch may or may not be done before our test + // task starts. To make sure it's done, queue another fetch and await it. + registerAddTasksWithRustSetup(async () => { + await QuickSuggest.weather._test_fetch(); + }); }); // Basic checks of the row DOM. @@ -341,11 +355,8 @@ async function doDismissTest(command) { await UrlbarTestUtils.promisePopupClose(window); // Enable the weather suggestion again and wait for it to be fetched. - let fetchPromise = QuickSuggest.weather.waitForFetches(); UrlbarPrefs.clear("suggest.weather"); - info("Waiting for weather fetch after re-enabling the suggestion"); - await fetchPromise; - info("Got weather fetch"); + await QuickSuggest.weather._test_fetch(); // Wait for keywords to be re-synced from remote settings. await QuickSuggestTestUtils.forceSync(); @@ -396,6 +407,94 @@ async function doSessionOngoingCommandTest(command) { await doDismissTest("not_interested"); } +// Test for menu item to mange the suggest. +add_tasks_with_rust(async function manage() { + await BrowserTestUtils.withNewTab({ gBrowser }, async browser => { + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: MerinoTestUtils.WEATHER_KEYWORD, + }); + + let resultIndex = 1; + let details = await UrlbarTestUtils.getDetailsOfResultAt( + window, + resultIndex + ); + assertIsWeatherResult(details.result, true); + + const managePage = "about:preferences#search"; + let onManagePageLoaded = BrowserTestUtils.browserLoaded( + browser, + false, + managePage + ); + // Click the command. + await UrlbarTestUtils.openResultMenuAndClickItem(window, "manage", { + resultIndex, + }); + await onManagePageLoaded; + Assert.equal( + browser.currentURI.spec, + managePage, + "The manage page is loaded" + ); + + await UrlbarTestUtils.promisePopupClose(window); + }); +}); + +// Test for simple UI. +add_tasks_with_rust(async function simpleUI() { + const testData = [ + { + weatherSimpleUI: true, + expectedSummary: + MerinoTestUtils.WEATHER_SUGGESTION.current_conditions.summary, + }, + { + weatherSimpleUI: false, + expectedSummary: `${MerinoTestUtils.WEATHER_SUGGESTION.current_conditions.summary}; ${MerinoTestUtils.WEATHER_SUGGESTION.forecast.summary}`, + }, + ]; + + for (let { weatherSimpleUI, expectedSummary } of testData) { + let nimbusCleanup = await UrlbarTestUtils.initNimbusFeature({ + weatherSimpleUI, + }); + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: MerinoTestUtils.WEATHER_KEYWORD, + }); + + let resultIndex = 1; + let details = await UrlbarTestUtils.getDetailsOfResultAt( + window, + resultIndex + ); + assertIsWeatherResult(details.result, true); + + let { row } = details.element; + let summary = row.querySelector(".urlbarView-dynamic-weather-summaryText"); + + // `getViewUpdate()` is allowed to be async and `UrlbarView` awaits it even + // though the `Weather` implementation is not async. That means the summary + // text content will be updated asyncly, so we need to wait for it. + await TestUtils.waitForCondition( + () => summary.textContent == expectedSummary, + "Waiting for the row's summary text to be updated" + ); + Assert.equal( + summary.textContent, + expectedSummary, + "The summary text should be correct" + ); + + await UrlbarTestUtils.promisePopupClose(window); + await nimbusCleanup(); + } +}); + function assertIsWeatherResult(result, isWeatherResult) { let provider = UrlbarPrefs.get("quickSuggestRustEnabled") ? UrlbarProviderQuickSuggest diff --git a/browser/components/urlbar/tests/quicksuggest/browser/head.js b/browser/components/urlbar/tests/quicksuggest/browser/head.js index 7d62a44d45..cc5f449e94 100644 --- a/browser/components/urlbar/tests/quicksuggest/browser/head.js +++ b/browser/components/urlbar/tests/quicksuggest/browser/head.js @@ -636,20 +636,49 @@ function _assertGleanPing(ping) { } } +let gAddTasksWithRustSetup; + /** * Adds two tasks: One with the Rust backend disabled and one with it enabled. * The names of the task functions will be the name of the passed-in task - * function appended with "_rustDisabled" and "_rustEnabled" respectively. Call - * with the usual `add_task()` arguments. + * function appended with "_rustDisabled" and "_rustEnabled". If the passed-in + * task doesn't have a name, "anonymousTask" will be used. + * + * Call this with the usual `add_task()` arguments. Additionally, an object with + * the following properties can be specified as any argument: + * + * {boolean} skip_if_rust_enabled + * If true, a "_rustEnabled" task won't be added. Useful when Rust is enabled + * by default but the task doesn't make sense with Rust and you still want to + * test some behavior when Rust is disabled. * * @param {...any} args * The usual `add_task()` arguments. */ function add_tasks_with_rust(...args) { + let skipIfRustEnabled = false; + let i = args.findIndex(a => a.skip_if_rust_enabled); + if (i >= 0) { + skipIfRustEnabled = true; + args.splice(i, 1); + } + let taskFnIndex = args.findIndex(a => typeof a == "function"); let taskFn = args[taskFnIndex]; for (let rustEnabled of [false, true]) { + let newTaskName = + (taskFn.name || "anonymousTask") + + (rustEnabled ? "_rustEnabled" : "_rustDisabled"); + + if (rustEnabled && skipIfRustEnabled) { + info( + "add_tasks_with_rust: Skipping due to skip_if_rust_enabled: " + + newTaskName + ); + continue; + } + let newTaskFn = async (...taskFnArgs) => { info("add_tasks_with_rust: Setting rustEnabled: " + rustEnabled); UrlbarPrefs.set("quicksuggest.rustEnabled", rustEnabled); @@ -660,12 +689,30 @@ function add_tasks_with_rust(...args) { await QuickSuggestTestUtils.forceSync(); info("add_tasks_with_rust: Done forcing sync"); + if (gAddTasksWithRustSetup) { + info("add_tasks_with_rust: Calling setup function"); + await gAddTasksWithRustSetup(); + info("add_tasks_with_rust: Done calling setup function"); + } + let rv; try { info( "add_tasks_with_rust: Calling original task function: " + taskFn.name ); rv = await taskFn(...taskFnArgs); + } catch (e) { + // Clearly report any unusual errors to make them easier to spot and to + // make the flow of the test clearer. The harness throws NS_ERROR_ABORT + // when a normal assertion fails, so don't report that. + if (e.result != Cr.NS_ERROR_ABORT) { + Assert.ok( + false, + "add_tasks_with_rust: The original task function threw an error: " + + e + ); + } + throw e; } finally { info( "add_tasks_with_rust: Done calling original task function: " + @@ -683,11 +730,32 @@ function add_tasks_with_rust(...args) { return rv; }; - Object.defineProperty(newTaskFn, "name", { - value: taskFn.name + (rustEnabled ? "_rustEnabled" : "_rustDisabled"), - }); - let addTaskArgs = [...args]; - addTaskArgs[taskFnIndex] = newTaskFn; + Object.defineProperty(newTaskFn, "name", { value: newTaskName }); + + let addTaskArgs = []; + for (let j = 0; j < args.length; j++) { + addTaskArgs[j] = + j == taskFnIndex + ? newTaskFn + : Cu.cloneInto(args[j], this, { cloneFunctions: true }); + } add_task(...addTaskArgs); } } + +/** + * Registers a setup function that `add_tasks_with_rust()` will await before + * calling each of your original tasks. Call this at most once in your test file + * (i.e., in `add_setup()`). This is useful when enabling/disabling Rust has + * side effects related to your particular test that need to be handled or + * awaited for each of your tasks. On the other hand, if only one or two of your + * tasks need special setup, do it directly in those tasks instead of using + * this. The passed-in `setupFn` is automatically unregistered on cleanup. + * + * @param {Function} setupFn + * A function that will be awaited before your original tasks are called. + */ +function registerAddTasksWithRustSetup(setupFn) { + gAddTasksWithRustSetup = setupFn; + registerCleanupFunction(() => (gAddTasksWithRustSetup = null)); +} diff --git a/browser/components/urlbar/tests/quicksuggest/unit/head.js b/browser/components/urlbar/tests/quicksuggest/unit/head.js index c468e4526f..73bedf468e 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/head.js +++ b/browser/components/urlbar/tests/quicksuggest/unit/head.js @@ -20,18 +20,49 @@ add_setup(async function setUpQuickSuggestXpcshellTest() { UrlbarPrefs._testSkipTelemetryEnvironmentInit = true; }); +let gAddTasksWithRustSetup; + /** * Adds two tasks: One with the Rust backend disabled and one with it enabled. * The names of the task functions will be the name of the passed-in task * function appended with "_rustDisabled" and "_rustEnabled". If the passed-in - * task doesn't have a name, "anonymousTask" will be used. Call this with the - * usual `add_task()` arguments. + * task doesn't have a name, "anonymousTask" will be used. + * + * Call this with the usual `add_task()` arguments. Additionally, an object with + * the following properties can be specified as any argument: + * + * {boolean} skip_if_rust_enabled + * If true, a "_rustEnabled" task won't be added. Useful when Rust is enabled + * by default but the task doesn't make sense with Rust and you still want to + * test some behavior when Rust is disabled. + * + * @param {...any} args + * The usual `add_task()` arguments. */ function add_tasks_with_rust(...args) { + let skipIfRustEnabled = false; + let i = args.findIndex(a => a.skip_if_rust_enabled); + if (i >= 0) { + skipIfRustEnabled = true; + args.splice(i, 1); + } + let taskFnIndex = args.findIndex(a => typeof a == "function"); let taskFn = args[taskFnIndex]; for (let rustEnabled of [false, true]) { + let newTaskName = + (taskFn.name || "anonymousTask") + + (rustEnabled ? "_rustEnabled" : "_rustDisabled"); + + if (rustEnabled && skipIfRustEnabled) { + info( + "add_tasks_with_rust: Skipping due to skip_if_rust_enabled: " + + newTaskName + ); + continue; + } + let newTaskFn = async (...taskFnArgs) => { info("add_tasks_with_rust: Setting rustEnabled: " + rustEnabled); UrlbarPrefs.set("quicksuggest.rustEnabled", rustEnabled); @@ -42,6 +73,12 @@ function add_tasks_with_rust(...args) { await QuickSuggestTestUtils.forceSync(); info("add_tasks_with_rust: Done forcing sync"); + if (gAddTasksWithRustSetup) { + info("add_tasks_with_rust: Calling setup function"); + await gAddTasksWithRustSetup(); + info("add_tasks_with_rust: Done calling setup function"); + } + let rv; try { info( @@ -77,17 +114,35 @@ function add_tasks_with_rust(...args) { return rv; }; - Object.defineProperty(newTaskFn, "name", { - value: - (taskFn.name || "anonymousTask") + - (rustEnabled ? "_rustEnabled" : "_rustDisabled"), - }); - let addTaskArgs = [...args]; - addTaskArgs[taskFnIndex] = newTaskFn; + Object.defineProperty(newTaskFn, "name", { value: newTaskName }); + + let addTaskArgs = []; + for (let j = 0; j < args.length; j++) { + addTaskArgs[j] = + j == taskFnIndex + ? newTaskFn + : Cu.cloneInto(args[j], this, { cloneFunctions: true }); + } add_task(...addTaskArgs); } } +/** + * Registers a setup function that `add_tasks_with_rust()` will await before + * calling each of your original tasks. Call this at most once in your test file + * (i.e., in `add_setup()`). This is useful when enabling/disabling Rust has + * side effects related to your particular test that need to be handled or + * awaited for each of your tasks. On the other hand, if only one or two of your + * tasks need special setup, do it directly in those tasks instead of using + * this. + * + * @param {Function} setupFn + * A function that will be awaited before your original tasks are called. + */ +function registerAddTasksWithRustSetup(setupFn) { + gAddTasksWithRustSetup = setupFn; +} + /** * Returns an expected Wikipedia (non-sponsored) result that can be passed to * `check_results()` regardless of whether the Rust backend is enabled. @@ -106,7 +161,7 @@ function makeWikipediaResult({ iconBlob = new Blob([new Uint8Array([])]), impressionUrl = "http://example.com/wikipedia-impression", clickUrl = "http://example.com/wikipedia-click", - blockId = 1, + blockId = 2, advertiser = "Wikipedia", iabCategory = "5 - Education", suggestedIndex = -1, @@ -362,7 +417,6 @@ function makeWeatherResult({ temperatureUnit, url: MerinoTestUtils.WEATHER_SUGGESTION.url, iconId: "6", - helpUrl: QuickSuggest.HELP_URL, requestId: MerinoTestUtils.server.response.body.request_id, source: "merino", provider: "accuweather", @@ -909,3 +963,40 @@ async function doRustProvidersTests({ searchString, tests }) { UrlbarPrefs.clear("quicksuggest.rustEnabled"); await QuickSuggestTestUtils.forceSync(); } + +/** + * Waits for `Weather` to start and finish a new fetch. Typically you call this + * before you know a new fetch will start, save but don't await the promise, do + * the thing that triggers the new fetch, and then await the promise to wait for + * the fetch to finish. + * + * If a fetch is currently ongoing, this will first wait for a new fetch to + * start, which might not be what you want. If you only want to wait for any + * ongoing fetch to finish, await `QuickSuggest.weather.fetchPromise` instead. + */ +async function waitForNewWeatherFetch() { + let { fetchPromise: oldFetchPromise } = QuickSuggest.weather; + + // Wait for a new fetch to start. + let newFetchPromise; + await TestUtils.waitForCondition(() => { + let { fetchPromise } = QuickSuggest.weather; + if ( + (oldFetchPromise && fetchPromise != oldFetchPromise) || + (!oldFetchPromise && fetchPromise) + ) { + newFetchPromise = fetchPromise; + return true; + } + return false; + }, "Waiting for a new weather fetch to start"); + + Assert.equal( + QuickSuggest.weather.fetchPromise, + newFetchPromise, + "Sanity check: fetchPromise hasn't changed since waitForCondition returned" + ); + + // Wait for the new fetch to finish. + await newFetchPromise; +} diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js index e4c145aabb..59c0b26241 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js +++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js @@ -18,6 +18,8 @@ const HTTP_SEARCH_STRING = "http prefix"; const HTTPS_SEARCH_STRING = "https prefix"; const PREFIX_SUGGESTIONS_STRIPPED_URL = "example.com/prefix-test"; +const ONE_CHAR_SEARCH_STRINGS = ["x", "x ", " x", " x "]; + const { TIMESTAMP_TEMPLATE, TIMESTAMP_LENGTH } = QuickSuggest; const TIMESTAMP_SEARCH_STRING = "timestamp"; const TIMESTAMP_SUGGESTION_URL = `http://example.com/timestamp-${TIMESTAMP_TEMPLATE}`; @@ -69,6 +71,11 @@ const REMOTE_SETTINGS_RESULTS = [ iab_category: "22 - Shopping", icon: "1234", }, + QuickSuggestTestUtils.ampRemoteSettings({ + keywords: [...ONE_CHAR_SEARCH_STRINGS, "12", "a longer keyword"], + title: "Suggestion with 1-char keyword", + url: "http://example.com/1-char-keyword", + }), ]; function expectedNonSponsoredResult() { @@ -751,10 +758,10 @@ async function doDedupeAgainstURLTest({ } // Tests the remote settings latency histogram. -add_task( +add_tasks_with_rust( { // Not supported by the Rust backend. - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function latencyTelemetry() { UrlbarPrefs.set("suggest.quicksuggest.nonsponsored", true); @@ -791,10 +798,10 @@ add_task( // Tests setup and teardown of the remote settings client depending on whether // quick suggest is enabled. -add_task( +add_tasks_with_rust( { // Not supported by the Rust backend. - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function setupAndTeardown() { Assert.ok( @@ -885,7 +892,7 @@ add_task( "Remote settings backend is disabled after enabling the Rust backend" ); - UrlbarPrefs.clear("quicksuggest.rustEnabled"); + UrlbarPrefs.set("quicksuggest.rustEnabled", false); Assert.ok( QuickSuggest.jsBackend.rs, "Settings client is non-null after disabling the Rust backend" @@ -898,6 +905,7 @@ add_task( // Leave the prefs in the same state as when the task started. UrlbarPrefs.clear("suggest.quicksuggest.nonsponsored"); UrlbarPrefs.clear("suggest.quicksuggest.sponsored"); + UrlbarPrefs.clear("quicksuggest.rustEnabled"); UrlbarPrefs.set("quicksuggest.enabled", true); Assert.ok( !QuickSuggest.jsBackend.rs, @@ -1349,10 +1357,10 @@ add_tasks_with_rust(async function block_timestamp() { // Makes sure remote settings data is fetched using the correct `type` based on // the value of the `quickSuggestRemoteSettingsDataType` Nimbus variable. -add_task( +add_tasks_with_rust( { // Not supported by the Rust backend. - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function remoteSettingsDataType() { UrlbarPrefs.set("suggest.quicksuggest.sponsored", true); @@ -1509,7 +1517,7 @@ add_tasks_with_rust(async function tabToSearch() { // search heuristic makeSearchResult(context, { engineName: Services.search.defaultEngine.name, - engineIconUri: Services.search.defaultEngine.getIconURL(), + engineIconUri: await Services.search.defaultEngine.getIconURL(), heuristic: true, }), // tab to search @@ -1595,7 +1603,7 @@ add_tasks_with_rust(async function position() { // search heuristic makeSearchResult(context, { engineName: Services.search.defaultEngine.name, - engineIconUri: Services.search.defaultEngine.getIconURL(), + engineIconUri: await Services.search.defaultEngine.getIconURL(), heuristic: true, }), // best match whose backing suggestion has a `position` @@ -1659,3 +1667,35 @@ add_task(async function rustProviders() { ], }); }); + +// Tests the keyword/search-string-length threshold. Keywords/search strings +// must be at least two characters long to be matched. +add_tasks_with_rust(async function keywordLengthThreshold() { + UrlbarPrefs.set("suggest.quicksuggest.sponsored", true); + await QuickSuggestTestUtils.forceSync(); + + let tests = [ + ...ONE_CHAR_SEARCH_STRINGS.map(keyword => ({ keyword, expected: false })), + { keyword: "12", expected: true }, + { keyword: "a longer keyword", expected: true }, + ]; + + for (let { keyword, expected } of tests) { + await check_results({ + context: createContext(keyword, { + providers: [UrlbarProviderQuickSuggest.name], + isPrivate: false, + }), + matches: !expected + ? [] + : [ + makeAmpResult({ + keyword, + title: "Suggestion with 1-char keyword", + url: "http://example.com/1-char-keyword", + originalUrl: "http://example.com/1-char-keyword", + }), + ], + }); + } +}); diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js index c17f3f1655..806685eff7 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js +++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js @@ -42,7 +42,7 @@ const REMOTE_SETTINGS_RESULTS = [ icon: "https://example.com/first-addon.svg", title: "First Addon", rating: "4.7", - keywords: ["first", "1st", "two words", "a b c"], + keywords: ["first", "1st", "two words", "aa b c"], description: "Description for the First Addon", number_of_ratings: 1256, score: 0.25, @@ -353,35 +353,35 @@ add_tasks_with_rust(async function remoteSettings() { }), }, { - input: "a", + input: "aa", expected: makeExpectedResult({ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0], source: "remote-settings", }), }, { - input: "a ", + input: "aa ", expected: makeExpectedResult({ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0], source: "remote-settings", }), }, { - input: "a b", + input: "aa b", expected: makeExpectedResult({ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0], source: "remote-settings", }), }, { - input: "a b ", + input: "aa b ", expected: makeExpectedResult({ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0], source: "remote-settings", }), }, { - input: "a b c", + input: "aa b c", expected: makeExpectedResult({ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0], source: "remote-settings", diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js index 29133a8579..79b4df2b77 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js +++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js @@ -214,9 +214,9 @@ add_tasks_with_rust(async function lowPrefixes() { // starting at "how to" instead of the first word. // // Note: The Rust implementation doesn't support this. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function lowPrefixes_howTo() { // search string -> should match diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js b/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js index e6ec61bcd4..f2e3f96c1f 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js +++ b/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js @@ -78,11 +78,15 @@ add_task(async function firstRun() { await checkSuggestions(); - // Disable and re-enable the backend. No new ingestion should start - // immediately since this isn't the first time the backend has been enabled. + // Disable and re-enable the backend. Another ingest should start immediately + // since ingest is done every time the backend is re-enabled. UrlbarPrefs.set("quicksuggest.rustEnabled", false); UrlbarPrefs.set("quicksuggest.rustEnabled", true); - await assertNoNewIngestStarted(ingestPromise); + ({ ingestPromise } = await waitForIngestStart(ingestPromise)); + + info("Awaiting ingest promise"); + await ingestPromise; + info("Done awaiting ingest promise"); await checkSuggestions(); @@ -101,14 +105,18 @@ add_task(async function interval() { "Sanity check: Rust backend is initially disabled" ); - // Set a small interval and enable the backend. No new ingestion should start - // immediately since this isn't the first time the backend has been enabled. + // Set a small interval and enable the backend. A new ingest will immediately + // start. let intervalSecs = 1; UrlbarPrefs.set("quicksuggest.rustIngestIntervalSeconds", intervalSecs); UrlbarPrefs.set("quicksuggest.rustEnabled", true); - await assertNoNewIngestStarted(ingestPromise); + ({ ingestPromise } = await waitForIngestStart(ingestPromise)); - // Wait for a few ingests to happen. + info("Awaiting ingest promise"); + await ingestPromise; + info("Done awaiting ingest promise"); + + // Wait for a few ingests to happen due to the timer firing. for (let i = 0; i < 3; i++) { info("Preparing for ingest at index " + i); @@ -193,17 +201,6 @@ async function waitForIngestStart(oldIngestPromise) { return { ingestPromise: newIngestPromise }; } -async function assertNoNewIngestStarted(oldIngestPromise) { - for (let i = 0; i < 3; i++) { - await TestUtils.waitForTick(); - } - Assert.equal( - QuickSuggest.rustBackend.ingestPromise, - oldIngestPromise, - "No new ingest started" - ); -} - async function checkSuggestions(expected = [REMOTE_SETTINGS_SUGGESTION]) { let actual = await QuickSuggest.rustBackend.query("amp"); Assert.deepEqual( diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js b/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js index 28801904a1..cd794f435b 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js +++ b/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js @@ -34,6 +34,15 @@ add_setup(async () => { // `lastFetchTimeMs` is expected to be `fetchDelayAfterComingOnlineMs`, we can // be sure the value actually came from `fetchDelayAfterComingOnlineMs`. QuickSuggest.weather._test_fetchDelayAfterComingOnlineMs = 53; + + // When `add_tasks_with_rust()` disables the Rust backend and forces sync, the + // JS backend will sync `Weather` with remote settings. Since keywords are + // present in remote settings at that point (we added them above), `Weather` + // will then start fetching. The fetch may or may not be done before our test + // task starts. To make sure it's done, queue another fetch and await it. + registerAddTasksWithRustSetup(async () => { + await QuickSuggest.weather._test_fetch(); + }); }); // The feature should be properly uninitialized when it's disabled and then @@ -52,17 +61,15 @@ add_tasks_with_rust(async function disableAndEnable_suggestPref() { async function doBasicDisableAndEnableTest(pref) { // Sanity check initial state. - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); // Disable the feature. It should be immediately uninitialized. UrlbarPrefs.set(pref, false); assertDisabled({ message: "After disabling", - pendingFetchCount: 0, }); // No suggestion should be returned for a search. @@ -83,19 +90,17 @@ async function doBasicDisableAndEnableTest(pref) { // Re-enable the feature. It should be immediately initialized and a fetch // should start. info("Re-enable the feature"); - let fetchPromise = QuickSuggest.weather.waitForFetches(); + let fetchPromise = waitForNewWeatherFetch(); UrlbarPrefs.set(pref, true); - assertEnabled({ + await assertEnabled({ message: "Immediately after re-enabling", hasSuggestion: false, - pendingFetchCount: 1, }); await fetchPromise; - assertEnabled({ + await assertEnabled({ message: "After awaiting fetch", hasSuggestion: true, - pendingFetchCount: 0, }); Assert.equal( @@ -126,16 +131,15 @@ async function doBasicDisableAndEnableTest(pref) { // This task is only appropriate for the JS backend, not Rust, since fetching is // always active with Rust. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function keywordsNotDefined() { // Sanity check initial state. - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); // Set RS data without any keywords. Fetching should immediately stop. @@ -147,7 +151,6 @@ add_task( ]); assertDisabled({ message: "After setting RS data without keywords", - pendingFetchCount: 0, }); // No suggestion should be returned for a search. @@ -162,24 +165,22 @@ add_task( // Set keywords. Fetching should immediately start. info("Setting keywords"); - let fetchPromise = QuickSuggest.weather.waitForFetches(); + let fetchPromise = waitForNewWeatherFetch(); await QuickSuggestTestUtils.setRemoteSettingsRecords([ { type: "weather", weather: MerinoTestUtils.WEATHER_RS_DATA, }, ]); - assertEnabled({ + await assertEnabled({ message: "Immediately after setting keywords", hasSuggestion: false, - pendingFetchCount: 1, }); await fetchPromise; - assertEnabled({ + await assertEnabled({ message: "After awaiting fetch", hasSuggestion: true, - pendingFetchCount: 0, }); Assert.equal( @@ -211,27 +212,24 @@ add_task( // it should be discarded since the feature is disabled. add_tasks_with_rust(async function disableAndEnable_immediate1() { // Sanity check initial state. - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); // Disable the feature. It should be immediately uninitialized. UrlbarPrefs.set("weather.featureGate", false); assertDisabled({ message: "After disabling", - pendingFetchCount: 0, }); // Re-enable the feature. It should be immediately initialized and a fetch // should start. - let fetchPromise = QuickSuggest.weather.waitForFetches(); + let fetchPromise = waitForNewWeatherFetch(); UrlbarPrefs.set("weather.featureGate", true); - assertEnabled({ + await assertEnabled({ message: "Immediately after re-enabling", hasSuggestion: false, - pendingFetchCount: 1, }); // Disable it again. The fetch will remain ongoing since pending fetches @@ -239,7 +237,6 @@ add_tasks_with_rust(async function disableAndEnable_immediate1() { UrlbarPrefs.set("weather.featureGate", false); assertDisabled({ message: "After disabling again", - pendingFetchCount: 1, }); // Wait for the fetch to finish. @@ -249,21 +246,19 @@ add_tasks_with_rust(async function disableAndEnable_immediate1() { // uninitialized. assertDisabled({ message: "After awaiting fetch", - pendingFetchCount: 0, }); // Clean up by re-enabling the feature for the remaining tasks. - fetchPromise = QuickSuggest.weather.waitForFetches(); + fetchPromise = waitForNewWeatherFetch(); UrlbarPrefs.set("weather.featureGate", true); await fetchPromise; // Wait for keywords to be re-synced from remote settings. await QuickSuggestTestUtils.forceSync(); - assertEnabled({ + await assertEnabled({ message: "On cleanup", hasSuggestion: true, - pendingFetchCount: 0, }); }); @@ -279,26 +274,23 @@ add_tasks_with_rust(async function disableAndEnable_immediate1() { // from step 2 should be discarded. add_tasks_with_rust(async function disableAndEnable_immediate2() { // Sanity check initial state. - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); // Disable the feature. It should be immediately uninitialized. UrlbarPrefs.set("weather.featureGate", false); assertDisabled({ message: "After disabling", - pendingFetchCount: 0, }); // Re-enable the feature. It should be immediately initialized and a fetch // should start. UrlbarPrefs.set("weather.featureGate", true); - assertEnabled({ + await assertEnabled({ message: "Immediately after re-enabling", hasSuggestion: false, - pendingFetchCount: 1, }); // Disable it again. The fetch will remain ongoing since pending fetches @@ -306,25 +298,21 @@ add_tasks_with_rust(async function disableAndEnable_immediate2() { UrlbarPrefs.set("weather.featureGate", false); assertDisabled({ message: "After disabling again", - pendingFetchCount: 1, }); - // Re-enable it. A new fetch should start, so now there will be two pending - // fetches. - let fetchPromise = QuickSuggest.weather.waitForFetches(); + // Re-enable it. A new fetch should start. + let fetchPromise = waitForNewWeatherFetch(); UrlbarPrefs.set("weather.featureGate", true); - assertEnabled({ + await assertEnabled({ message: "Immediately after re-enabling again", hasSuggestion: false, - pendingFetchCount: 2, }); - // Wait for both fetches to finish. + // Wait for it to finish. await fetchPromise; - assertEnabled({ + await assertEnabled({ message: "Immediately after re-enabling again", hasSuggestion: true, - pendingFetchCount: 0, }); // Wait for keywords to be re-synced from remote settings. @@ -334,10 +322,9 @@ add_tasks_with_rust(async function disableAndEnable_immediate2() { // A fetch that doesn't return a suggestion should cause the last-fetched // suggestion to be discarded. add_tasks_with_rust(async function noSuggestion() { - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); let histograms = MerinoTestUtils.getAndClearHistograms({ @@ -350,10 +337,9 @@ add_tasks_with_rust(async function noSuggestion() { await QuickSuggest.weather._test_fetch(); - assertEnabled({ + await assertEnabled({ message: "After fetch", hasSuggestion: false, - pendingFetchCount: 0, }); Assert.equal( QuickSuggest.weather._test_merino.lastFetchStatus, @@ -381,19 +367,17 @@ add_tasks_with_rust(async function noSuggestion() { // Clean up by forcing another fetch so the suggestion is non-null for the // remaining tasks. await QuickSuggest.weather._test_fetch(); - assertEnabled({ + await assertEnabled({ message: "On cleanup", hasSuggestion: true, - pendingFetchCount: 0, }); }); // A network error should cause the last-fetched suggestion to be discarded. add_tasks_with_rust(async function networkError() { - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); let histograms = MerinoTestUtils.getAndClearHistograms({ @@ -411,10 +395,9 @@ add_tasks_with_rust(async function networkError() { QuickSuggest.weather._test_setTimeoutMs(-1); - assertEnabled({ + await assertEnabled({ message: "After fetch", hasSuggestion: false, - pendingFetchCount: 0, }); Assert.equal( QuickSuggest.weather._test_merino.lastFetchStatus, @@ -440,19 +423,17 @@ add_tasks_with_rust(async function networkError() { // Clean up by forcing another fetch so the suggestion is non-null for the // remaining tasks. await QuickSuggest.weather._test_fetch(); - assertEnabled({ + await assertEnabled({ message: "On cleanup", hasSuggestion: true, - pendingFetchCount: 0, }); }); // An HTTP error should cause the last-fetched suggestion to be discarded. add_tasks_with_rust(async function httpError() { - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); let histograms = MerinoTestUtils.getAndClearHistograms({ @@ -463,10 +444,9 @@ add_tasks_with_rust(async function httpError() { MerinoTestUtils.server.response = { status: 500 }; await QuickSuggest.weather._test_fetch(); - assertEnabled({ + await assertEnabled({ message: "After fetch", hasSuggestion: false, - pendingFetchCount: 0, }); Assert.equal( QuickSuggest.weather._test_merino.lastFetchStatus, @@ -494,20 +474,18 @@ add_tasks_with_rust(async function httpError() { MerinoTestUtils.server.reset(); MerinoTestUtils.server.response.body.suggestions = [WEATHER_SUGGESTION]; await QuickSuggest.weather._test_fetch(); - assertEnabled({ + await assertEnabled({ message: "On cleanup", hasSuggestion: true, - pendingFetchCount: 0, }); }); // A fetch that doesn't return a suggestion due to a client timeout should cause // the last-fetched suggestion to be discarded. add_tasks_with_rust(async function clientTimeout() { - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); let histograms = MerinoTestUtils.getAndClearHistograms({ @@ -528,10 +506,9 @@ add_tasks_with_rust(async function clientTimeout() { await QuickSuggest.weather._test_fetch(); - assertEnabled({ + await assertEnabled({ message: "After fetch", hasSuggestion: false, - pendingFetchCount: 0, }); Assert.equal( QuickSuggest.weather._test_merino.lastFetchStatus, @@ -573,10 +550,9 @@ add_tasks_with_rust(async function clientTimeout() { // Clean up by forcing another fetch so the suggestion is non-null for the // remaining tasks. await QuickSuggest.weather._test_fetch(); - assertEnabled({ + await assertEnabled({ message: "On cleanup", hasSuggestion: true, - pendingFetchCount: 0, }); }); @@ -662,10 +638,9 @@ async function doLocaleTest({ shouldRunTask, osUnit, unitsByLocale }) { return; } - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); // Sanity check initial locale info. @@ -716,10 +691,9 @@ async function doLocaleTest({ shouldRunTask, osUnit, unitsByLocale }) { // Blocks a result and makes sure the weather pref is disabled. add_tasks_with_rust(async function block() { // Sanity check initial state. - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); Assert.ok( UrlbarPrefs.get("suggest.weather"), @@ -775,17 +749,16 @@ add_tasks_with_rust(async function block() { }); // Re-enable the pref and clean up. - let fetchPromise = QuickSuggest.weather.waitForFetches(); + let fetchPromise = waitForNewWeatherFetch(); UrlbarPrefs.set("suggest.weather", true); await fetchPromise; // Wait for keywords to be re-synced from remote settings. await QuickSuggestTestUtils.forceSync(); - assertEnabled({ + await assertEnabled({ message: "On cleanup", hasSuggestion: true, - pendingFetchCount: 0, }); }); @@ -849,15 +822,11 @@ async function doWakeTest({ // Advance the clock and simulate wake. info("Sending wake notification"); + let fetchPromise = waitForNewWeatherFetch(); let nowOnWake = nowOnStart + sleepIntervalMs; dateNowStub.returns(nowOnWake); QuickSuggest.weather.observe(null, "wake_notification", ""); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 0, - "After wake, next fetch should not have immediately started" - ); Assert.equal( QuickSuggest.weather._test_lastFetchTimeMs, nowOnStart, @@ -891,18 +860,13 @@ async function doWakeTest({ // Wait for the fetch. If the wake didn't trigger it, then the caller should // have passed in a `sleepIntervalMs` that will make it start soon. info("Waiting for fetch after wake"); - await QuickSuggest.weather.waitForFetches(); + await fetchPromise; Assert.equal( QuickSuggest.weather._test_fetchTimerMs, QuickSuggest.weather._test_fetchIntervalMs, "After post-wake fetch, timer period should remain full fetch interval" ); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 0, - "After post-wake fetch, no more fetches should be pending" - ); dateNowStub.restore(); } @@ -957,11 +921,6 @@ async function doOnlineTestWithSuggestion({ topic, dataValues }) { info("Sending notification: " + JSON.stringify({ topic, data })); QuickSuggest.weather.observe(null, topic, data); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 0, - "Fetch should not have started" - ); Assert.equal( QuickSuggest.weather._test_fetchTimer, timer, @@ -1032,11 +991,6 @@ async function doOnlineTestWithNullSuggestion({ !QuickSuggest.weather.suggestion, "Suggestion should remain null" ); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 0, - "Fetch should not have started" - ); Assert.equal( QuickSuggest.weather._test_fetchTimer, timer, @@ -1055,13 +1009,9 @@ async function doOnlineTestWithNullSuggestion({ Assert.ok(!QuickSuggest.weather.suggestion, "Suggestion should be null"); info("Sending notification: " + JSON.stringify({ topic, data })); + let fetchPromise = waitForNewWeatherFetch(); QuickSuggest.weather.observe(null, topic, data); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 0, - "Fetch should not have started yet" - ); Assert.notEqual( QuickSuggest.weather._test_fetchTimer, 0, @@ -1081,13 +1031,8 @@ async function doOnlineTestWithNullSuggestion({ timer = QuickSuggest.weather._test_fetchTimer; info("Waiting for fetch after notification"); - await QuickSuggest.weather.waitForFetches(); + await fetchPromise; - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 0, - "Fetch should not be pending" - ); Assert.notEqual( QuickSuggest.weather._test_fetchTimer, 0, @@ -1164,20 +1109,23 @@ async function doManyNotificationsTest(notifications) { MerinoTestUtils.WEATHER_SUGGESTION, ]; + let { fetchPromise: oldFetchPromise } = QuickSuggest.weather; + let fetchPromise = waitForNewWeatherFetch(); + // Send the notifications. for (let [topic, data] of notifications) { info("Sending notification: " + JSON.stringify({ topic, data })); QuickSuggest.weather.observe(null, topic, data); + Assert.equal( + QuickSuggest.weather.fetchPromise, + oldFetchPromise, + "No new fetch should have started yet" + ); } info("Waiting for fetch after notifications"); - await QuickSuggest.weather.waitForFetches(); + await fetchPromise; - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 0, - "Fetch should not be pending" - ); Assert.notEqual( QuickSuggest.weather._test_fetchTimer, 0, @@ -1241,7 +1189,7 @@ add_tasks_with_rust(async function vpn() { // Simulate the link status changing. Since the mock link service still // indicates a VPN is detected, the suggestion should remain null. - let fetchPromise = QuickSuggest.weather.waitForFetches(); + let fetchPromise = waitForNewWeatherFetch(); QuickSuggest.weather.observe(null, "network:link-status-changed", "changed"); await fetchPromise; Assert.ok(!QuickSuggest.weather.suggestion, "Suggestion should remain null"); @@ -1251,7 +1199,7 @@ add_tasks_with_rust(async function vpn() { Ci.nsINetworkLinkService.NONE_DETECTED; // Simulate the link status changing again. The suggestion should be fetched. - fetchPromise = QuickSuggest.weather.waitForFetches(); + fetchPromise = waitForNewWeatherFetch(); QuickSuggest.weather.observe(null, "network:link-status-changed", "changed"); await fetchPromise; Assert.ok(QuickSuggest.weather.suggestion, "Suggestion should be fetched"); @@ -1264,10 +1212,9 @@ add_tasks_with_rust(async function vpn() { // weather record. add_tasks_with_rust(async function nimbusOverride() { // Sanity check initial state. - assertEnabled({ + await assertEnabled({ message: "Sanity check initial state", hasSuggestion: true, - pendingFetchCount: 0, }); let defaultResult = makeWeatherResult(); @@ -1349,7 +1296,7 @@ add_tasks_with_rust(async function nimbusOverride() { }); }); -function assertEnabled({ message, hasSuggestion, pendingFetchCount }) { +async function assertEnabled({ message, hasSuggestion }) { info("Asserting feature is enabled"); if (message) { info(message); @@ -1360,20 +1307,20 @@ function assertEnabled({ message, hasSuggestion, pendingFetchCount }) { hasSuggestion, "Suggestion is null or non-null as expected" ); + Assert.ok(QuickSuggest.weather._test_merino, "Merino client is non-null"); + + await TestUtils.waitForCondition( + () => QuickSuggest.weather._test_fetchTimer, + "Waiting for fetch timer to become non-zero" + ); Assert.notEqual( QuickSuggest.weather._test_fetchTimer, 0, "Fetch timer is non-zero" ); - Assert.ok(QuickSuggest.weather._test_merino, "Merino client is non-null"); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - pendingFetchCount, - "Expected pending fetch count" - ); } -function assertDisabled({ message, pendingFetchCount }) { +function assertDisabled({ message }) { info("Asserting feature is disabled"); if (message) { info(message); @@ -1394,9 +1341,4 @@ function assertDisabled({ message, pendingFetchCount }) { null, "Merino client is null" ); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - pendingFetchCount, - "Expected pending fetch count" - ); } diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js b/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js index efa5922c3e..559e0cc1fa 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js +++ b/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js @@ -23,6 +23,15 @@ add_setup(async () => { prefs: [["suggest.quicksuggest.nonsponsored", true]], }); await MerinoTestUtils.initWeather(); + + // When `add_tasks_with_rust()` disables the Rust backend and forces sync, the + // JS backend will sync `Weather` with remote settings. Since keywords are + // present in remote settings at that point (we added them above), `Weather` + // will then start fetching. The fetch may or may not be done before our test + // task starts. To make sure it's done, queue another fetch and await it. + registerAddTasksWithRustSetup(async () => { + await QuickSuggest.weather._test_fetch(); + }); }); // * Settings data: none @@ -89,9 +98,9 @@ add_tasks_with_rust(async function () { // // JS backend only. The Rust component expects settings data to contain // min_keyword_length. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function () { await doKeywordsTest({ @@ -128,9 +137,9 @@ add_task( // // JS backend only. The Rust component doesn't treat minKeywordLength == 0 as a // special case. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function () { await doKeywordsTest({ @@ -296,9 +305,9 @@ add_tasks_with_rust(async function () { // // JS backend only. The Rust component expects settings data to contain // min_keyword_length. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function () { await doKeywordsTest({ @@ -338,9 +347,9 @@ add_task( // // JS backend only. The Rust component doesn't treat minKeywordLength == 0 as a // special case. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function () { await doKeywordsTest({ @@ -578,9 +587,9 @@ add_tasks_with_rust(async function () { // TODO bug 1879209: This doesn't work with the Rust backend because if // min_keyword_length isn't specified on ingest, the Rust database will retain // the last known good min_keyword_length, which interferes with this task. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function () { await doKeywordsTest({ @@ -618,9 +627,9 @@ add_task( // TODO bug 1879209: This doesn't work with the Rust backend because if // min_keyword_length isn't specified on ingest, the Rust database will retain // the last known good min_keyword_length, which interferes with this task. -add_task( +add_tasks_with_rust( { - skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"), + skip_if_rust_enabled: true, }, async function () { await doKeywordsTest({ @@ -817,7 +826,7 @@ async function doKeywordsTest({ !UrlbarPrefs.get("quickSuggestRustEnabled") && (nimbusValues?.weatherKeywords || settingsData?.keywords) ) { - fetchPromise = QuickSuggest.weather.waitForFetches(); + fetchPromise = waitForNewWeatherFetch(); } let nimbusCleanup; @@ -838,7 +847,6 @@ async function doKeywordsTest({ if (fetchPromise) { info("Waiting for fetch"); - assertFetchingStarted({ pendingFetchCount: 1 }); await fetchPromise; info("Got fetch"); } @@ -872,10 +880,10 @@ async function doKeywordsTest({ await nimbusCleanup?.(); - fetchPromise = null; if (!QuickSuggest.weather.suggestion) { - fetchPromise = QuickSuggest.weather.waitForFetches(); + fetchPromise = waitForNewWeatherFetch(); } + await QuickSuggestTestUtils.setRemoteSettingsRecords([ { type: "weather", @@ -905,28 +913,8 @@ async function doMatchingQuickSuggestTest(pref, isSponsored) { let keyword = "test"; let attachment = isSponsored - ? { - id: 1, - url: "http://example.com/amp", - title: "AMP Suggestion", - keywords: [keyword], - click_url: "http://example.com/amp-click", - impression_url: "http://example.com/amp-impression", - advertiser: "Amp", - iab_category: "22 - Shopping", - icon: "1234", - } - : { - id: 2, - url: "http://example.com/wikipedia", - title: "Wikipedia Suggestion", - keywords: [keyword], - click_url: "http://example.com/wikipedia-click", - impression_url: "http://example.com/wikipedia-impression", - advertiser: "Wikipedia", - iab_category: "5 - Education", - icon: "1234", - }; + ? QuickSuggestTestUtils.ampRemoteSettings({ keywords: [keyword] }) + : QuickSuggestTestUtils.wikipediaRemoteSettings({ keywords: [keyword] }); // Add a remote settings result to quick suggest. let oldPrefValue = UrlbarPrefs.get(pref); @@ -943,27 +931,6 @@ async function doMatchingQuickSuggestTest(pref, isSponsored) { ]); // First do a search to verify the quick suggest result matches the keyword. - let payload; - if (!UrlbarPrefs.get("quickSuggestRustEnabled")) { - payload = { - source: "remote-settings", - provider: "AdmWikipedia", - sponsoredImpressionUrl: attachment.impression_url, - sponsoredClickUrl: attachment.click_url, - sponsoredBlockId: attachment.id, - }; - } else { - payload = { - source: "rust", - provider: isSponsored ? "Amp" : "Wikipedia", - }; - if (isSponsored) { - payload.sponsoredImpressionUrl = attachment.impression_url; - payload.sponsoredClickUrl = attachment.click_url; - payload.sponsoredBlockId = attachment.id; - } - } - info("Doing first search for quick suggest result"); await check_results({ context: createContext(keyword, { @@ -971,35 +938,9 @@ async function doMatchingQuickSuggestTest(pref, isSponsored) { isPrivate: false, }), matches: [ - { - type: UrlbarUtils.RESULT_TYPE.URL, - source: UrlbarUtils.RESULT_SOURCE.SEARCH, - heuristic: false, - payload: { - ...payload, - telemetryType: isSponsored ? "adm_sponsored" : "adm_nonsponsored", - qsSuggestion: keyword, - title: attachment.title, - url: attachment.url, - displayUrl: attachment.url.replace(/[/]$/, ""), - originalUrl: attachment.url, - icon: null, - sponsoredAdvertiser: attachment.advertiser, - sponsoredIabCategory: attachment.iab_category, - isSponsored, - descriptionL10n: isSponsored - ? { id: "urlbar-result-action-sponsored" } - : undefined, - helpUrl: QuickSuggest.HELP_URL, - helpL10n: { - id: "urlbar-result-menu-learn-more-about-firefox-suggest", - }, - isBlockable: true, - blockL10n: { - id: "urlbar-result-menu-dismiss-firefox-suggest", - }, - }, - }, + isSponsored + ? makeAmpResult({ keyword }) + : makeWikipediaResult({ keyword }), ], }); @@ -1398,7 +1339,7 @@ async function doIncrementTest({ !UrlbarPrefs.get("quickSuggestRustEnabled") && (nimbusValues?.weatherKeywords || settingsData?.weather?.keywords) ) { - fetchPromise = QuickSuggest.weather.waitForFetches(); + fetchPromise = waitForNewWeatherFetch(); } let nimbusCleanup; @@ -1419,7 +1360,6 @@ async function doIncrementTest({ if (fetchPromise) { info("Waiting for fetch"); - assertFetchingStarted({ pendingFetchCount: 1 }); await fetchPromise; info("Got fetch"); } @@ -1472,9 +1412,8 @@ async function doIncrementTest({ await nimbusCleanup?.(); - fetchPromise = null; if (!QuickSuggest.weather.suggestion) { - fetchPromise = QuickSuggest.weather.waitForFetches(); + fetchPromise = waitForNewWeatherFetch(); } await QuickSuggestTestUtils.setRemoteSettingsRecords([ { @@ -1485,19 +1424,3 @@ async function doIncrementTest({ UrlbarPrefs.clear("weather.minKeywordLength"); await fetchPromise; } - -function assertFetchingStarted() { - info("Asserting fetching has started"); - - Assert.notEqual( - QuickSuggest.weather._test_fetchTimer, - 0, - "Fetch timer is non-zero" - ); - Assert.ok(QuickSuggest.weather._test_merino, "Merino client is non-null"); - Assert.equal( - QuickSuggest.weather._test_pendingFetchCount, - 1, - "Expected pending fetch count" - ); -} diff --git a/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml b/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml index ceab478795..1f0e226684 100644 --- a/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml +++ b/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml @@ -49,3 +49,4 @@ skip-if = ["true"] # Bug 1880214 ["test_weather.js"] ["test_weather_keywords.js"] +skip-if = ["verify"] # Bug 1880214 - Takes a very long time due to add_tasks_with_rust() diff --git a/browser/components/urlbar/tests/unit/head.js b/browser/components/urlbar/tests/unit/head.js index 6f78608c94..da96d5704f 100644 --- a/browser/components/urlbar/tests/unit/head.js +++ b/browser/components/urlbar/tests/unit/head.js @@ -1109,26 +1109,6 @@ async function getOriginFrecency(prefix, aHost) { return rows[0].getResultByIndex(0); } -/** - * Returns the origin frecency stats. - * - * @returns {object} - * An object { count, sum, squares }. - */ -async function getOriginFrecencyStats() { - let db = await PlacesUtils.promiseDBConnection(); - let rows = await db.execute(` - SELECT - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_count'), 0), - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum'), 0), - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum_of_squares'), 0) - `); - let count = rows[0].getResultByIndex(0); - let sum = rows[0].getResultByIndex(1); - let squares = rows[0].getResultByIndex(2); - return { count, sum, squares }; -} - /** * Returns the origin autofill frecency threshold. * @@ -1136,18 +1116,7 @@ async function getOriginFrecencyStats() { * The threshold. */ async function getOriginAutofillThreshold() { - let { count, sum, squares } = await getOriginFrecencyStats(); - if (!count) { - return 0; - } - if (count == 1) { - return sum; - } - let stddevMultiplier = UrlbarPrefs.get("autoFill.stddevMultiplier"); - return ( - sum / count + - stddevMultiplier * Math.sqrt((squares - (sum * sum) / count) / count) - ); + return PlacesUtils.metadata.get("origin_frecency_threshold", 2.0); } /** diff --git a/browser/components/urlbar/tests/unit/test_UrlbarPrefs.js b/browser/components/urlbar/tests/unit/test_UrlbarPrefs.js index d30739f03e..7fb3256f6c 100644 --- a/browser/components/urlbar/tests/unit/test_UrlbarPrefs.js +++ b/browser/components/urlbar/tests/unit/test_UrlbarPrefs.js @@ -363,10 +363,10 @@ add_task(async function onNimbusChanged() { // Add an observer that throws an Error and an observer that does not define // anything to check whether the other observers can get notifications. UrlbarPrefs.addObserver({ - onPrefChanged(pref) { + onPrefChanged() { throw new Error("From onPrefChanged"); }, - onNimbusChanged(pref) { + onNimbusChanged() { throw new Error("From onNimbusChanged"); }, }); @@ -407,10 +407,10 @@ add_task(async function onPrefChanged() { // Add an observer that throws an Error and an observer that does not define // anything to check whether the other observers can get notifications. UrlbarPrefs.addObserver({ - onPrefChanged(pref) { + onPrefChanged() { throw new Error("From onPrefChanged"); }, - onNimbusChanged(pref) { + onNimbusChanged() { throw new Error("From onNimbusChanged"); }, }); diff --git a/browser/components/urlbar/tests/unit/test_UrlbarSearchUtils.js b/browser/components/urlbar/tests/unit/test_UrlbarSearchUtils.js index fe33228007..28cbd381f1 100644 --- a/browser/components/urlbar/tests/unit/test_UrlbarSearchUtils.js +++ b/browser/components/urlbar/tests/unit/test_UrlbarSearchUtils.js @@ -65,14 +65,10 @@ add_task(async function onlyEnabled_option_nomatch() { let domain = engine.searchUrlDomain; let token = domain.substr(0, 1); engine.hideOneOffButton = true; - let matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix(token, { - onlyEnabled: true, - }); + let matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix(token); Assert.notEqual(matchedEngines[0].searchUrlDomain, domain); engine.hideOneOffButton = false; - matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix(token, { - onlyEnabled: true, - }); + matchedEngines = await UrlbarSearchUtils.enginesForDomainPrefix(token); Assert.equal(matchedEngines[0].searchUrlDomain, domain); }); @@ -95,7 +91,7 @@ add_task(async function add_search_engine_match() { Assert.ok(matchedEngine); Assert.equal(matchedEngine.searchForm, "https://www.bacon.moz"); Assert.equal(matchedEngine.name, "bacon"); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); info("also type part of the public suffix"); matchedEngine = ( await UrlbarSearchUtils.enginesForDomainPrefix("bacon.m") @@ -103,7 +99,7 @@ add_task(async function add_search_engine_match() { Assert.ok(matchedEngine); Assert.equal(matchedEngine.searchForm, "https://www.bacon.moz"); Assert.equal(matchedEngine.name, "bacon"); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); }); add_task(async function match_multiple_search_engines() { @@ -134,19 +130,19 @@ add_task(async function test_aliased_search_engine_match() { Assert.ok(matchedEngine); Assert.equal(matchedEngine.name, "bacon"); Assert.ok(matchedEngine.aliases.includes("pork")); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); // Upper case matchedEngine = await UrlbarSearchUtils.engineForAlias("PORK"); Assert.ok(matchedEngine); Assert.equal(matchedEngine.name, "bacon"); Assert.ok(matchedEngine.aliases.includes("pork")); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); // Cap case matchedEngine = await UrlbarSearchUtils.engineForAlias("Pork"); Assert.ok(matchedEngine); Assert.equal(matchedEngine.name, "bacon"); Assert.ok(matchedEngine.aliases.includes("pork")); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); }); add_task(async function test_aliased_search_engine_match_upper_case_alias() { @@ -164,19 +160,19 @@ add_task(async function test_aliased_search_engine_match_upper_case_alias() { Assert.ok(matchedEngine); Assert.equal(matchedEngine.name, "patch"); Assert.ok(matchedEngine.aliases.includes("PR")); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); // Upper case matchedEngine = await UrlbarSearchUtils.engineForAlias("PR"); Assert.ok(matchedEngine); Assert.equal(matchedEngine.name, "patch"); Assert.ok(matchedEngine.aliases.includes("PR")); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); // Cap case matchedEngine = await UrlbarSearchUtils.engineForAlias("Pr"); Assert.ok(matchedEngine); Assert.equal(matchedEngine.name, "patch"); Assert.ok(matchedEngine.aliases.includes("PR")); - Assert.equal(matchedEngine.getIconURL(), null); + Assert.equal(await matchedEngine.getIconURL(), null); }); add_task(async function remove_search_engine_nomatch() { diff --git a/browser/components/urlbar/tests/unit/test_about_urls.js b/browser/components/urlbar/tests/unit/test_about_urls.js index 277ddb8ee1..82a8ef2750 100644 --- a/browser/components/urlbar/tests/unit/test_about_urls.js +++ b/browser/components/urlbar/tests/unit/test_about_urls.js @@ -76,8 +76,10 @@ add_task(async function aboutAboutAndAboutAddons() { heuristic: true, }), makeVisitResult(context, { + source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, uri: "about:addons", title: "about:addons", + iconUri: "page-icon:about:addons", tags: null, providerName: "AboutPages", }), @@ -93,8 +95,10 @@ add_task(async function aboutColonMatchesOnlyAboutPages() { const aboutPageNames = AboutPagesUtils.visibleAboutUrls.slice(0, 9); const aboutPageResults = aboutPageNames.map(aboutPageName => { return makeVisitResult(context, { + source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, uri: aboutPageName, title: aboutPageName, + iconUri: "page-icon:" + aboutPageName, tags: null, providerName: "AboutPages", }); @@ -165,8 +169,10 @@ add_task(async function after_general() { title: "Guide to about:addons in Firefox", }), makeVisitResult(context, { + source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, uri: "about:addons", title: "about:addons", + iconUri: "page-icon:about:addons", tags: null, providerName: "AboutPages", }), diff --git a/browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js b/browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js index 05e3a230f1..7164ae8911 100644 --- a/browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js +++ b/browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js @@ -893,8 +893,11 @@ add_autofill_task(async function bookmarkBelowThreshold() { await cleanup(); }); -// Bookmarked places should be autofilled when they *do* meet the threshold. +// Bookmarked places should be autofilled also when they meet the threshold. add_autofill_task(async function bookmarkAboveThreshold() { + // Add a visit to the URL, otherwise origin frecency will be too small, note + // it would be filled anyway as bookmarks are always filled. + await PlacesTestUtils.addVisits(["http://" + url]); // Bookmark a URL. await PlacesTestUtils.addBookmarkWithDetails({ uri: "http://" + url, @@ -957,13 +960,10 @@ add_autofill_task(async function zeroThreshold() { ); Assert.equal(placeFrecency, -1); - // Make sure the origin's frecency is 0. let originFrecency = await getOriginFrecency("http://", host); - Assert.equal(originFrecency, 0); - - // Make sure the autofill threshold is 0. + Assert.equal(originFrecency, 1, "Check expected origin's frecency"); let threshold = await getOriginAutofillThreshold(); - Assert.equal(threshold, 0); + Assert.equal(threshold, 1, "Check expected origins threshold"); let context = createContext(search, { isPrivate: false }); await check_results({ diff --git a/browser/components/urlbar/tests/unit/test_heuristic_cancel.js b/browser/components/urlbar/tests/unit/test_heuristic_cancel.js index 6f6f2fbd8a..a78004f2bd 100644 --- a/browser/components/urlbar/tests/unit/test_heuristic_cancel.js +++ b/browser/components/urlbar/tests/unit/test_heuristic_cancel.js @@ -126,7 +126,7 @@ add_task(async function timerIsCancelled() { // Then they will be queued up in a _heuristicProvidersTimer, waiting for // the results from SlowProvider. let resultsAddedPromise = new Promise(resolve => { - let observe = async (subject, topic, data) => { + let observe = async () => { Services.obs.removeObserver(observe, "results-added"); // Fire the second query to cancel the first. await controller.startQuery(secondContext); diff --git a/browser/components/urlbar/tests/unit/test_hideSponsoredHistory.js b/browser/components/urlbar/tests/unit/test_hideSponsoredHistory.js index d49aaf2fb7..79d3e3b17c 100644 --- a/browser/components/urlbar/tests/unit/test_hideSponsoredHistory.js +++ b/browser/components/urlbar/tests/unit/test_hideSponsoredHistory.js @@ -78,7 +78,7 @@ add_task(async function test() { makeSearchResult(context, { heuristic: true, engineName: engine.name, - engineIconUri: engine.getIconURL(), + engineIconUri: await engine.getIconURL(), }), ]; if (shouldAppear) { diff --git a/browser/components/urlbar/tests/unit/test_match_javascript.js b/browser/components/urlbar/tests/unit/test_match_javascript.js index 3d3eab19ba..bba0af1376 100644 --- a/browser/components/urlbar/tests/unit/test_match_javascript.js +++ b/browser/components/urlbar/tests/unit/test_match_javascript.js @@ -32,7 +32,10 @@ add_task(async function test_javascript_match() { await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); info("Match non-javascript: with plain search"); - let context = createContext("a", { isPrivate: false }); + let context = createContext("a", { + isPrivate: false, + allowAutofill: false /* avoid autofilling abc, as it's not necessary */, + }); await check_results({ context, matches: [ diff --git a/browser/components/urlbar/tests/unit/test_providerHistoryUrlHeuristic.js b/browser/components/urlbar/tests/unit/test_providerHistoryUrlHeuristic.js index 7eb62fbeea..8cf643393f 100644 --- a/browser/components/urlbar/tests/unit/test_providerHistoryUrlHeuristic.js +++ b/browser/components/urlbar/tests/unit/test_providerHistoryUrlHeuristic.js @@ -185,8 +185,10 @@ add_task(async function test_unsupported_protocol() { title: "Robots!", }), makeVisitResult(context, { + source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, uri: "about:robots", title: "about:robots", + iconUri: "page-icon:about:robots", tags: null, providerName: "AboutPages", }), diff --git a/browser/components/urlbar/tests/unit/test_providerOpenTabs.js b/browser/components/urlbar/tests/unit/test_providerOpenTabs.js index f85f547ac3..689ecf614f 100644 --- a/browser/components/urlbar/tests/unit/test_providerOpenTabs.js +++ b/browser/components/urlbar/tests/unit/test_providerOpenTabs.js @@ -3,23 +3,24 @@ "use strict"; +const userContextId1 = 3; +const userContextId2 = 5; +const url = "http://foo.mozilla.org/"; +const url2 = "http://foo2.mozilla.org/"; + add_task(async function test_openTabs() { - const userContextId1 = 3; - const userContextId2 = 5; - const url = "http://foo.mozilla.org/"; - const url2 = "http://foo2.mozilla.org/"; UrlbarProviderOpenTabs.registerOpenTab(url, userContextId1, false); UrlbarProviderOpenTabs.registerOpenTab(url, userContextId1, false); UrlbarProviderOpenTabs.registerOpenTab(url2, userContextId1, false); UrlbarProviderOpenTabs.registerOpenTab(url, userContextId2, false); Assert.deepEqual( [url, url2], - UrlbarProviderOpenTabs.getOpenTabs(userContextId1), + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(userContextId1), "Found all the expected tabs" ); Assert.deepEqual( [url], - UrlbarProviderOpenTabs.getOpenTabs(userContextId2), + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(userContextId2), "Found all the expected tabs" ); await PlacesUtils.promiseLargeCacheDBConnection(); @@ -37,13 +38,13 @@ add_task(async function test_openTabs() { await UrlbarProviderOpenTabs.unregisterOpenTab(url2, userContextId1, false); Assert.deepEqual( [url], - UrlbarProviderOpenTabs.getOpenTabs(userContextId1), + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(userContextId1), "Found all the expected tabs" ); await UrlbarProviderOpenTabs.unregisterOpenTab(url, userContextId1, false); Assert.deepEqual( [url], - UrlbarProviderOpenTabs.getOpenTabs(userContextId1), + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(userContextId1), "Found all the expected tabs" ); Assert.deepEqual( @@ -77,4 +78,86 @@ add_task(async function test_openTabs() { Assert.equal(matchCount, 2, "Found the expected number of matches"); // Sanity check that this doesn't throw. provider.cancelQuery(context); + await UrlbarProviderOpenTabs.unregisterOpenTab(url, userContextId1, false); + await UrlbarProviderOpenTabs.unregisterOpenTab(url, userContextId2, false); +}); + +add_task(async function test_openTabs_mixedtype_input() { + // Passing the userContextId as a string, rather than a number, is a fairly + // common mistake, check the API handles both properly. + Assert.deepEqual( + [], + UrlbarProviderOpenTabs.getOpenTabUrls(1), + "Found all the expected tabs" + ); + Assert.deepEqual( + [], + UrlbarProviderOpenTabs.getOpenTabUrls(2), + "Found all the expected tabs" + ); + UrlbarProviderOpenTabs.registerOpenTab(url, 1, false); + UrlbarProviderOpenTabs.registerOpenTab(url, "2", false); + Assert.deepEqual( + [url], + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(1), + "Found all the expected tabs" + ); + Assert.deepEqual( + [url], + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(2), + "Found all the expected tabs" + ); + Assert.deepEqual( + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(1), + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId("1"), + "Also check getOpenTabs adapts to the argument type" + ); + UrlbarProviderOpenTabs.unregisterOpenTab(url, "1", false); + UrlbarProviderOpenTabs.unregisterOpenTab(url, 2, false); + Assert.deepEqual( + [], + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(1), + "Found all the expected tabs" + ); + Assert.deepEqual( + [], + UrlbarProviderOpenTabs.getOpenTabUrlsForUserContextId(2), + "Found all the expected tabs" + ); +}); + +add_task(async function test_openTabs() { + Assert.equal( + 0, + UrlbarProviderOpenTabs.getOpenTabUrls().size, + "Check there's no open tabs" + ); + Assert.equal( + 0, + UrlbarProviderOpenTabs.getOpenTabUrls(true).size, + "Check there's no private open tabs" + ); + await UrlbarProviderOpenTabs.registerOpenTab(url, userContextId1, false); + await UrlbarProviderOpenTabs.registerOpenTab(url, userContextId2, false); + await UrlbarProviderOpenTabs.registerOpenTab(url2, 0, true); + Assert.equal( + 1, + UrlbarProviderOpenTabs.getOpenTabUrls().size, + "Check open tabs" + ); + Assert.deepEqual( + [userContextId1, userContextId2], + Array.from(UrlbarProviderOpenTabs.getOpenTabUrls().get(url)), + "Check the tab is in 2 userContextIds" + ); + Assert.equal( + 1, + UrlbarProviderOpenTabs.getOpenTabUrls(true).size, + "Check open private tabs" + ); + Assert.deepEqual( + [-1], + Array.from(UrlbarProviderOpenTabs.getOpenTabUrls(true).get(url2)), + "Check the tab is in the private userContextId" + ); }); diff --git a/browser/components/urlbar/tests/unit/test_providerTabToSearch.js b/browser/components/urlbar/tests/unit/test_providerTabToSearch.js index 0a8bfbead5..32bf450654 100644 --- a/browser/components/urlbar/tests/unit/test_providerTabToSearch.js +++ b/browser/components/urlbar/tests/unit/test_providerTabToSearch.js @@ -87,7 +87,7 @@ add_task(async function noAutofill() { matches: [ makeSearchResult(context, { engineName: Services.search.defaultEngine.name, - engineIconUri: Services.search.defaultEngine.getIconURL(), + engineIconUri: await Services.search.defaultEngine.getIconURL(), heuristic: true, providerName: "HeuristicFallback", }), @@ -423,7 +423,7 @@ add_task(async function test_publicSuffix() { matches: [ makeSearchResult(context, { engineName: Services.search.defaultEngine.name, - engineIconUri: Services.search.defaultEngine.getIconURL(), + engineIconUri: await Services.search.defaultEngine.getIconURL(), heuristic: true, providerName: "HeuristicFallback", }), diff --git a/browser/components/urlbar/tests/unit/test_providersManager_filtering.js b/browser/components/urlbar/tests/unit/test_providersManager_filtering.js index 094eb42437..4a1eb5c0ef 100644 --- a/browser/components/urlbar/tests/unit/test_providersManager_filtering.js +++ b/browser/components/urlbar/tests/unit/test_providersManager_filtering.js @@ -205,10 +205,10 @@ add_task(async function test_filter_queryContext() { get type() { return UrlbarUtils.PROVIDER_TYPE.PROFILE; } - isActive(context) { + isActive(_context) { return true; } - async startQuery(context, add) { + async startQuery(_context, _add) { Assert.ok(false, "Provider should no be invoked"); } } @@ -360,7 +360,7 @@ add_task(async function test_filter_priority() { super({ priority, name: `${priority}` + namePart }); this._shouldBeInvoked = shouldBeInvoked; } - async startQuery(context, add) { + async startQuery(_context, _add) { Assert.ok(this._shouldBeInvoked, `${this.name} was invoked`); } } diff --git a/browser/components/urlbar/tests/unit/test_remote_tabs.js b/browser/components/urlbar/tests/unit/test_remote_tabs.js index bb0e708162..a73721d7dc 100644 --- a/browser/components/urlbar/tests/unit/test_remote_tabs.js +++ b/browser/components/urlbar/tests/unit/test_remote_tabs.js @@ -28,7 +28,7 @@ let MockClientsEngine = { Assert.ok(guid.endsWith("desktop") || guid.endsWith("mobile")); return guid.endsWith("mobile") ? "phone" : "desktop"; }, - remoteClientExists(id) { + remoteClientExists(_id) { return true; }, getClientName(id) { @@ -662,7 +662,7 @@ add_task(async function test_duplicate_remote_tabs() { let url = "http://foo.remote.com/"; let tabs = Array(3) .fill(0) - .map((e, i) => ({ + .map(() => ({ urlHistory: [url], title: "A title", lastUsed: Math.floor(Date.now() / 1000), diff --git a/browser/components/urlbar/tests/unit/test_search_suggestions.js b/browser/components/urlbar/tests/unit/test_search_suggestions.js index dc7185149f..22f1ec7617 100644 --- a/browser/components/urlbar/tests/unit/test_search_suggestions.js +++ b/browser/components/urlbar/tests/unit/test_search_suggestions.js @@ -430,7 +430,7 @@ add_task(async function remoteSuggestionsDupeSearchString() { add_task(async function queryIsNotASubstring() { Services.prefs.setBoolPref(SUGGEST_PREF, true); - setSuggestionsFn(searchStr => { + setSuggestionsFn(() => { return ["aaa", "bbb"]; }); @@ -1550,7 +1550,7 @@ add_task(async function restrict_remote_suggestions_after_no_results() { // maxCharsForSearchSuggestions returns 0 results. We set it to 4 here to // avoid constructing a 100+ character string. Services.prefs.setIntPref("browser.urlbar.maxCharsForSearchSuggestions", 4); - setSuggestionsFn(searchStr => { + setSuggestionsFn(() => { return []; }); diff --git a/browser/components/urlbar/tests/unit/xpcshell.toml b/browser/components/urlbar/tests/unit/xpcshell.toml index 188f4390c7..b168d3b987 100644 --- a/browser/components/urlbar/tests/unit/xpcshell.toml +++ b/browser/components/urlbar/tests/unit/xpcshell.toml @@ -128,10 +128,6 @@ prefs = [ ["test_providerOmnibox.js"] ["test_providerOpenTabs.js"] -skip-if = [ - "os == 'mac' && debug", # Bug 1781972 - "os == 'win' && debug", # Bug 1781972 -] ["test_providerPlaces.js"] -- cgit v1.2.3