diff options
Diffstat (limited to 'browser/components/search/test/browser/telemetry/browser_search_telemetry_spa_multi_tab.js')
-rw-r--r-- | browser/components/search/test/browser/telemetry/browser_search_telemetry_spa_multi_tab.js | 875 |
1 files changed, 875 insertions, 0 deletions
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_spa_multi_tab.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_spa_multi_tab.js new file mode 100644 index 0000000000..478a995e97 --- /dev/null +++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_spa_multi_tab.js @@ -0,0 +1,875 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Check SPA page loads on a single provider using multiple tabs. + */ + +"use strict"; + +// Allow more time for Mac machines so they don't time out in verify mode. +if (AppConstants.platform == "macosx") { + requestLongerTimeout(3); +} + +add_setup(async function () { + await initSinglePageAppTest(); + + await SpecialPowers.pushPrefEnv({ + set: [["dom.ipc.processCount.webIsolated", 1]], + }); + + registerCleanupFunction(async () => { + SearchSERPTelemetry.overrideSearchTelemetryForTests(); + resetTelemetry(); + }); +}); + +// Deliberately has actions happening after one another to assert that the +// different events are recorded properly. + +// One issue that can occur is if two SERPs have the same search term, if we +// try finding the item for the URL, it might match the wrong item. +// e.g. two tabs search for foobar +// one tab then searches for barfoo +// the other tab that had foobar does another search, but instead of referring +// back to foobar, it looks at barfoo and messes with its state. + +// We use switch tabs to avoid `getBoundsWithoutFlushing` not returning the +// latest visual info, which affects ad visibility counts. +add_task(async function test_load_serps_and_click_related_searches() { + resetTelemetry(); + + let tab1 = await SinglePageAppUtils.createTabAndLoadURL(); + let tab2 = await SinglePageAppUtils.createTabAndLoadURL(); + let tab3 = await SinglePageAppUtils.createTabAndLoadURL(); + + await BrowserTestUtils.switchTab(gBrowser, tab1); + await SinglePageAppUtils.visitRelatedSearchWithoutAds(tab1); + + await BrowserTestUtils.switchTab(gBrowser, tab2); + await SinglePageAppUtils.visitRelatedSearch(tab2); + + await BrowserTestUtils.switchTab(gBrowser, tab3); + await SinglePageAppUtils.visitRelatedSearchWithoutAds(tab3); + + await BrowserTestUtils.switchTab(gBrowser, tab1); + await SinglePageAppUtils.visitRelatedSearch(tab1); + + await BrowserTestUtils.switchTab(gBrowser, tab2); + await SinglePageAppUtils.visitRelatedSearchWithoutAds(tab2); + + await BrowserTestUtils.switchTab(gBrowser, tab3); + await SinglePageAppUtils.visitRelatedSearchWithoutAds(tab3); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example1:tagged:ff": 9, + }, + "browser.search.withads.unknown": { + "example1:tagged": 5, + }, + } + ); + + assertSERPTelemetry([ + { + // Tab 1 - Visit a SERP, clicks a related search without ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visits a SERP, clicks a related SERP with ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 3 - Visit a SERP, clicks a related SERP without ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 1 - Visits a related SERP without ads, clicks on a related SERP + // with ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [], + }, + { + // Tab 2 - Visits a related search with ads, clicks a related SERP + // without ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 3 - Visit a SERP without ads, clicks a related SERP without ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [], + }, + { + // Tab 1 - Visit a related SERP with ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a related SERP without ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [], + }, + { + // Tab 3 - Visit a related SERP without ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [], + }, + ]); + + await BrowserTestUtils.removeTab(tab1); + await BrowserTestUtils.removeTab(tab2); + await BrowserTestUtils.removeTab(tab3); +}); + +/** + * The source of the ad click should match the correct tab. + */ +add_task(async function test_different_sources_click_ad() { + resetTelemetry(); + + let tab1 = await SinglePageAppUtils.createTabAndLoadURL(); + let tab2 = await SinglePageAppUtils.createTabAndLoadURL(); + + await SinglePageAppUtils.visitRelatedSearch(tab2); + await SinglePageAppUtils.goBack(tab2); + await SinglePageAppUtils.clickAd(tab2); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example1:tagged:ff": 3, + }, + "browser.search.withads.unknown": { + "example1:tagged": 3, + }, + "browser.search.content.tabhistory": { + "example1:tagged:ff": 1, + }, + "browser.search.withads.tabhistory": { + "example1:tagged": 1, + }, + "browser.search.adclicks.tabhistory": { + "example1:tagged": 1, + }, + } + ); + + assertSERPTelemetry([ + { + // Tab 1 - Visit a SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a SERP, click a related SERP with ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a SERP, click back button. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + abandonment: { + reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION, + }, + }, + { + // Tab 2 - Visit a SERP, click ad button. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "tabhistory", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + }, + ]); + + await BrowserTestUtils.removeTab(tab1); + await BrowserTestUtils.removeTab(tab2); +}); + +add_task(async function test_different_sources_click_redirect_ad_in_new_tab() { + resetTelemetry(); + + let tab1 = await SinglePageAppUtils.createTabAndLoadURL(); + let tab2 = await SinglePageAppUtils.createTabAndLoadURL(); + + await SinglePageAppUtils.visitRelatedSearch(tab2); + await SinglePageAppUtils.goBack(tab2); + let tab3 = await SinglePageAppUtils.clickRedirectAdInNewTab(tab2); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example1:tagged:ff": 3, + }, + "browser.search.withads.unknown": { + "example1:tagged": 3, + }, + "browser.search.content.tabhistory": { + "example1:tagged:ff": 1, + }, + "browser.search.withads.tabhistory": { + "example1:tagged": 1, + }, + "browser.search.adclicks.tabhistory": { + "example1:tagged": 1, + }, + } + ); + + assertSERPTelemetry([ + { + // Tab 1 - Visit a SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a SERP, click a related SERP with ads. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a SERP, click back button. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + abandonment: { + reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION, + }, + }, + { + // Tab 2 - Visit a SERP, click ad button. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "tabhistory", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + }, + ]); + + await BrowserTestUtils.removeTab(tab1); + await BrowserTestUtils.removeTab(tab2); + await BrowserTestUtils.removeTab(tab3); +}); + +add_task(async function test_update_query_params_after_search() { + resetTelemetry(); + + let tab1 = await SinglePageAppUtils.createTabAndLoadURL(); + info("Visit a related search so that the URL has an extra query parameter."); + await SinglePageAppUtils.visitRelatedSearch(tab1); + + let tab2 = await SinglePageAppUtils.createTabAndLoadURL(); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example1:tagged:ff": 3, + }, + "browser.search.withads.unknown": { + "example1:tagged": 3, + }, + } + ); + + assertSERPTelemetry([ + { + // Tab 1 - Visit a SERP, click on a related SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 1 - Visit a related SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a SERP, click on an ad. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + ]); + + await BrowserTestUtils.removeTab(tab1); + await BrowserTestUtils.removeTab(tab2); +}); + +add_task(async function test_update_query_params() { + resetTelemetry(); + + // Deliberately use a different search term for the first example, because + // if both tabs have the same search term and a link is clicked that opens a + // new window, we currently can't recover the exact browser. + let tab1 = await SinglePageAppUtils.createTabAndSearch("foo bar"); + info("Visit a related search so that the URL has an extra query parameter."); + await SinglePageAppUtils.visitRelatedSearch(tab1); + + let tab2 = await SinglePageAppUtils.createTabAndLoadURL(); + let newWindow = await SinglePageAppUtils.clickRedirectAdInNewWindow(tab2); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example1:tagged:ff": 3, + }, + "browser.search.withads.unknown": { + "example1:tagged": 3, + }, + "browser.search.adclicks.unknown": { "example1:tagged": 1 }, + } + ); + + assertSERPTelemetry([ + { + // Tab 1 - Visit a SERP, clicked a related SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 1 - Visit a related SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a SERP, click ad opening in a new window. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + ]); + + await BrowserTestUtils.closeWindow(newWindow); + await BrowserTestUtils.removeTab(tab1); + await BrowserTestUtils.removeTab(tab2); +}); + +add_task(async function test_update_query_params_multiple_related() { + resetTelemetry(); + + let tab1 = await SinglePageAppUtils.createTabAndSearch("foo bar"); + info("Visit a related search so that the URL has an extra query parameter."); + await SinglePageAppUtils.visitRelatedSearch(tab1); + + let tab2 = await SinglePageAppUtils.createTabAndLoadURL(); + info("Visit a related search so that the URL has an extra query parameter."); + await SinglePageAppUtils.visitRelatedSearch(tab2); + + let newWindow = await SinglePageAppUtils.clickRedirectAdInNewWindow(tab2); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example1:tagged:ff": 4, + }, + "browser.search.withads.unknown": { + "example1:tagged": 4, + }, + "browser.search.adclicks.unknown": { "example1:tagged": 1 }, + } + ); + + assertSERPTelemetry([ + { + // Tab 1 - Visit a SERP, clicked a related SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 1 - Visit a related SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a SERP, clicked a related SERP. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + { + // Tab 2 - Visit a related SERP. Click on ad that opens in a new window. + impression: { + provider: "example1", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + is_private: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + adImpressions: [ + { + component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + ads_loaded: "2", + ads_visible: "2", + ads_hidden: "0", + }, + ], + }, + ]); + + await BrowserTestUtils.closeWindow(newWindow); + await BrowserTestUtils.removeTab(tab1); + await BrowserTestUtils.removeTab(tab2); +}); |