summaryrefslogtreecommitdiffstats
path: root/browser/modules/test/browser/browser_PartnerLinkAttribution.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/modules/test/browser/browser_PartnerLinkAttribution.js')
-rw-r--r--browser/modules/test/browser/browser_PartnerLinkAttribution.js428
1 files changed, 428 insertions, 0 deletions
diff --git a/browser/modules/test/browser/browser_PartnerLinkAttribution.js b/browser/modules/test/browser/browser_PartnerLinkAttribution.js
new file mode 100644
index 0000000000..08e393694d
--- /dev/null
+++ b/browser/modules/test/browser/browser_PartnerLinkAttribution.js
@@ -0,0 +1,428 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * This file tests urlbar telemetry with search related actions.
+ */
+
+"use strict";
+
+const SCALAR_URLBAR = "browser.engagement.navigation.urlbar";
+
+// The preference to enable suggestions in the urlbar.
+const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
+// The name of the search engine used to generate suggestions.
+const SUGGESTION_ENGINE_NAME =
+ "browser_UsageTelemetry usageTelemetrySearchSuggestions.xml";
+
+ChromeUtils.defineESModuleGetters(this, {
+ CustomizableUITestUtils:
+ "resource://testing-common/CustomizableUITestUtils.sys.mjs",
+
+ Region: "resource://gre/modules/Region.sys.mjs",
+ SearchTestUtils: "resource://testing-common/SearchTestUtils.sys.mjs",
+ UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.sys.mjs",
+});
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ HttpServer: "resource://testing-common/httpd.js",
+});
+
+let gCUITestUtils = new CustomizableUITestUtils(window);
+SearchTestUtils.init(this);
+
+var gHttpServer = null;
+var gRequests = [];
+
+function submitHandler(request, response) {
+ gRequests.push(request);
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+}
+
+add_setup(async function () {
+ // Ensure the initial init is complete.
+ await Services.search.init();
+
+ // Clear history so that history added by previous tests doesn't mess up this
+ // test when it selects results in the urlbar.
+ await PlacesUtils.history.clear();
+
+ let searchExtensions = getChromeDir(getResolvedURI(gTestPath));
+ searchExtensions.append("search-engines");
+
+ await SearchTestUtils.useMochitestEngines(searchExtensions);
+
+ SearchTestUtils.useMockIdleService();
+ let response = await fetch(`resource://search-extensions/engines.json`);
+ let json = await response.json();
+ await SearchTestUtils.updateRemoteSettingsConfig(json.data);
+
+ let topsitesAttribution = Services.prefs.getStringPref(
+ "browser.partnerlink.campaign.topsites"
+ );
+ gHttpServer = new HttpServer();
+ gHttpServer.registerPathHandler(`/cid/${topsitesAttribution}`, submitHandler);
+ gHttpServer.start(-1);
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ // Enable search suggestions in the urlbar.
+ [SUGGEST_URLBAR_PREF, true],
+ // Clear historical search suggestions to avoid interference from previous
+ // tests.
+ ["browser.urlbar.maxHistoricalSearchSuggestions", 0],
+ [
+ "browser.partnerlink.attributionURL",
+ `http://localhost:${gHttpServer.identity.primaryPort}/cid/`,
+ ],
+ ],
+ });
+
+ await gCUITestUtils.addSearchBar();
+
+ // Make sure to restore the engine once we're done.
+ registerCleanupFunction(async function () {
+ let settingsWritten = SearchTestUtils.promiseSearchNotification(
+ "write-settings-to-disk-complete"
+ );
+ await SearchTestUtils.updateRemoteSettingsConfig();
+ await gHttpServer.stop();
+ gHttpServer = null;
+ await PlacesUtils.history.clear();
+ gCUITestUtils.removeSearchBar();
+ await settingsWritten;
+ });
+});
+
+function searchInAwesomebar(value, win = window) {
+ return UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window: win,
+ waitForFocus,
+ value,
+ fireInputEvent: true,
+ });
+}
+
+async function searchInSearchbar(inputText) {
+ let win = window;
+ await new Promise(r => waitForFocus(r, win));
+ let sb = BrowserSearch.searchBar;
+ // Write the search query in the searchbar.
+ sb.focus();
+ sb.value = inputText;
+ sb.textbox.controller.startSearch(inputText);
+ // Wait for the popup to be shown and built.
+ let popup = sb.textbox.popup;
+ await Promise.all([
+ BrowserTestUtils.waitForEvent(popup, "popupshown"),
+ BrowserTestUtils.waitForEvent(popup.oneOffButtons, "rebuild"),
+ ]);
+ // And then for the search to complete.
+ await BrowserTestUtils.waitForCondition(
+ () =>
+ sb.textbox.controller.searchStatus >=
+ Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH,
+ "The search in the searchbar must complete."
+ );
+}
+
+add_task(async function test_simpleQuery_no_attribution() {
+ await Services.search.setDefault(
+ Services.search.getEngineByName("Simple Engine"),
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:blank"
+ );
+
+ info("Simulate entering a simple search.");
+ let promiseLoad = BrowserTestUtils.waitForDocLoadAndStopIt(
+ "https://example.com/?sourceId=Mozilla-search&search=simple+query",
+ tab
+ );
+ await searchInAwesomebar("simple query");
+ EventUtils.synthesizeKey("KEY_Enter");
+ await promiseLoad;
+
+ await new Promise(resolve => Services.tm.dispatchToMainThread(resolve));
+
+ Assert.equal(gRequests.length, 0, "Should not have submitted an attribution");
+
+ BrowserTestUtils.removeTab(tab);
+
+ await Services.search.setDefault(
+ Services.search.getEngineByName("basic"),
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+});
+
+async function checkAttributionRecorded(actionFn, cleanupFn) {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "data:text/plain;charset=utf8,simple%20query"
+ );
+
+ let promiseLoad = BrowserTestUtils.waitForDocLoadAndStopIt(
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?search=simple+query&foo=1",
+ tab
+ );
+ await actionFn(tab);
+ await promiseLoad;
+
+ await BrowserTestUtils.waitForCondition(
+ () => gRequests.length == 1,
+ "Should have received an attribution submission"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Region"),
+ Region.home,
+ "Should have set the region correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Source"),
+ "searchurl",
+ "Should have set the source correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Target-url"),
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?foo=1",
+ "Should have set the target url correctly and stripped the search terms"
+ );
+ if (cleanupFn) {
+ await cleanupFn();
+ }
+ BrowserTestUtils.removeTab(tab);
+ gRequests = [];
+}
+
+add_task(async function test_urlbar() {
+ await checkAttributionRecorded(async tab => {
+ await searchInAwesomebar("simple query");
+ EventUtils.synthesizeKey("KEY_Enter");
+ });
+});
+
+add_task(async function test_searchbar() {
+ await checkAttributionRecorded(async tab => {
+ let sb = BrowserSearch.searchBar;
+ // Write the search query in the searchbar.
+ sb.focus();
+ sb.value = "simple query";
+ sb.textbox.controller.startSearch("simple query");
+ // Wait for the popup to show.
+ await BrowserTestUtils.waitForEvent(sb.textbox.popup, "popupshown");
+ // And then for the search to complete.
+ await BrowserTestUtils.waitForCondition(
+ () =>
+ sb.textbox.controller.searchStatus >=
+ Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH,
+ "The search in the searchbar must complete."
+ );
+ EventUtils.synthesizeKey("KEY_Enter");
+ });
+});
+
+add_task(async function test_context_menu() {
+ let contextMenu;
+ await checkAttributionRecorded(
+ async tab => {
+ info("Select all the text in the page.");
+ await SpecialPowers.spawn(tab.linkedBrowser, [""], async function () {
+ return new Promise(resolve => {
+ content.document.addEventListener(
+ "selectionchange",
+ () => resolve(),
+ {
+ once: true,
+ }
+ );
+ content.document
+ .getSelection()
+ .selectAllChildren(content.document.body);
+ });
+ });
+
+ info("Open the context menu.");
+ contextMenu = document.getElementById("contentAreaContextMenu");
+ let shownPromise = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popupshown"
+ );
+ BrowserTestUtils.synthesizeMouseAtCenter(
+ "body",
+ { type: "contextmenu", button: 2 },
+ gBrowser.selectedBrowser
+ );
+ await shownPromise;
+
+ let hiddenPromise = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popuphidden"
+ );
+
+ info("Click on search.");
+ let searchItem = contextMenu.querySelector("#context-searchselect");
+ contextMenu.activateItem(searchItem);
+ await hiddenPromise;
+ },
+ () => {
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ }
+ );
+});
+
+add_task(async function test_about_newtab() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [
+ "browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar",
+ false,
+ ],
+ ],
+ });
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:newtab",
+ false
+ );
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ await ContentTaskUtils.waitForCondition(() => !content.document.hidden);
+ });
+
+ info("Trigger a simple search, just text + enter.");
+ let promiseLoad = BrowserTestUtils.waitForDocLoadAndStopIt(
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?search=simple+query&foo=1",
+ tab
+ );
+ await typeInSearchField(
+ tab.linkedBrowser,
+ "simple query",
+ "newtab-search-text"
+ );
+ await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, tab.linkedBrowser);
+ await promiseLoad;
+
+ await BrowserTestUtils.waitForCondition(
+ () => gRequests.length == 1,
+ "Should have received an attribution submission"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Region"),
+ Region.home,
+ "Should have set the region correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Source"),
+ "searchurl",
+ "Should have set the source correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Target-url"),
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?foo=1",
+ "Should have set the target url correctly and stripped the search terms"
+ );
+
+ BrowserTestUtils.removeTab(tab);
+ await SpecialPowers.popPrefEnv();
+ gRequests = [];
+});
+
+add_task(async function test_urlbar_oneOff_click() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:blank"
+ );
+
+ info("Type a query.");
+ let promiseLoad = BrowserTestUtils.waitForDocLoadAndStopIt(
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?search=query&foo=1",
+ tab
+ );
+ await searchInAwesomebar("query");
+ info("Click the first one-off button.");
+ UrlbarTestUtils.getOneOffSearchButtons(window)
+ .getSelectableButtons(false)[0]
+ .click();
+ EventUtils.synthesizeKey("KEY_Enter");
+ await promiseLoad;
+
+ await BrowserTestUtils.waitForCondition(
+ () => gRequests.length == 1,
+ "Should have received an attribution submission"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Region"),
+ Region.home,
+ "Should have set the region correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Source"),
+ "searchurl",
+ "Should have set the source correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Target-url"),
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?foo=1",
+ "Should have set the target url correctly and stripped the search terms"
+ );
+
+ BrowserTestUtils.removeTab(tab);
+ gRequests = [];
+});
+
+add_task(async function test_searchbar_oneOff_click() {
+ // For this test, set the other engine as default, so that we can select
+ // the attribution engine as the first one in the one-offs.
+ await Services.search.setDefault(
+ Services.search.getEngineByName("Simple Engine"),
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:blank"
+ );
+
+ info("Type a query.");
+ let promiseLoad = BrowserTestUtils.waitForDocLoadAndStopIt(
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?search=searchbar&foo=1",
+ tab
+ );
+ await searchInSearchbar("searchbar");
+ info("Click the first one-off button.");
+ BrowserSearch.searchBar.textbox.popup.oneOffButtons
+ .getSelectableButtons(false)[0]
+ .click();
+ await promiseLoad;
+
+ await BrowserTestUtils.waitForCondition(
+ () => gRequests.length == 1,
+ "Should have received an attribution submission"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Region"),
+ Region.home,
+ "Should have set the region correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Source"),
+ "searchurl",
+ "Should have set the source correctly"
+ );
+ Assert.equal(
+ gRequests[0].getHeader("X-Target-url"),
+ "https://mochi.test:8888/browser/browser/components/search/test/browser/?foo=1",
+ "Should have set the target url correctly and stripped the search terms"
+ );
+
+ BrowserTestUtils.removeTab(tab);
+ // Set back the engine in case of other tests in this file.
+ await Services.search.setDefault(
+ Services.search.getEngineByName("basic"),
+ Ci.nsISearchService.CHANGE_REASON_UNKNOWN
+ );
+ gRequests = [];
+});