summaryrefslogtreecommitdiffstats
path: root/browser/components/shopping/tests/browser/browser_shopping_settings.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/shopping/tests/browser/browser_shopping_settings.js')
-rw-r--r--browser/components/shopping/tests/browser/browser_shopping_settings.js642
1 files changed, 642 insertions, 0 deletions
diff --git a/browser/components/shopping/tests/browser/browser_shopping_settings.js b/browser/components/shopping/tests/browser/browser_shopping_settings.js
new file mode 100644
index 0000000000..2508be05c7
--- /dev/null
+++ b/browser/components/shopping/tests/browser/browser_shopping_settings.js
@@ -0,0 +1,642 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests that the fakespot link has the expected url and utm parameters.
+ */
+add_task(async function test_shopping_settings_fakespot_learn_more() {
+ await BrowserTestUtils.withNewTab(
+ {
+ url: "about:shoppingsidebar",
+ gBrowser,
+ },
+ async browser => {
+ await SpecialPowers.spawn(
+ browser,
+ [MOCK_ANALYZED_PRODUCT_RESPONSE],
+ async mockData => {
+ let shoppingContainer =
+ content.document.querySelector(
+ "shopping-container"
+ ).wrappedJSObject;
+
+ let href = shoppingContainer.settingsEl.fakespotLearnMoreLinkEl.href;
+ let url = new URL(href);
+ is(url.pathname, "/our-mission");
+ is(url.origin, "https://www.fakespot.com");
+
+ let qs = url.searchParams;
+ is(qs.get("utm_source"), "review-checker");
+ is(qs.get("utm_campaign"), "fakespot-by-mozilla");
+ is(qs.get("utm_medium"), "inproduct");
+ is(qs.get("utm_term"), "core-sidebar");
+ }
+ );
+ }
+ );
+});
+
+/**
+ * Tests that the ads link has the expected utm parameters.
+ */
+add_task(async function test_shopping_settings_ads_learn_more() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.shopping.experience2023.ads.enabled", true]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ url: "about:shoppingsidebar",
+ gBrowser,
+ },
+ async browser => {
+ await SpecialPowers.spawn(
+ browser,
+ [MOCK_ANALYZED_PRODUCT_RESPONSE],
+ async mockData => {
+ let shoppingContainer =
+ content.document.querySelector(
+ "shopping-container"
+ ).wrappedJSObject;
+
+ let href = shoppingContainer.settingsEl.adsLearnMoreLinkEl.href;
+ let qs = new URL(href).searchParams;
+
+ is(qs.get("utm_campaign"), "learn-more");
+ is(qs.get("utm_medium"), "inproduct");
+ is(qs.get("utm_term"), "core-sidebar");
+ }
+ );
+ }
+ );
+});
+
+/**
+ * Tests that the settings component is rendered as expected when
+ * `browser.shopping.experience2023.ads.enabled` is true.
+ */
+add_task(async function test_shopping_settings_ads_enabled() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.shopping.experience2023.ads.enabled", true]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ url: "about:shoppingsidebar",
+ gBrowser,
+ },
+ async browser => {
+ await SpecialPowers.spawn(
+ browser,
+ [MOCK_ANALYZED_PRODUCT_RESPONSE],
+ async mockData => {
+ let shoppingContainer =
+ content.document.querySelector(
+ "shopping-container"
+ ).wrappedJSObject;
+
+ shoppingContainer.data = Cu.cloneInto(mockData, content);
+ // Note (Bug 1876878): Until we have proper mocks of data passed from ShoppingSidebarChild,
+ // hardcode `adsEnabled` to be passed to settings.mjs so that we can test
+ // toggle for ad visibility.
+ shoppingContainer.adsEnabled = true;
+ await shoppingContainer.updateComplete;
+
+ let shoppingSettings = shoppingContainer.settingsEl;
+ ok(shoppingSettings, "Got the shopping-settings element");
+
+ let adsToggle = shoppingSettings.recommendationsToggleEl;
+ ok(adsToggle, "There should be an ads toggle");
+
+ let optOutButton = shoppingSettings.optOutButtonEl;
+ ok(optOutButton, "There should be an opt-out button");
+ }
+ );
+ }
+ );
+
+ await SpecialPowers.popPrefEnv();
+});
+
+/**
+ * Tests that the settings component is rendered as expected when
+ * `browser.shopping.experience2023.ads.enabled` is false.
+ */
+add_task(async function test_shopping_settings_ads_disabled() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.shopping.experience2023.ads.enabled", false]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ url: "about:shoppingsidebar",
+ gBrowser,
+ },
+ async browser => {
+ let shoppingSettings = await getSettingsDetails(
+ browser,
+ MOCK_POPULATED_DATA
+ );
+ ok(shoppingSettings.settingsEl, "Got the shopping-settings element");
+
+ let adsToggle = shoppingSettings.recommendationsToggleEl;
+ ok(!adsToggle, "There should be no ads toggle");
+
+ let optOutButton = shoppingSettings.optOutButtonEl;
+ ok(optOutButton, "There should be an opt-out button");
+ }
+ );
+
+ await SpecialPowers.popPrefEnv();
+});
+
+/**
+ * Tests that the shopping-settings ads toggle and ad render correctly, even with
+ * multiple tabs. If `browser.shopping.experience2023.ads.userEnabled`
+ * is false in one tab, it should be false for all other tabs with the shopping sidebar open.
+ */
+add_task(async function test_settings_toggle_ad_and_multiple_tabs() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.shopping.experience2023.ads.enabled", true],
+ ["browser.shopping.experience2023.ads.userEnabled", true],
+ ],
+ });
+
+ // Tab 1 - ad is visible at first and then toggle is selected to set ads.userEnabled to false.
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:shoppingsidebar"
+ );
+ let browser1 = tab1.linkedBrowser;
+
+ let mockArgs = {
+ mockData: MOCK_ANALYZED_PRODUCT_RESPONSE,
+ mockRecommendationData: MOCK_RECOMMENDED_ADS_RESPONSE,
+ };
+ await SpecialPowers.spawn(browser1, [mockArgs], async args => {
+ const { mockData, mockRecommendationData } = args;
+ let shoppingContainer =
+ content.document.querySelector("shopping-container").wrappedJSObject;
+
+ let adVisiblePromise = ContentTaskUtils.waitForCondition(() => {
+ return (
+ shoppingContainer.recommendedAdEl &&
+ ContentTaskUtils.isVisible(shoppingContainer.recommendedAdEl)
+ );
+ }, "Waiting for recommended-ad to be visible");
+
+ shoppingContainer.data = Cu.cloneInto(mockData, content);
+ shoppingContainer.recommendationData = Cu.cloneInto(
+ mockRecommendationData,
+ content
+ );
+ // Note (Bug 1876878): Until we have proper mocks of data passed from ShoppingSidebarChild,
+ // hardcode `adsEnabled` and `adsEnabledByUser` so that we can test ad visibility.
+ shoppingContainer.adsEnabled = true;
+ shoppingContainer.adsEnabledByUser = true;
+
+ await shoppingContainer.updateComplete;
+ await adVisiblePromise;
+
+ let adEl = shoppingContainer.recommendedAdEl;
+ await adEl.updateComplete;
+ is(
+ adEl.priceEl.textContent,
+ "$" + mockRecommendationData[0].price,
+ "Price is shown correctly"
+ );
+ is(
+ adEl.linkEl.title,
+ mockRecommendationData[0].name,
+ "Title in link is shown correctly"
+ );
+ is(
+ adEl.linkEl.href,
+ mockRecommendationData[0].url,
+ "URL for link is correct"
+ );
+ is(
+ adEl.ratingEl.rating,
+ mockRecommendationData[0].adjusted_rating,
+ "MozFiveStar rating is shown correctly"
+ );
+ is(
+ adEl.letterGradeEl.letter,
+ mockRecommendationData[0].grade,
+ "LetterGrade letter is shown correctly"
+ );
+
+ let shoppingSettings = shoppingContainer.settingsEl;
+ ok(shoppingSettings, "Got the shopping-settings element");
+
+ let adsToggle = shoppingSettings.recommendationsToggleEl;
+ ok(adsToggle, "There should be a toggle");
+ ok(adsToggle.hasAttribute("pressed"), "Toggle should have enabled state");
+
+ ok(
+ SpecialPowers.getBoolPref(
+ "browser.shopping.experience2023.ads.userEnabled"
+ ),
+ "ads userEnabled pref should be true"
+ );
+
+ let adRemovedPromise = ContentTaskUtils.waitForCondition(() => {
+ return !shoppingContainer.recommendedAdEl;
+ }, "Waiting for recommended-ad to be removed");
+
+ adsToggle.click();
+
+ await adRemovedPromise;
+
+ ok(!adsToggle.hasAttribute("pressed"), "Toggle should have disabled state");
+ ok(
+ !SpecialPowers.getBoolPref(
+ "browser.shopping.experience2023.ads.userEnabled"
+ ),
+ "ads userEnabled pref should be false"
+ );
+ });
+
+ // Tab 2 - ads.userEnabled should still be false and ad should not be visible.
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:shoppingsidebar"
+ );
+ let browser2 = tab2.linkedBrowser;
+
+ await SpecialPowers.spawn(browser2, [mockArgs], async args => {
+ const { mockData, mockRecommendationData } = args;
+ let shoppingContainer =
+ content.document.querySelector("shopping-container").wrappedJSObject;
+
+ shoppingContainer.data = Cu.cloneInto(mockData, content);
+ shoppingContainer.recommendationData = Cu.cloneInto(
+ mockRecommendationData,
+ content
+ );
+ // Note (Bug 1876878): Until we have proper mocks of data passed from ShoppingSidebarChild,
+ // hardcode `adsEnabled` so that we can test ad visibility.
+ shoppingContainer.adsEnabled = true;
+
+ await shoppingContainer.updateComplete;
+
+ ok(
+ !shoppingContainer.recommendedAdEl,
+ "There should be no ads in the new tab"
+ );
+ ok(
+ !SpecialPowers.getBoolPref(
+ "browser.shopping.experience2023.ads.userEnabled"
+ ),
+ "ads userEnabled pref should be false"
+ );
+ });
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+
+ await SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
+});
+
+/**
+ * Tests that the settings component is rendered as expected when
+ * `browser.shopping.experience2023.autoOpen.enabled` is false.
+ */
+add_task(async function test_shopping_settings_experiment_auto_open_disabled() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.shopping.experience2023.autoOpen.enabled", false]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ url: PRODUCT_TEST_URL,
+ gBrowser,
+ },
+ async browser => {
+ let sidebar = gBrowser
+ .getPanel(browser)
+ .querySelector("shopping-sidebar");
+ await promiseSidebarUpdated(sidebar, PRODUCT_TEST_URL);
+
+ await SpecialPowers.spawn(
+ sidebar.querySelector("browser"),
+ [MOCK_ANALYZED_PRODUCT_RESPONSE],
+ async mockData => {
+ let shoppingContainer =
+ content.document.querySelector(
+ "shopping-container"
+ ).wrappedJSObject;
+
+ shoppingContainer.data = Cu.cloneInto(mockData, content);
+ await shoppingContainer.updateComplete;
+
+ let shoppingSettings = shoppingContainer.settingsEl;
+ ok(shoppingSettings, "Got the shopping-settings element");
+ ok(
+ !shoppingSettings.wrapperEl.className.includes(
+ "shopping-settings-auto-open-ui-enabled"
+ ),
+ "Settings card should not have a special classname with autoOpen pref disabled"
+ );
+ is(
+ shoppingSettings.shoppingCardEl?.type,
+ "accordion",
+ "shopping-card type should be accordion"
+ );
+
+ /* Verify control treatment UI */
+ ok(
+ !shoppingSettings.autoOpenToggleEl,
+ "There should be no auto-open toggle"
+ );
+ ok(
+ !shoppingSettings.autoOpenToggleDescriptionEl,
+ "There should be no description for the auto-open toggle"
+ );
+ ok(!shoppingSettings.dividerEl, "There should be no divider");
+ ok(
+ !shoppingSettings.sidebarEnabledStateEl,
+ "There should be no message about the sidebar active state"
+ );
+
+ ok(
+ shoppingSettings.optOutButtonEl,
+ "There should be an opt-out button"
+ );
+ }
+ );
+ }
+ );
+
+ await SpecialPowers.popPrefEnv();
+});
+
+/**
+ * Tests that the settings component is rendered as expected when
+ * `browser.shopping.experience2023.autoOpen.enabled` is true and
+ * `browser.shopping.experience2023.ads.enabled is true`.
+ */
+add_task(
+ async function test_shopping_settings_experiment_auto_open_enabled_with_ads() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.shopping.experience2023.autoOpen.enabled", true],
+ ["browser.shopping.experience2023.autoOpen.userEnabled", true],
+ ["browser.shopping.experience2023.ads.enabled", true],
+ ],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ url: PRODUCT_TEST_URL,
+ gBrowser,
+ },
+ async browser => {
+ let sidebar = gBrowser
+ .getPanel(browser)
+ .querySelector("shopping-sidebar");
+ await promiseSidebarUpdated(sidebar, PRODUCT_TEST_URL);
+
+ await SpecialPowers.spawn(
+ sidebar.querySelector("browser"),
+ [MOCK_ANALYZED_PRODUCT_RESPONSE],
+ async mockData => {
+ let shoppingContainer =
+ content.document.querySelector(
+ "shopping-container"
+ ).wrappedJSObject;
+
+ await shoppingContainer.updateComplete;
+
+ let shoppingSettings = shoppingContainer.settingsEl;
+ ok(shoppingSettings, "Got the shopping-settings element");
+ ok(
+ shoppingSettings.wrapperEl.className.includes(
+ "shopping-settings-auto-open-ui-enabled"
+ ),
+ "Settings card should have a special classname with autoOpen pref enabled"
+ );
+ is(
+ shoppingSettings.shoppingCardEl?.type,
+ "",
+ "shopping-card type should be default"
+ );
+
+ ok(
+ shoppingSettings.recommendationsToggleEl,
+ "There should be an ads toggle"
+ );
+
+ /* Verify auto-open experiment UI */
+ ok(
+ shoppingSettings.autoOpenToggleEl,
+ "There should be an auto-open toggle"
+ );
+ ok(
+ shoppingSettings.autoOpenToggleDescriptionEl,
+ "There should be a description for the auto-open toggle"
+ );
+ ok(shoppingSettings.dividerEl, "There should be a divider");
+ ok(
+ shoppingSettings.sidebarEnabledStateEl,
+ "There should be a message about the sidebar active state"
+ );
+
+ ok(
+ shoppingSettings.optOutButtonEl,
+ "There should be an opt-out button"
+ );
+ }
+ );
+ }
+ );
+
+ await SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
+ }
+);
+
+/**
+ * Tests that the settings component is rendered as expected when
+ * `browser.shopping.experience2023.autoOpen.enabled` is true and
+ * `browser.shopping.experience2023.ads.enabled is false`.
+ */
+add_task(
+ async function test_shopping_settings_experiment_auto_open_enabled_no_ads() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.shopping.experience2023.autoOpen.enabled", true],
+ ["browser.shopping.experience2023.autoOpen.userEnabled", true],
+ ["browser.shopping.experience2023.ads.enabled", false],
+ ],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ url: PRODUCT_TEST_URL,
+ gBrowser,
+ },
+ async browser => {
+ let sidebar = gBrowser
+ .getPanel(browser)
+ .querySelector("shopping-sidebar");
+ await promiseSidebarUpdated(sidebar, PRODUCT_TEST_URL);
+
+ await SpecialPowers.spawn(
+ sidebar.querySelector("browser"),
+ [MOCK_ANALYZED_PRODUCT_RESPONSE],
+ async mockData => {
+ let shoppingContainer =
+ content.document.querySelector(
+ "shopping-container"
+ ).wrappedJSObject;
+
+ await shoppingContainer.updateComplete;
+
+ let shoppingSettings = shoppingContainer.settingsEl;
+ ok(shoppingSettings, "Got the shopping-settings element");
+ ok(
+ shoppingSettings.wrapperEl.className.includes(
+ "shopping-settings-auto-open-ui-enabled"
+ ),
+ "Settings card should have a special classname with autoOpen pref enabled"
+ );
+ is(
+ shoppingSettings.shoppingCardEl?.type,
+ "",
+ "shopping-card type should be default"
+ );
+
+ ok(
+ !shoppingSettings.recommendationsToggleEl,
+ "There should be no ads toggle"
+ );
+
+ /* Verify auto-open experiment UI */
+ ok(
+ shoppingSettings.autoOpenToggleEl,
+ "There should be an auto-open toggle"
+ );
+ ok(
+ shoppingSettings.autoOpenToggleDescriptionEl,
+ "There should be a description for the auto-open toggle"
+ );
+ ok(shoppingSettings.dividerEl, "There should be a divider");
+ ok(
+ shoppingSettings.sidebarEnabledStateEl,
+ "There should be a message about the sidebar active state"
+ );
+
+ ok(
+ shoppingSettings.optOutButtonEl,
+ "There should be an opt-out button"
+ );
+ }
+ );
+ }
+ );
+
+ await SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
+ }
+);
+
+/**
+ * Tests that auto-open toggle state and autoOpen.userEnabled pref update correctly.
+ */
+add_task(async function test_settings_auto_open_toggle() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.shopping.experience2023.autoOpen.enabled", true],
+ ["browser.shopping.experience2023.autoOpen.userEnabled", true],
+ ],
+ });
+
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ PRODUCT_TEST_URL
+ );
+ let browser = tab1.linkedBrowser;
+
+ let mockArgs = {
+ mockData: MOCK_ANALYZED_PRODUCT_RESPONSE,
+ };
+
+ let sidebar = gBrowser.getPanel(browser).querySelector("shopping-sidebar");
+ await promiseSidebarUpdated(sidebar, PRODUCT_TEST_URL);
+
+ await SpecialPowers.spawn(
+ sidebar.querySelector("browser"),
+ [mockArgs],
+ async args => {
+ const { mockData } = args;
+ let shoppingContainer =
+ content.document.querySelector("shopping-container").wrappedJSObject;
+
+ shoppingContainer.data = Cu.cloneInto(mockData, content);
+ await shoppingContainer.updateComplete;
+
+ let shoppingSettings = shoppingContainer.settingsEl;
+ ok(shoppingSettings, "Got the shopping-settings element");
+
+ let autoOpenToggle = shoppingSettings.autoOpenToggleEl;
+ ok(autoOpenToggle, "There should be an auto-open toggle");
+ ok(
+ autoOpenToggle.hasAttribute("pressed"),
+ "Toggle should have enabled state"
+ );
+
+ let toggleStateChangePromise = ContentTaskUtils.waitForCondition(() => {
+ return !autoOpenToggle.hasAttribute("pressed");
+ }, "Waiting for auto-open toggle state to be disabled");
+
+ autoOpenToggle.click();
+
+ await toggleStateChangePromise;
+
+ ok(
+ !SpecialPowers.getBoolPref(
+ "browser.shopping.experience2023.autoOpen.userEnabled"
+ ),
+ "autoOpen.userEnabled pref should be false"
+ );
+ ok(
+ SpecialPowers.getBoolPref(
+ "browser.shopping.experience2023.autoOpen.enabled"
+ ),
+ "autoOpen.enabled pref should still be true"
+ );
+ ok(
+ !SpecialPowers.getBoolPref("browser.shopping.experience2023.active"),
+ "Sidebar active pref should be false after pressing auto-open toggle to close the sidebar"
+ );
+
+ // Now try updating the pref directly to see if toggle will change state immediately
+ await SpecialPowers.popPrefEnv();
+ toggleStateChangePromise = ContentTaskUtils.waitForCondition(() => {
+ return autoOpenToggle.hasAttribute("pressed");
+ }, "Waiting for auto-open toggle to be enabled");
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.shopping.experience2023.autoOpen.userEnabled", true],
+ ["browser.shopping.experience2023.active", true],
+ ],
+ });
+
+ await toggleStateChangePromise;
+ }
+ );
+
+ BrowserTestUtils.removeTab(tab1);
+
+ await SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
+});