From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser/browser_quicksuggest_addons.js | 560 +++++++++++++++++++++ 1 file changed, 560 insertions(+) create mode 100644 browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_addons.js (limited to 'browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_addons.js') diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_addons.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_addons.js new file mode 100644 index 0000000000..e0b75d0e9b --- /dev/null +++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_addons.js @@ -0,0 +1,560 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test for addon suggestions. + +const TEST_MERINO_SUGGESTIONS = [ + { + provider: "amo", + icon: "https://example.com/first.svg", + url: "https://example.com/first-addon", + title: "First Addon", + description: "This is a first addon", + custom_details: { + amo: { + rating: "5", + number_of_ratings: "1234567", + guid: "first@addon", + }, + }, + is_top_pick: true, + }, + { + provider: "amo", + icon: "https://example.com/second.png", + url: "https://example.com/second-addon", + title: "Second Addon", + description: "This is a second addon", + custom_details: { + amo: { + rating: "4.5", + number_of_ratings: "123", + guid: "second@addon", + }, + }, + is_sponsored: true, + is_top_pick: false, + }, + { + provider: "amo", + icon: "https://example.com/third.svg", + url: "https://example.com/third-addon", + title: "Third Addon", + description: "This is a third addon", + custom_details: { + amo: { + rating: "0", + number_of_ratings: "0", + guid: "third@addon", + }, + }, + is_top_pick: false, + }, + { + provider: "amo", + icon: "https://example.com/fourth.svg", + url: "https://example.com/fourth-addon", + title: "Fourth Addon", + description: "This is a fourth addon", + custom_details: { + amo: { + rating: "4", + number_of_ratings: "4", + guid: "fourth@addon", + }, + }, + }, +]; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.quicksuggest.enabled", true], + ["browser.urlbar.quicksuggest.remoteSettings.enabled", false], + ["browser.urlbar.bestMatch.enabled", true], + ], + }); + + await SearchTestUtils.installSearchExtension({}, { setAsDefault: true }); + + await QuickSuggestTestUtils.ensureQuickSuggestInit({ + merinoSuggestions: TEST_MERINO_SUGGESTIONS, + }); +}); + +add_task(async function basic() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.addons.featureGate", true]], + }); + + for (const merinoSuggestion of TEST_MERINO_SUGGESTIONS) { + MerinoTestUtils.server.response.body.suggestions = [merinoSuggestion]; + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "only match the Merino suggestion", + }); + Assert.equal(UrlbarTestUtils.getResultCount(window), 2); + + const { element, result } = await UrlbarTestUtils.getDetailsOfResultAt( + window, + 1 + ); + const row = element.row; + const icon = row.querySelector(".urlbarView-dynamic-addons-icon"); + Assert.equal(icon.src, merinoSuggestion.icon); + const url = row.querySelector(".urlbarView-dynamic-addons-url"); + Assert.equal(url.textContent, merinoSuggestion.url); + const title = row.querySelector(".urlbarView-dynamic-addons-title"); + Assert.equal(title.textContent, merinoSuggestion.title); + const description = row.querySelector( + ".urlbarView-dynamic-addons-description" + ); + Assert.equal(description.textContent, merinoSuggestion.description); + const reviews = row.querySelector(".urlbarView-dynamic-addons-reviews"); + Assert.equal( + reviews.textContent, + `${new Intl.NumberFormat().format( + Number(merinoSuggestion.custom_details.amo.number_of_ratings) + )} reviews` + ); + + const isTopPick = merinoSuggestion.is_top_pick ?? true; + if (isTopPick) { + Assert.equal(result.suggestedIndex, 1); + } else if (merinoSuggestion.is_sponsored) { + Assert.equal( + result.suggestedIndex, + UrlbarPrefs.get("quickSuggestSponsoredIndex") + ); + } else { + Assert.equal( + result.suggestedIndex, + UrlbarPrefs.get("quickSuggestNonSponsoredIndex") + ); + } + + const onLoad = BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + merinoSuggestion.url + ); + EventUtils.synthesizeMouseAtCenter(row, {}); + await onLoad; + Assert.ok(true, "Expected page is loaded"); + + await PlacesUtils.history.clear(); + } + + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function ratings() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.addons.featureGate", true]], + }); + + const testRating = [ + "0", + "0.24", + "0.25", + "0.74", + "0.75", + "1", + "1.24", + "1.25", + "1.74", + "1.75", + "2", + "2.24", + "2.25", + "2.74", + "2.75", + "3", + "3.24", + "3.25", + "3.74", + "3.75", + "4", + "4.24", + "4.25", + "4.74", + "4.75", + "5", + ]; + const baseMerinoSuggestion = JSON.parse( + JSON.stringify(TEST_MERINO_SUGGESTIONS[0]) + ); + + for (const rating of testRating) { + baseMerinoSuggestion.custom_details.amo.rating = rating; + MerinoTestUtils.server.response.body.suggestions = [baseMerinoSuggestion]; + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "only match the Merino suggestion", + }); + Assert.equal(UrlbarTestUtils.getResultCount(window), 2); + + const { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1); + + const ratingElements = element.row.querySelectorAll( + ".urlbarView-dynamic-addons-rating" + ); + Assert.equal(ratingElements.length, 5); + + for (let i = 0; i < ratingElements.length; i++) { + const ratingElement = ratingElements[i]; + + const distanceToFull = Number(rating) - i; + let fill = "full"; + if (distanceToFull < 0.25) { + fill = "empty"; + } else if (distanceToFull < 0.75) { + fill = "half"; + } + Assert.equal(ratingElement.getAttribute("fill"), fill); + } + } + + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function disable() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.addons.featureGate", false]], + }); + + // Restore AdmWikipedia suggestions. + MerinoTestUtils.server.reset(); + // Add one Addon suggestion that is higher score than AdmWikipedia. + MerinoTestUtils.server.response.body.suggestions.push( + Object.assign({}, TEST_MERINO_SUGGESTIONS[0], { score: 2 }) + ); + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "only match the Merino suggestion", + }); + Assert.equal(UrlbarTestUtils.getResultCount(window), 2); + + const { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1); + Assert.equal(result.payload.telemetryType, "adm_sponsored"); + + MerinoTestUtils.server.response.body.suggestions = TEST_MERINO_SUGGESTIONS; + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function resultMenu_showLessFrequently() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.addons.featureGate", true], + ["browser.urlbar.addons.showLessFrequentlyCount", 0], + ], + }); + + const cleanUpNimbus = await UrlbarTestUtils.initNimbusFeature({ + addonsShowLessFrequentlyCap: 3, + }); + + // Sanity check. + Assert.equal(UrlbarPrefs.get("addonsShowLessFrequentlyCap"), 3); + Assert.equal(UrlbarPrefs.get("addons.showLessFrequentlyCount"), 0); + + await doShowLessFrequently({ + input: "aaa b", + expected: { + isSuggestionShown: true, + isMenuItemShown: true, + }, + }); + Assert.equal(UrlbarPrefs.get("addons.showLessFrequentlyCount"), 1); + + await doShowLessFrequently({ + input: "aaa b", + expected: { + isSuggestionShown: true, + isMenuItemShown: true, + }, + }); + Assert.equal(UrlbarPrefs.get("addons.showLessFrequentlyCount"), 2); + + await doShowLessFrequently({ + input: "aaa b", + expected: { + isSuggestionShown: true, + isMenuItemShown: true, + }, + }); + Assert.equal(UrlbarPrefs.get("addons.showLessFrequentlyCount"), 3); + + await doShowLessFrequently({ + input: "aaa b", + expected: { + // The suggestion should not display since addons.showLessFrequentlyCount + // is 3 and the substring (" b") after the first word ("aaa") is 2 chars + // long. + isSuggestionShown: false, + }, + }); + + await doShowLessFrequently({ + input: "aaa bb", + expected: { + // The suggestion should display, but item should not shown since the + // addons.showLessFrequentlyCount reached to addonsShowLessFrequentlyCap + // already. + isSuggestionShown: true, + isMenuItemShown: false, + }, + }); + + await cleanUpNimbus(); + await SpecialPowers.popPrefEnv(); +}); + +// Tests the "Not interested" result menu dismissal command. +add_task(async function resultMenu_notInterested() { + await doDismissTest("not_interested"); +}); + +// Tests the "Not relevant" result menu dismissal command. +add_task(async function notRelevant() { + await doDismissTest("not_relevant"); +}); + +add_task(async function rowLabel() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.addons.featureGate", true]], + }); + + const testCases = [ + { + bestMatch: true, + expected: "Firefox extension", + }, + { + bestMatch: false, + expected: "Firefox Suggest", + }, + ]; + + for (const { bestMatch, expected } of testCases) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.bestMatch.enabled", bestMatch]], + }); + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "only match the Merino suggestion", + }); + Assert.equal(UrlbarTestUtils.getResultCount(window), 2); + + const { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1); + const row = element.row; + Assert.equal(row.getAttribute("label"), expected); + + await SpecialPowers.popPrefEnv(); + } + + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function treatmentB() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.addons.featureGate", true]], + }); + + const cleanUpNimbus = await UrlbarTestUtils.initNimbusFeature({ + addonsUITreatment: "b", + }); + // Sanity check. + Assert.equal(UrlbarPrefs.get("addonsUITreatment"), "b"); + + const merinoSuggestion = TEST_MERINO_SUGGESTIONS[0]; + MerinoTestUtils.server.response.body.suggestions = [merinoSuggestion]; + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "only match the Merino suggestion", + }); + Assert.equal(UrlbarTestUtils.getResultCount(window), 2); + + const { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1); + const row = element.row; + const icon = row.querySelector(".urlbarView-dynamic-addons-icon"); + Assert.equal(icon.src, merinoSuggestion.icon); + const url = row.querySelector(".urlbarView-dynamic-addons-url"); + Assert.equal(url.textContent, merinoSuggestion.url); + const title = row.querySelector(".urlbarView-dynamic-addons-title"); + Assert.equal(title.textContent, merinoSuggestion.title); + const description = row.querySelector( + ".urlbarView-dynamic-addons-description" + ); + Assert.equal(description.textContent, merinoSuggestion.description); + const ratingContainer = row.querySelector( + ".urlbarView-dynamic-addons-ratingContainer" + ); + Assert.ok(BrowserTestUtils.is_hidden(ratingContainer)); + const reviews = row.querySelector(".urlbarView-dynamic-addons-reviews"); + Assert.equal(reviews.textContent, "Recommended"); + + await cleanUpNimbus(); + await SpecialPowers.popPrefEnv(); +}); + +async function doShowLessFrequently({ input, expected }) { + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: input, + }); + + if (!expected.isSuggestionShown) { + for (let i = 0; i < UrlbarTestUtils.getResultCount(window); i++) { + const details = await UrlbarTestUtils.getDetailsOfResultAt(window, i); + Assert.notEqual( + details.result.payload.dynamicType, + "addons", + `Addons suggestion should be absent (checking index ${i})` + ); + } + + return; + } + + const resultIndex = 1; + const details = await UrlbarTestUtils.getDetailsOfResultAt( + window, + resultIndex + ); + Assert.equal( + details.result.payload.dynamicType, + "addons", + `Addons suggestion should be present at expected index after ${input} search` + ); + + // Click the command. + try { + await UrlbarTestUtils.openResultMenuAndClickItem( + window, + "show_less_frequently", + { + resultIndex, + } + ); + Assert.ok(expected.isMenuItemShown); + Assert.ok( + gURLBar.view.isOpen, + "The view should remain open clicking the command" + ); + Assert.ok( + details.element.row.hasAttribute("feedback-acknowledgment"), + "Row should have feedback acknowledgment after clicking command" + ); + } catch (e) { + Assert.ok(!expected.isMenuItemShown); + Assert.ok( + !details.element.row.hasAttribute("feedback-acknowledgment"), + "Row should not have feedback acknowledgment after clicking command" + ); + Assert.equal( + e.message, + "Menu item not found for command: show_less_frequently" + ); + } + + await UrlbarTestUtils.promisePopupClose(window); +} + +async function doDismissTest(command) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.addons.featureGate", true]], + }); + + await UrlbarTestUtils.promiseAutocompleteResultPopup({ + window, + value: "123", + }); + + const resultCount = UrlbarTestUtils.getResultCount(window); + const resultIndex = 1; + let details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex); + Assert.equal( + details.result.payload.dynamicType, + "addons", + "Addons suggestion should be present" + ); + + // Sanity check. + Assert.ok(UrlbarPrefs.get("suggest.addons")); + + // Click the command. + await UrlbarTestUtils.openResultMenuAndClickItem( + window, + ["[data-l10n-id=firefox-suggest-command-dont-show-this]", command], + { resultIndex, openByMouse: true } + ); + + Assert.ok( + !UrlbarPrefs.get("suggest.addons"), + "suggest.addons pref should be set to false after dismissal" + ); + + // The row should be a tip now. + Assert.ok(gURLBar.view.isOpen, "The view should remain open after dismissal"); + Assert.equal( + UrlbarTestUtils.getResultCount(window), + resultCount, + "The result count should not haved changed after dismissal" + ); + details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex); + Assert.equal( + details.type, + UrlbarUtils.RESULT_TYPE.TIP, + "Row should be a tip after dismissal" + ); + Assert.equal( + details.result.payload.type, + "dismissalAcknowledgment", + "Tip type should be dismissalAcknowledgment" + ); + Assert.ok( + !details.element.row.hasAttribute("feedback-acknowledgment"), + "Row should not have feedback acknowledgment after dismissal" + ); + + // Get the dismissal acknowledgment's "Got it" button and click it. + let gotItButton = UrlbarTestUtils.getButtonForResultIndex( + window, + "0", + resultIndex + ); + Assert.ok(gotItButton, "Row should have a 'Got it' button"); + EventUtils.synthesizeMouseAtCenter(gotItButton, {}, window); + + // The view should remain open and the tip row should be gone. + Assert.ok( + gURLBar.view.isOpen, + "The view should remain open clicking the 'Got it' button" + ); + Assert.equal( + UrlbarTestUtils.getResultCount(window), + resultCount - 1, + "The result count should be one less after clicking 'Got it' button" + ); + for (let i = 0; i < UrlbarTestUtils.getResultCount(window); i++) { + details = await UrlbarTestUtils.getDetailsOfResultAt(window, i); + Assert.ok( + details.type != UrlbarUtils.RESULT_TYPE.TIP && + details.result.payload.dynamicType !== "addons", + "Tip result and addon result should not be present" + ); + } + + await UrlbarTestUtils.promisePopupClose(window); + + await SpecialPowers.popPrefEnv(); + UrlbarPrefs.clear("suggest.addons"); +} -- cgit v1.2.3