summaryrefslogtreecommitdiffstats
path: root/browser/components/search/test
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/search/test')
-rw-r--r--browser/components/search/test/browser/browser_426329.js2
-rw-r--r--browser/components/search/test/browser/browser_contentSearch.js14
-rw-r--r--browser/components/search/test/browser/browser_contentSearchUI.js44
-rw-r--r--browser/components/search/test/browser/browser_contentSearchUI_default.js25
-rw-r--r--browser/components/search/test/browser/browser_defaultPrivate_nimbus.js45
-rw-r--r--browser/components/search/test/browser/browser_google_behavior.js4
-rw-r--r--browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js4
-rw-r--r--browser/components/search/test/browser/browser_rich_suggestions.js56
-rw-r--r--browser/components/search/test/browser/browser_searchEngine_behaviors.js12
-rw-r--r--browser/components/search/test/browser/browser_searchbar_keyboard_navigation.js16
-rw-r--r--browser/components/search/test/browser/browser_searchbar_openpopup.js9
-rw-r--r--browser/components/search/test/browser/browser_trending_suggestions.js63
-rw-r--r--browser/components/search/test/browser/contentSearchUI.html3
-rw-r--r--browser/components/search/test/browser/head.js2
-rw-r--r--browser/components/search/test/browser/telemetry/browser.toml30
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_glean_serp_event_telemetry_categorization_enabled_by_nimbus_variable.js2
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component.js41
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_children.js149
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_parent.js134
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_ad_values.js2
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_download_timer.js6
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_extraction.js191
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_region.js2
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting.js2
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer.js2
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer_wakeup.js2
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_content.js8
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_children.js480
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_parent.js434
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_ignoreLinkRegexps.js223
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_nonAdsLinkQueryParamNames.js252
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_target.js174
-rw-r--r--browser/components/search/test/browser/telemetry/browser_search_telemetry_sources_webextension.js4
-rw-r--r--browser/components/search/test/browser/telemetry/domain_category_mappings.json8
-rw-r--r--browser/components/search/test/browser/telemetry/head.js83
-rw-r--r--browser/components/search/test/browser/telemetry/searchTelemetryAd_components_cookie_banner.html16
-rw-r--r--browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html9
-rw-r--r--browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_redirecting_links.html40
-rw-r--r--browser/components/search/test/browser/telemetry/searchTelemetryDomainExtraction.html179
-rw-r--r--browser/components/search/test/browser/telemetry/searchTelemetrySinglePageApp.html4
-rw-r--r--browser/components/search/test/browser/telemetry/searchTelemetry_redirect_with_js.html25
-rw-r--r--browser/components/search/test/unit/domain_category_mappings_1a.json3
-rw-r--r--browser/components/search/test/unit/domain_category_mappings_1b.json3
-rw-r--r--browser/components/search/test/unit/domain_category_mappings_2a.json3
-rw-r--r--browser/components/search/test/unit/domain_category_mappings_2b.json3
-rw-r--r--browser/components/search/test/unit/test_search_telemetry_categorization_logic.js225
-rw-r--r--browser/components/search/test/unit/test_search_telemetry_categorization_process_domains.js89
-rw-r--r--browser/components/search/test/unit/test_search_telemetry_categorization_sync.js66
-rw-r--r--browser/components/search/test/unit/xpcshell.toml8
49 files changed, 2870 insertions, 331 deletions
diff --git a/browser/components/search/test/browser/browser_426329.js b/browser/components/search/test/browser/browser_426329.js
index 093c793048..c793f6c27e 100644
--- a/browser/components/search/test/browser/browser_426329.js
+++ b/browser/components/search/test/browser/browser_426329.js
@@ -292,7 +292,7 @@ add_task(async function testClearHistory() {
function promiseObserver(topic) {
return new Promise(resolve => {
- let obs = (aSubject, aTopic, aData) => {
+ let obs = (aSubject, aTopic) => {
Services.obs.removeObserver(obs, aTopic);
resolve(aSubject);
};
diff --git a/browser/components/search/test/browser/browser_contentSearch.js b/browser/components/search/test/browser/browser_contentSearch.js
index 7b9328fb94..07753927f1 100644
--- a/browser/components/search/test/browser/browser_contentSearch.js
+++ b/browser/components/search/test/browser/browser_contentSearch.js
@@ -50,6 +50,14 @@ add_setup(async function () {
await SearchTestUtils.promiseNewSearchEngine({
url: getRootDirectory(gTestPath) + "testEngine_chromeicon.xml",
});
+
+ // Install a WebExtension based engine to allow testing passing of plain
+ // URIs (moz-extension://) to the content process.
+ await SearchTestUtils.installSearchExtension({
+ icons: {
+ 16: "favicon.ico",
+ },
+ });
});
add_task(async function GetState() {
@@ -460,7 +468,7 @@ var currentStateObj = async function (isPrivateWindowValue, hiddenEngine = "") {
),
};
for (let engine of await Services.search.getVisibleEngines()) {
- let uri = engine.getIconURL(16);
+ let uri = await engine.getIconURL(16);
state.engines.push({
name: engine.name,
iconData: await iconDataFromURI(uri),
@@ -476,7 +484,7 @@ var currentStateObj = async function (isPrivateWindowValue, hiddenEngine = "") {
};
async function constructEngineObj(engine) {
- let uriFavicon = engine.getIconURL(16);
+ let uriFavicon = await engine.getIconURL(16);
return {
name: engine.name,
iconData: await iconDataFromURI(uriFavicon),
@@ -491,7 +499,7 @@ function iconDataFromURI(uri) {
);
}
- if (!uri.startsWith("data:")) {
+ if (!uri.startsWith("data:") && !uri.startsWith("blob:")) {
plainURIIconTested = true;
return Promise.resolve(uri);
}
diff --git a/browser/components/search/test/browser/browser_contentSearchUI.js b/browser/components/search/test/browser/browser_contentSearchUI.js
index 9196b1355c..da6044f35f 100644
--- a/browser/components/search/test/browser/browser_contentSearchUI.js
+++ b/browser/components/search/test/browser/browser_contentSearchUI.js
@@ -24,17 +24,6 @@ ChromeUtils.defineESModuleGetters(this, {
"resource://gre/modules/SearchSuggestionController.sys.mjs",
});
-const pageURL = getRootDirectory(gTestPath) + TEST_PAGE_BASENAME;
-BrowserTestUtils.registerAboutPage(
- registerCleanupFunction,
- "test-about-content-search-ui",
- pageURL,
- Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
- Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD |
- Ci.nsIAboutModule.ALLOW_SCRIPT |
- Ci.nsIAboutModule.URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS
-);
-
requestLongerTimeout(2);
function waitForSuggestions() {
@@ -261,6 +250,19 @@ let extension1;
let extension2;
add_setup(async function () {
+ const pageURL = getRootDirectory(gTestPath) + TEST_PAGE_BASENAME;
+
+ let cleanupAboutPage;
+ await BrowserTestUtils.registerAboutPage(
+ callback => (cleanupAboutPage = callback),
+ "test-about-content-search-ui",
+ pageURL,
+ Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
+ Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD |
+ Ci.nsIAboutModule.ALLOW_SCRIPT |
+ Ci.nsIAboutModule.URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS
+ );
+
let originalOnMessageSearch = ContentSearch._onMessageSearch;
let originalOnMessageManageEngines = ContentSearch._onMessageManageEngines;
@@ -290,8 +292,20 @@ add_setup(async function () {
}
registerCleanupFunction(async () => {
+ // Ensure tabs are closed before we continue on with the cleanup.
+ for (let tab of tabs) {
+ BrowserTestUtils.removeTab(tab);
+ }
+ Services.search.restoreDefaultEngines();
+
+ await TestUtils.waitForTick();
+
ContentSearch._onMessageSearch = originalOnMessageSearch;
ContentSearch._onMessageManageEngines = originalOnMessageManageEngines;
+
+ if (cleanupAboutPage) {
+ await cleanupAboutPage();
+ }
});
await promiseTab();
@@ -1096,10 +1110,6 @@ add_task(async function settings() {
await msg("reset");
});
-add_task(async function cleanup() {
- Services.search.restoreDefaultEngines();
-});
-
function checkState(
actualState,
expectedInputVal,
@@ -1147,10 +1157,10 @@ function checkState(
}
var gMsgMan;
-
+var tabs = [];
async function promiseTab() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
- registerCleanupFunction(() => BrowserTestUtils.removeTab(tab));
+ tabs.push(tab);
let loadedPromise = BrowserTestUtils.firstBrowserLoaded(window);
openTrustedLinkIn("about:test-about-content-search-ui", "current");
diff --git a/browser/components/search/test/browser/browser_contentSearchUI_default.js b/browser/components/search/test/browser/browser_contentSearchUI_default.js
index 47114fa6da..5410cfc826 100644
--- a/browser/components/search/test/browser/browser_contentSearchUI_default.js
+++ b/browser/components/search/test/browser/browser_contentSearchUI_default.js
@@ -58,11 +58,22 @@ async function ensureIcon(tab, expectedIcon) {
"Search Icon not set."
);
- Assert.equal(
- computedStyle.getPropertyValue("--newtab-search-icon"),
- `url(${icon})`,
- "Should have the expected icon"
- );
+ if (icon.startsWith("blob:")) {
+ // We don't check the data here as `browser_contentSearch.js` performs
+ // those checks.
+ Assert.ok(
+ computedStyle
+ .getPropertyValue("--newtab-search-icon")
+ .startsWith("url(blob:"),
+ "Should have a blob URL"
+ );
+ } else {
+ Assert.equal(
+ computedStyle.getPropertyValue("--newtab-search-icon"),
+ `url(${icon})`,
+ "Should have the expected icon"
+ );
+ }
}
);
}
@@ -96,7 +107,7 @@ async function runNewTabTest(isHandoff) {
waitForLoad: false,
});
- let engineIcon = defaultEngine.getIconURL(16);
+ let engineIcon = await defaultEngine.getIconURL(16);
await ensureIcon(tab, engineIcon);
if (isHandoff) {
@@ -162,7 +173,7 @@ add_task(async function test_content_search_attributes_in_private_window() {
});
let tab = win.gBrowser.selectedTab;
- let engineIcon = defaultEngine.getIconURL(16);
+ let engineIcon = await defaultEngine.getIconURL(16);
await ensureIcon(tab, engineIcon);
await ensurePlaceholder(
diff --git a/browser/components/search/test/browser/browser_defaultPrivate_nimbus.js b/browser/components/search/test/browser/browser_defaultPrivate_nimbus.js
index ce5acc91a0..41b9ce7576 100644
--- a/browser/components/search/test/browser/browser_defaultPrivate_nimbus.js
+++ b/browser/components/search/test/browser/browser_defaultPrivate_nimbus.js
@@ -31,6 +31,47 @@ const CONFIG_DEFAULT = [
},
];
+const CONFIG_V2 = [
+ {
+ recordType: "engine",
+ identifier: "basic",
+ base: {
+ name: "basic",
+ urls: {
+ search: {
+ base: "https://example.com",
+ searchTermParamName: "q",
+ },
+ },
+ },
+ variants: [{ environment: { allRegionsAndLocales: true } }],
+ },
+ {
+ recordType: "engine",
+ identifier: "private",
+ base: {
+ name: "private",
+ urls: {
+ search: {
+ base: "https://example.com",
+ searchTermParamName: "q",
+ },
+ },
+ },
+ variants: [{ environment: { allRegionsAndLocales: true } }],
+ },
+ {
+ recordType: "defaultEngines",
+ globalDefault: "basic",
+ globalDefaultPrivate: "private",
+ specificDefaults: [],
+ },
+ {
+ recordType: "engineOrders",
+ orders: [],
+ },
+];
+
SearchTestUtils.init(this);
add_setup(async () => {
@@ -50,7 +91,9 @@ add_setup(async () => {
});
SearchTestUtils.useMockIdleService();
- await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_DEFAULT);
+ await SearchTestUtils.updateRemoteSettingsConfig(
+ SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT
+ );
registerCleanupFunction(async () => {
let settingsWritten = SearchTestUtils.promiseSearchNotification(
diff --git a/browser/components/search/test/browser/browser_google_behavior.js b/browser/components/search/test/browser/browser_google_behavior.js
index cce3b3ce1f..ccc84e8bba 100644
--- a/browser/components/search/test/browser/browser_google_behavior.js
+++ b/browser/components/search/test/browser/browser_google_behavior.js
@@ -55,7 +55,7 @@ if (code) {
}
function promiseContentSearchReady(browser) {
- return SpecialPowers.spawn(browser, [], async function (args) {
+ return SpecialPowers.spawn(browser, [], async function () {
return new Promise(resolve => {
SpecialPowers.pushPrefEnv({
set: [
@@ -175,7 +175,7 @@ async function testSearchEngine(engineDetails) {
await promiseContentSearchReady(browser);
},
async run(tab) {
- await SpecialPowers.spawn(tab.linkedBrowser, [], async function (args) {
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
let input = content.document.querySelector("input[id*=search-]");
input.focus();
input.value = "foo";
diff --git a/browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js b/browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js
index 9f05e948ed..174a86ba3f 100644
--- a/browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js
+++ b/browser/components/search/test/browser/browser_oneOffContextMenu_setDefault.js
@@ -71,10 +71,10 @@ async function testSearchBarChangeEngine(win, testPrivate, isPrivateWindow) {
if (testPrivate == isPrivateWindow) {
let expectedName = originalEngine.name;
- let expectedImage = originalEngine.getIconURL();
+ let expectedImage = await originalEngine.getIconURL();
if (isPrivateWindow) {
expectedName = originalPrivateEngine.name;
- expectedImage = originalPrivateEngine.getIconURL();
+ expectedImage = await originalPrivateEngine.getIconURL();
}
Assert.equal(
diff --git a/browser/components/search/test/browser/browser_rich_suggestions.js b/browser/components/search/test/browser/browser_rich_suggestions.js
index 98adedcee5..3daefc12d9 100644
--- a/browser/components/search/test/browser/browser_rich_suggestions.js
+++ b/browser/components/search/test/browser/browser_rich_suggestions.js
@@ -17,6 +17,58 @@ 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",
+ params: [
+ {
+ name: "richsuggestions",
+ value: "true",
+ },
+ ],
+ },
+ suggestions: {
+ base: "https://example.com/browser/browser/components/search/test/browser/trendingSuggestionEngine.sjs",
+ method: "GET",
+ params: [
+ {
+ name: "richsuggestions",
+ value: "true",
+ },
+ ],
+ searchTermParamName: "query",
+ },
+ },
+ aliases: ["basic"],
+ },
+ variants: [
+ {
+ environment: { allRegionsAndLocales: true },
+ },
+ ],
+ },
+ {
+ recordType: "defaultEngines",
+ globalDefault: "basic",
+ specificDefaults: [],
+ },
+ {
+ recordType: "engineOrders",
+ orders: [],
+ },
+];
+
SearchTestUtils.init(this);
add_setup(async () => {
@@ -37,7 +89,9 @@ add_setup(async () => {
});
SearchTestUtils.useMockIdleService();
- await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_DEFAULT);
+ await SearchTestUtils.updateRemoteSettingsConfig(
+ SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT
+ );
registerCleanupFunction(async () => {
let settingsWritten = SearchTestUtils.promiseSearchNotification(
diff --git a/browser/components/search/test/browser/browser_searchEngine_behaviors.js b/browser/components/search/test/browser/browser_searchEngine_behaviors.js
index 15a30583bf..295e069857 100644
--- a/browser/components/search/test/browser/browser_searchEngine_behaviors.js
+++ b/browser/components/search/test/browser/browser_searchEngine_behaviors.js
@@ -22,9 +22,13 @@ const SEARCH_ENGINE_DETAILS = [
},
{
alias: "b",
- baseURL: `https://www.bing.com/search?{code}pc=${
- SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "MOZR" : "MOZI"
- }&q=foo`,
+ baseURL: SearchUtils.newSearchConfigEnabled
+ ? `https://www.bing.com/search?pc=${
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "MOZR" : "MOZI"
+ }&{code}q=foo`
+ : `https://www.bing.com/search?{code}pc=${
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "MOZR" : "MOZI"
+ }&q=foo`,
codes: {
context: "form=MOZCON&",
keyword: "form=MOZLBR&",
@@ -74,7 +78,7 @@ const SEARCH_ENGINE_DETAILS = [
];
function promiseContentSearchReady(browser) {
- return SpecialPowers.spawn(browser, [], async function (args) {
+ return SpecialPowers.spawn(browser, [], async function () {
SpecialPowers.pushPrefEnv({
set: [
[
diff --git a/browser/components/search/test/browser/browser_searchbar_keyboard_navigation.js b/browser/components/search/test/browser/browser_searchbar_keyboard_navigation.js
index ee292db1b5..7e2be41993 100644
--- a/browser/components/search/test/browser/browser_searchbar_keyboard_navigation.js
+++ b/browser/components/search/test/browser/browser_searchbar_keyboard_navigation.js
@@ -29,18 +29,10 @@ async function checkHeader(engine) {
// The header can be updated after getting the engine, so we may have to
// wait for it.
let header = searchPopup.searchbarEngineName;
- if (!header.getAttribute("value").includes(engine.name)) {
- await new Promise(resolve => {
- let observer = new MutationObserver(() => {
- observer.disconnect();
- resolve();
- });
- observer.observe(searchPopup.searchbarEngineName, {
- attributes: true,
- attributeFilter: ["value"],
- });
- });
- }
+ await TestUtils.waitForCondition(
+ () => header.getAttribute("value").includes(engine.name),
+ "Should have the correct engine name displayed in the header"
+ );
Assert.ok(
header.getAttribute("value").includes(engine.name),
"Should have the correct engine name displayed in the header"
diff --git a/browser/components/search/test/browser/browser_searchbar_openpopup.js b/browser/components/search/test/browser/browser_searchbar_openpopup.js
index 2653e65e8d..32c6995f69 100644
--- a/browser/components/search/test/browser/browser_searchbar_openpopup.js
+++ b/browser/components/search/test/browser/browser_searchbar_openpopup.js
@@ -126,7 +126,7 @@ add_task(async function open_empty() {
let image = searchPopup.querySelector(".searchbar-engine-image");
Assert.equal(
image.src,
- engine.getIconURL(16),
+ await engine.getIconURL(16),
"Should have the correct icon"
);
@@ -267,6 +267,13 @@ add_no_popup_task(async function right_click_doesnt_open_popup() {
context_click(textbox);
let contextPopup = await promise;
+ // Assert that the context menu click inside the popup does nothing. If it
+ // opens something, assert_no_popup_task will make us fail. On macOS this
+ // doesn't work because of native context menus.
+ if (!navigator.platform.includes("Mac")) {
+ context_click(contextPopup);
+ }
+
is(
Services.focus.focusedElement,
textbox,
diff --git a/browser/components/search/test/browser/browser_trending_suggestions.js b/browser/components/search/test/browser/browser_trending_suggestions.js
index 74d0b944d5..efe54d2da5 100644
--- a/browser/components/search/test/browser/browser_trending_suggestions.js
+++ b/browser/components/search/test/browser/browser_trending_suggestions.js
@@ -22,6 +22,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: [],
+ },
+];
+
SearchTestUtils.init(this);
add_setup(async () => {
@@ -38,7 +97,9 @@ add_setup(async () => {
});
SearchTestUtils.useMockIdleService();
- await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_DEFAULT);
+ await SearchTestUtils.updateRemoteSettingsConfig(
+ SearchUtils.newSearchConfigEnabled ? CONFIG_V2 : CONFIG_DEFAULT
+ );
Services.telemetry.clearScalars();
registerCleanupFunction(async () => {
diff --git a/browser/components/search/test/browser/contentSearchUI.html b/browser/components/search/test/browser/contentSearchUI.html
index 09abe822b2..7fa41b9d86 100644
--- a/browser/components/search/test/browser/contentSearchUI.html
+++ b/browser/components/search/test/browser/contentSearchUI.html
@@ -13,6 +13,9 @@
</head>
<body>
+<!-- Dummy Button is used to ensure pressing Shift+Tab on <input> will make the new focus
+ - remains in the same document, rather than the Chrome UI. -->
+<button>Dummy Button</button>
<div id="container"><input type="text" value=""/></div>
<script src="chrome://mochitests/content/browser/browser/components/search/test/browser/contentSearchUI.js">
diff --git a/browser/components/search/test/browser/head.js b/browser/components/search/test/browser/head.js
index 7a45a9f4f5..6051ef1caa 100644
--- a/browser/components/search/test/browser/head.js
+++ b/browser/components/search/test/browser/head.js
@@ -123,7 +123,7 @@ async function searchInSearchbar(inputText, win = window) {
return sb.textbox.popup;
}
-function clearSearchbarHistory(win = window) {
+function clearSearchbarHistory() {
info("cleanup the search history");
return FormHistory.update({ op: "remove", fieldname: "searchbar-history" });
}
diff --git a/browser/components/search/test/browser/telemetry/browser.toml b/browser/components/search/test/browser/telemetry/browser.toml
index 49d8f256aa..660fc4eae2 100644
--- a/browser/components/search/test/browser/telemetry/browser.toml
+++ b/browser/components/search/test/browser/telemetry/browser.toml
@@ -4,10 +4,7 @@ support-files = ["head.js", "head-spa.js"]
prefs = ["browser.search.log=true"]
["browser_search_glean_serp_event_telemetry_categorization_enabled_by_nimbus_variable.js"]
-support-files = [
- "domain_category_mappings.json",
- "searchTelemetryDomainCategorizationReporting.html",
-]
+support-files = ["searchTelemetryDomainCategorizationReporting.html"]
["browser_search_glean_serp_event_telemetry_enabled_by_nimbus_variable.js"]
support-files = ["searchTelemetryAd.html"]
@@ -31,9 +28,16 @@ support-files = [
"searchTelemetryAd_components_carousel_outer_container.html",
"searchTelemetryAd_components_text.html",
"searchTelemetryAd_components_visibility.html",
+ "searchTelemetryAd_components_cookie_banner.html",
"serp.css",
]
+["browser_search_telemetry_adImpression_component_skipCount_children.js"]
+support-files = ["searchTelemetryAd_searchbox_with_content.html", "serp.css"]
+
+["browser_search_telemetry_adImpression_component_skipCount_parent.js"]
+support-files = ["searchTelemetryAd_searchbox_with_content.html", "serp.css"]
+
["browser_search_telemetry_categorization_timing.js"]
["browser_search_telemetry_content.js"]
@@ -42,7 +46,6 @@ support-files = [
support-files = ["searchTelemetryDomainCategorizationReporting.html"]
["browser_search_telemetry_domain_categorization_download_timer.js"]
-support-files = ["domain_category_mappings.json"]
["browser_search_telemetry_domain_categorization_extraction.js"]
support-files = ["searchTelemetryDomainExtraction.html"]
@@ -85,6 +88,15 @@ support-files = [
"serp.css",
]
+["browser_search_telemetry_engagement_eventListeners_children.js"]
+support-files = ["searchTelemetryAd_searchbox_with_content.html", "serp.css"]
+
+["browser_search_telemetry_engagement_eventListeners_parent.js"]
+support-files = ["searchTelemetryAd_searchbox_with_content.html", "serp.css"]
+
+["browser_search_telemetry_engagement_ignoreLinkRegexps.js"]
+support-files = ["searchTelemetryAd_searchbox_with_content.html", "serp.css"]
+
["browser_search_telemetry_engagement_multiple_tabs.js"]
support-files = [
"searchTelemetryAd_searchbox_with_content.html",
@@ -98,6 +110,14 @@ support-files = [
"serp.css",
]
+["browser_search_telemetry_engagement_nonAdsLinkQueryParamNames.js"]
+support-files = [
+ "searchTelemetryAd_searchbox_with_redirecting_links.html",
+ "searchTelemetryAd_shopping.html",
+ "searchTelemetry_redirect_with_js.html",
+ "serp.css",
+]
+
["browser_search_telemetry_engagement_query_params.js"]
support-files = [
"searchTelemetryAd_components_query_parameters.html",
diff --git a/browser/components/search/test/browser/telemetry/browser_search_glean_serp_event_telemetry_categorization_enabled_by_nimbus_variable.js b/browser/components/search/test/browser/telemetry/browser_search_glean_serp_event_telemetry_categorization_enabled_by_nimbus_variable.js
index ed71a7c5ed..e73a9601d4 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_glean_serp_event_telemetry_categorization_enabled_by_nimbus_variable.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_glean_serp_event_telemetry_categorization_enabled_by_nimbus_variable.js
@@ -38,7 +38,7 @@ const TEST_PROVIDER_INFO = [
ads: [
{
selectors: "[data-ad-domain]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "adDomain",
},
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component.js
index 8049406d40..5a09353ed6 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component.js
@@ -78,6 +78,15 @@ const TEST_PROVIDER_INFO = [
type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
default: true,
},
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ included: {
+ parent: {
+ selector: "#banner",
+ },
+ },
+ topDown: true,
+ },
],
},
];
@@ -500,3 +509,35 @@ add_task(async function test_impressions_without_ads() {
BrowserTestUtils.removeTab(tab);
});
+
+add_task(async function test_ad_impressions_with_cookie_banner() {
+ resetTelemetry();
+ let url = getSERPUrl("searchTelemetryAd_components_cookie_banner.html");
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+
+ await waitForPageWithAdImpressions();
+
+ assertSERPTelemetry([
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+ },
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ BrowserTestUtils.removeTab(tab);
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_children.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_children.js
new file mode 100644
index 0000000000..65cd612a49
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_children.js
@@ -0,0 +1,149 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests skipCount property on elements in the children.
+ */
+
+const TEST_PROVIDER_INFO = [
+ {
+ telemetryId: "example",
+ searchPageRegexp:
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd/,
+ queryParamNames: ["s"],
+ codeParamName: "abc",
+ taggedCodes: ["ff"],
+ adServerAttributes: ["mozAttr"],
+ extraAdServersRegexps: [/^https:\/\/example\.com\/ad/],
+ },
+];
+
+const IMPRESSION = {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+};
+
+const SERP_URL = getSERPUrl("searchTelemetryAd_searchbox_with_content.html");
+
+async function replaceIncludedProperty(included) {
+ let components = [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ included,
+ topDown: true,
+ },
+ ];
+ TEST_PROVIDER_INFO[0].components = components;
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+}
+
+add_setup(async function () {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+ // Enable local telemetry recording for the duration of the tests.
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
+ registerCleanupFunction(async () => {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests();
+ Services.telemetry.canRecordExtended = oldCanRecord;
+ resetTelemetry();
+ });
+});
+
+// For older clients, skipCount won't be available.
+add_task(async function test_skip_count_not_provided() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ },
+ children: [
+ {
+ selector: "a",
+ },
+ ],
+ });
+
+ let { cleanup } = await openSerpInNewTab(SERP_URL);
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_skip_count_is_false() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ },
+ children: [
+ {
+ selector: "a",
+ skipCount: false,
+ },
+ ],
+ });
+
+ let { cleanup } = await openSerpInNewTab(SERP_URL);
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_skip_count_is_true() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ },
+ children: [
+ {
+ selector: "a",
+ skipCount: true,
+ },
+ ],
+ });
+
+ let { cleanup } = await openSerpInNewTab(SERP_URL);
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ adImpressions: [],
+ },
+ ]);
+
+ await cleanup();
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_parent.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_parent.js
new file mode 100644
index 0000000000..8471215840
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_adImpression_component_skipCount_parent.js
@@ -0,0 +1,134 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests skipCount property on parent elements.
+ */
+
+const TEST_PROVIDER_INFO = [
+ {
+ telemetryId: "example",
+ searchPageRegexp:
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd/,
+ queryParamNames: ["s"],
+ codeParamName: "abc",
+ taggedCodes: ["ff"],
+ adServerAttributes: ["mozAttr"],
+ extraAdServersRegexps: [/^https:\/\/example\.com\/ad/],
+ },
+];
+
+const IMPRESSION = {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+};
+
+const SERP_URL = getSERPUrl("searchTelemetryAd_searchbox_with_content.html");
+
+async function replaceIncludedProperty(included) {
+ let components = [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ included,
+ topDown: true,
+ },
+ ];
+ TEST_PROVIDER_INFO[0].components = components;
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+}
+
+add_setup(async function () {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+ // Enable local telemetry recording for the duration of the tests.
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
+ registerCleanupFunction(async () => {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests();
+ Services.telemetry.canRecordExtended = oldCanRecord;
+ resetTelemetry();
+ });
+});
+
+// For older clients, skipCount won't be available.
+add_task(async function test_skip_count_not_provided() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ },
+ });
+
+ let { cleanup } = await openSerpInNewTab(SERP_URL);
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_skip_count_is_false() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: false,
+ },
+ });
+
+ let { cleanup } = await openSerpInNewTab(SERP_URL);
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_skip_count_is_true() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ });
+
+ let { cleanup } = await openSerpInNewTab(SERP_URL);
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ adImpressions: [],
+ },
+ ]);
+
+ await cleanup();
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_ad_values.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_ad_values.js
index ce18f64e9f..246caf6f47 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_ad_values.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_ad_values.js
@@ -30,7 +30,7 @@ const TEST_PROVIDER_INFO = [
ads: [
{
selectors: "[data-ad-domain]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "adDomain",
},
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_download_timer.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_download_timer.js
index d01141d826..b8dd85da97 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_download_timer.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_download_timer.js
@@ -33,7 +33,7 @@ const TEST_PROVIDER_INFO = [
ads: [
{
selectors: "[data-ad-domain]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "adDomain",
},
@@ -119,6 +119,7 @@ add_task(async function test_download_after_failure() {
id: "example_id",
version: 1,
filename: "domain_category_mappings.json",
+ mapping: CONVERTED_ATTACHMENT_VALUES,
});
await db.create(record);
await db.importChanges({}, Date.now());
@@ -173,6 +174,7 @@ add_task(async function test_download_after_multiple_failures() {
id: "example_id",
version: 1,
filename: "domain_category_mappings.json",
+ mapping: CONVERTED_ATTACHMENT_VALUES,
});
await db.create(record);
await db.importChanges({}, Date.now());
@@ -220,6 +222,7 @@ add_task(async function test_cancel_download_timer() {
id: "example_id",
version: 1,
filename: "domain_category_mappings.json",
+ mapping: CONVERTED_ATTACHMENT_VALUES,
});
await db.create(record);
await db.importChanges({}, Date.now());
@@ -277,6 +280,7 @@ add_task(async function test_download_adjust() {
id: "example_id",
version: 1,
filename: "domain_category_mappings.json",
+ mapping: CONVERTED_ATTACHMENT_VALUES,
});
await db.create(record);
await db.importChanges({}, Date.now());
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_extraction.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_extraction.js
index 03ddb75481..e653be6c48 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_extraction.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_extraction.js
@@ -11,6 +11,10 @@ ChromeUtils.defineESModuleGetters(this, {
SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs",
});
+// The search provider's name is provided to ensure we can extract domains
+// from relative links, e.g. /url?=https://www.foobar.com
+const SEARCH_PROVIDER_NAME = "example";
+
const TESTS = [
{
title: "Extract domain from href (absolute URL) - one link.",
@@ -35,7 +39,7 @@ const TESTS = [
expectedDomains: ["foo.com", "bar.com", "baz.com", "qux.com"],
},
{
- title: "Extract domain from href (relative URL).",
+ title: "Extract domain from href (relative URL / URL matching provider)",
extractorInfos: [
{
selectors:
@@ -43,38 +47,33 @@ const TESTS = [
method: "href",
},
],
- expectedDomains: ["example.org"],
+ expectedDomains: [],
},
{
title: "Extract domain from data attribute - one link.",
extractorInfos: [
{
selectors: "#test4 [data-dtld]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "dtld",
},
},
],
- expectedDomains: ["www.abc.com"],
+ expectedDomains: ["abc.com"],
},
{
title: "Extract domain from data attribute - multiple links.",
extractorInfos: [
{
selectors: "#test5 [data-dtld]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "dtld",
},
},
],
- expectedDomains: [
- "www.foo.com",
- "www.bar.com",
- "www.baz.com",
- "www.qux.com",
- ],
+ expectedDomains: ["foo.com", "bar.com", "baz.com", "qux.com"],
},
{
title: "Extract domain from an href's query param value.",
@@ -88,7 +87,7 @@ const TESTS = [
},
},
],
- expectedDomains: ["def.com"],
+ expectedDomains: ["def.com", "bar.com", "baz.com"],
},
{
title:
@@ -144,7 +143,7 @@ const TESTS = [
},
{
selectors: "#test10 [data-dtld]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "dtld",
},
@@ -158,7 +157,7 @@ const TESTS = [
},
},
],
- expectedDomains: ["foobar.com", "www.abc.com", "def.com"],
+ expectedDomains: ["foobar.com", "abc.com", "def.com"],
},
{
title: "No elements match the selectors.",
@@ -176,7 +175,7 @@ const TESTS = [
extractorInfos: [
{
selectors: "#test12 [data-dtld]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "dtld",
},
@@ -208,6 +207,161 @@ const TESTS = [
],
expectedDomains: [],
},
+ {
+ title: "Second-level domains to a top-level domain.",
+ extractorInfos: [
+ {
+ selectors: "#test15 a",
+ method: "href",
+ },
+ ],
+ expectedDomains: [
+ "foobar.gc.ca",
+ "foobar.gov.uk",
+ "foobar.co.uk",
+ "foobar.co.il",
+ ],
+ },
+ {
+ title: "URL with a long subdomain.",
+ extractorInfos: [
+ {
+ selectors: "#test16 a",
+ method: "href",
+ },
+ ],
+ expectedDomains: ["foobar.com"],
+ },
+ {
+ title: "URLs with the same top level domain.",
+ extractorInfos: [
+ {
+ selectors: "#test17 a",
+ method: "href",
+ },
+ ],
+ expectedDomains: ["foobar.com"],
+ },
+ {
+ title: "Maximum domains extracted from a single selector.",
+ extractorInfos: [
+ {
+ selectors: "#test18 a",
+ method: "href",
+ },
+ ],
+ expectedDomains: [
+ "foobar1.com",
+ "foobar2.com",
+ "foobar3.com",
+ "foobar4.com",
+ "foobar5.com",
+ "foobar6.com",
+ "foobar7.com",
+ "foobar8.com",
+ "foobar9.com",
+ "foobar10.com",
+ ],
+ },
+ {
+ // This is just in case we use multiple selectors meant for separate SERPs
+ // and the provider switches to re-using their markup.
+ title: "Maximum domains extracted from multiple matching selectors.",
+ extractorInfos: [
+ {
+ selectors: "#test19 a.foo",
+ method: "href",
+ },
+ {
+ selectors: "#test19 a.baz",
+ method: "href",
+ },
+ ],
+ expectedDomains: [
+ "foobar1.com",
+ "foobar2.com",
+ "foobar3.com",
+ "foobar4.com",
+ "foobar5.com",
+ "foobar6.com",
+ "foobar7.com",
+ "foobar8.com",
+ "foobar9.com",
+ // This is from the second selector.
+ "foobaz1.com",
+ ],
+ },
+ {
+ title: "Bing organic result.",
+ extractorInfos: [
+ {
+ selectors: "#test20 #b_results .b_algo .b_attribution cite",
+ method: "textContent",
+ },
+ ],
+ expectedDomains: ["organic.com"],
+ },
+ {
+ title: "Bing sponsored result.",
+ extractorInfos: [
+ {
+ selectors: "#test21 #b_results .b_ad .b_attribution cite",
+ method: "textContent",
+ },
+ ],
+ expectedDomains: ["sponsored.com"],
+ },
+ {
+ title: "Bing carousel result.",
+ extractorInfos: [
+ {
+ selectors: "#test22 .adsMvCarousel cite",
+ method: "textContent",
+ },
+ ],
+ expectedDomains: ["fixedupfromthecarousel.com"],
+ },
+ {
+ title: "Bing sidebar result.",
+ extractorInfos: [
+ {
+ selectors: "#test23 aside cite",
+ method: "textContent",
+ },
+ ],
+ expectedDomains: ["fixedupfromthesidebar.com"],
+ },
+ {
+ title: "Extraction threshold respected using text content method.",
+ extractorInfos: [
+ {
+ selectors: "#test24 #b_results .b_ad .b_attribution cite",
+ method: "textContent",
+ },
+ ],
+ expectedDomains: [
+ "sponsored1.com",
+ "sponsored2.com",
+ "sponsored3.com",
+ "sponsored4.com",
+ "sponsored5.com",
+ "sponsored6.com",
+ "sponsored7.com",
+ "sponsored8.com",
+ "sponsored9.com",
+ "sponsored10.com",
+ ],
+ },
+ {
+ title: "Bing organic result with no protocol.",
+ extractorInfos: [
+ {
+ selectors: "#test25 #b_results .b_algo .b_attribution cite",
+ method: "textContent",
+ },
+ ],
+ expectedDomains: ["organic.com"],
+ },
];
add_setup(async function () {
@@ -240,14 +394,15 @@ add_task(async function test_domain_extraction_heuristics() {
let expectedDomains = new Set(currentTest.expectedDomains);
let actualDomains = await SpecialPowers.spawn(
gBrowser.selectedBrowser,
- [currentTest.extractorInfos],
- extractorInfos => {
+ [currentTest.extractorInfos, SEARCH_PROVIDER_NAME],
+ (extractorInfos, searchProviderName) => {
const { domainExtractor } = ChromeUtils.importESModule(
"resource:///actors/SearchSERPTelemetryChild.sys.mjs"
);
return domainExtractor.extractDomainsFromDocument(
content.document,
- extractorInfos
+ extractorInfos,
+ searchProviderName
);
}
);
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_region.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_region.js
index f328bb4f79..4c47b0b14a 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_region.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_region.js
@@ -30,7 +30,7 @@ const TEST_PROVIDER_INFO = [
ads: [
{
selectors: "[data-ad-domain]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "adDomain",
},
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting.js
index b7edb8763f..973f17b760 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting.js
@@ -30,7 +30,7 @@ const TEST_PROVIDER_INFO = [
ads: [
{
selectors: "[data-ad-domain]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "adDomain",
},
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer.js
index cfb8590960..9d3ac2c931 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer.js
@@ -31,7 +31,7 @@ const TEST_PROVIDER_INFO = [
ads: [
{
selectors: "[data-ad-domain]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "adDomain",
},
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer_wakeup.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer_wakeup.js
index cb95164221..c73e224eae 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer_wakeup.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_domain_categorization_reporting_timer_wakeup.js
@@ -32,7 +32,7 @@ const TEST_PROVIDER_INFO = [
ads: [
{
selectors: "[data-ad-domain]",
- method: "data-attribute",
+ method: "dataAttribute",
options: {
dataAttributeKey: "adDomain",
},
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_content.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_content.js
index a7ea62ebd5..f94e6b0bd8 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_content.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_content.js
@@ -138,8 +138,8 @@ add_task(async function test_click_tab() {
{
impression: {
provider: "example",
- tagged: "false",
- partner_code: "",
+ tagged: "true",
+ partner_code: "ff",
source: "unknown",
is_shopping_page: "false",
is_private: "false",
@@ -217,8 +217,8 @@ add_task(async function test_click_shopping() {
{
impression: {
provider: "example",
- tagged: "false",
- partner_code: "",
+ tagged: "true",
+ partner_code: "ff",
source: "unknown",
is_shopping_page: "true",
is_private: "false",
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_children.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_children.js
new file mode 100644
index 0000000000..4f5aaf9378
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_children.js
@@ -0,0 +1,480 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests eventListeners property on children elements in topDown searches.
+ */
+
+const TEST_PROVIDER_INFO = [
+ {
+ telemetryId: "example",
+ searchPageRegexp:
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd/,
+ queryParamNames: ["s"],
+ codeParamName: "abc",
+ taggedCodes: ["ff"],
+ adServerAttributes: ["mozAttr"],
+ extraAdServersRegexps: [/^https:\/\/example\.com\/ad/],
+ },
+];
+
+const IMPRESSION = {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+};
+
+const SELECTOR = ".arrow";
+const SERP_URL = getSERPUrl("searchTelemetryAd_searchbox_with_content.html");
+
+async function replaceIncludedProperty(included) {
+ TEST_PROVIDER_INFO[0].components = [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ included,
+ topDown: true,
+ },
+ ];
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+}
+
+add_setup(async function () {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+ // Enable local telemetry recording for the duration of the tests.
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
+ registerCleanupFunction(async () => {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests();
+ Services.telemetry.canRecordExtended = oldCanRecord;
+ resetTelemetry();
+ });
+});
+
+add_task(async function test_listeners_not_provided() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ expectEngagement: false,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_no_listeners() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ eventListeners: [],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ expectEngagement: false,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_click_listener() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ eventListeners: [{ eventType: "click" }],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: ".arrow-next",
+ tab,
+ });
+ await synthesizePageAction({
+ selector: ".arrow-prev",
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+/**
+ * The click event is by far our most used event so by default, we translate
+ * a "click" eventType to a "clicked" action. If no action is provided for
+ * another type of event, nothing should be reported.
+ */
+add_task(async function test_event_with_no_default_action() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ eventListeners: [{ eventType: "mousedown" }],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ expectEngagement: false,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_event_no_default_action_with_override() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "mousedown",
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ },
+ ],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_target_override() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ eventListeners: [{ eventType: "click", target: "custom_target" }],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: "custom_target",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_target_and_action_override() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "click",
+ action: "custom_action",
+ target: "custom_target",
+ },
+ ],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "custom_action",
+ target: "custom_target",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_multiple_listeners() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: " .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "click",
+ },
+ {
+ eventType: "mouseover",
+ action: "mouseovered",
+ },
+ ],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ event: {
+ type: "mouseover",
+ },
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "clicked",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ {
+ action: "mouseovered",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_condition() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: ".arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "keydown",
+ action: "keydowned",
+ condition: "keydownEnter",
+ },
+ ],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [SELECTOR], async function (s) {
+ let el = content.document.querySelector(s);
+ el.focus();
+ });
+
+ await EventUtils.synthesizeKey("A");
+ /* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
+ await new Promise(resolve => setTimeout(resolve, 10));
+
+ let pageActionPromise = waitForPageWithAction();
+ await EventUtils.synthesizeKey("KEY_Enter");
+ await pageActionPromise;
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "keydowned",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_condition_invalid() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons",
+ skipCount: true,
+ },
+ children: [
+ {
+ selector: ".arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "keydown",
+ action: "keydowned",
+ condition: "noConditionExistsWithThisName",
+ },
+ ],
+ },
+ ],
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [SELECTOR], async function (s) {
+ let el = content.document.querySelector(s);
+ el.focus();
+ });
+
+ await EventUtils.synthesizeKey("A");
+ /* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
+ await new Promise(resolve => setTimeout(resolve, 10));
+
+ await EventUtils.synthesizeKey("KEY_Enter");
+ /* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
+ await new Promise(resolve => setTimeout(resolve, 10));
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_parent.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_parent.js
new file mode 100644
index 0000000000..4e3c635b4c
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_eventListeners_parent.js
@@ -0,0 +1,434 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests eventListeners property on parent elements in topDown searches.
+ */
+
+const TEST_PROVIDER_INFO = [
+ {
+ telemetryId: "example",
+ searchPageRegexp:
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd/,
+ queryParamNames: ["s"],
+ codeParamName: "abc",
+ taggedCodes: ["ff"],
+ adServerAttributes: ["mozAttr"],
+ extraAdServersRegexps: [/^https:\/\/example\.com\/ad/],
+ },
+];
+
+// The impression doesn't change in these tests.
+const IMPRESSION = {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+};
+
+const SELECTOR = ".arrow";
+const SERP_URL = getSERPUrl("searchTelemetryAd_searchbox_with_content.html");
+
+async function replaceIncludedProperty(included) {
+ TEST_PROVIDER_INFO[0].components = [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ included,
+ topDown: true,
+ },
+ ];
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+}
+
+add_setup(async function () {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+ // Enable local telemetry recording for the duration of the tests.
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
+ registerCleanupFunction(async () => {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests();
+ Services.telemetry.canRecordExtended = oldCanRecord;
+ resetTelemetry();
+ });
+});
+
+add_task(async function test_listeners_not_provided() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ expectEngagement: false,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_no_listeners() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ expectEngagement: false,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_click_listener() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "click",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: ".arrow-next",
+ tab,
+ });
+ await synthesizePageAction({
+ selector: ".arrow-prev",
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+/**
+ * The click event is by far our most used event so by default, we translate
+ * a "click" eventType to a "clicked" action. If no action is provided for
+ * another type of event, nothing should be reported.
+ */
+add_task(async function test_event_with_no_default_action_parent() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "mousedown",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ expectEngagement: false,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_event_no_default_action_with_override() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "mousedown",
+ action: "clicked",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "clicked",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_target_override() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "click",
+ target: "custom_target",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "clicked",
+ target: "custom_target",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_target_and_action_override() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "click",
+ target: "custom_target",
+ action: "custom_action",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "custom_action",
+ target: "custom_target",
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_multiple_listeners() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "click",
+ action: "clicked",
+ },
+ {
+ eventType: "mouseover",
+ action: "mouseovered",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ });
+ await synthesizePageAction({
+ selector: SELECTOR,
+ tab,
+ event: {
+ type: "mouseover",
+ },
+ });
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "clicked",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ {
+ action: "mouseovered",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_condition() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "keydown",
+ action: "keydowned",
+ condition: "keydownEnter",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [SELECTOR], async function (s) {
+ let el = content.document.querySelector(s);
+ el.focus();
+ });
+
+ await EventUtils.synthesizeKey("A");
+ /* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
+ await new Promise(resolve => setTimeout(resolve, 10));
+
+ let pageActionPromise = waitForPageWithAction();
+ await EventUtils.synthesizeKey("KEY_Enter");
+ await pageActionPromise;
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "keydowned",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_condition_invalid() {
+ await replaceIncludedProperty({
+ parent: {
+ selector: ".refined-search-buttons .arrow",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "keydown",
+ action: "keydowned",
+ condition: "noConditionExistsWithThisName",
+ },
+ ],
+ },
+ });
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [SELECTOR], async function (s) {
+ let el = content.document.querySelector(s);
+ el.focus();
+ });
+
+ await EventUtils.synthesizeKey("A");
+ /* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
+ await new Promise(resolve => setTimeout(resolve, 10));
+
+ await EventUtils.synthesizeKey("KEY_Enter");
+ /* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
+ await new Promise(resolve => setTimeout(resolve, 10));
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_ignoreLinkRegexps.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_ignoreLinkRegexps.js
new file mode 100644
index 0000000000..10f2a2d836
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_ignoreLinkRegexps.js
@@ -0,0 +1,223 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests ignoreLinkRegexps property in search telemetry that explicitly results
+ * in our network code ignoring the link. The main reason for doing so is for
+ * rare situations where we need to find a components from a topDown approach
+ * but it loads a page in the network process.
+ */
+
+const TEST_PROVIDER_INFO = [
+ {
+ telemetryId: "example",
+ searchPageRegexp:
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd/,
+ queryParamNames: ["s"],
+ codeParamName: "abc",
+ taggedCodes: ["ff"],
+ adServerAttributes: ["mozAttr"],
+ extraAdServersRegexps: [/^https:\/\/example\.com\/ad/],
+ ignoreLinkRegexps: [
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd_searchbox_with_content.html\?s=test&page=images/,
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd_searchbox_with_content.html\?s=test&page=shopping/,
+ ],
+ components: [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
+ default: true,
+ },
+ ],
+ hrefToComponentMapAugmentation: [
+ {
+ action: "clicked_something",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ url: "https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox.html",
+ },
+ ],
+ },
+];
+
+// The impression doesn't change in these tests.
+const IMPRESSION = {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+};
+
+const SERP_URL = getSERPUrl("searchTelemetryAd_searchbox_with_content.html");
+
+async function replaceIncludedProperty(included) {
+ TEST_PROVIDER_INFO[0].components = [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ included,
+ topDown: true,
+ },
+ ];
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+}
+
+add_setup(async function () {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+ // Enable local telemetry recording for the duration of the tests.
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+
+ registerCleanupFunction(async () => {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests();
+ Services.telemetry.canRecordExtended = oldCanRecord;
+ resetTelemetry();
+ });
+});
+
+add_task(async function test_click_link_1_matching_ignore_link_regexps() {
+ resetTelemetry();
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ let promise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#images",
+ {},
+ tab.linkedBrowser
+ );
+ await promise;
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ abandonment: {
+ reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
+ },
+ },
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_click_link_2_matching_ignore_link_regexps() {
+ resetTelemetry();
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ let promise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#shopping",
+ {},
+ tab.linkedBrowser
+ );
+ await promise;
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ abandonment: {
+ reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
+ },
+ },
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_click_link_3_not_matching_ignore_link_regexps() {
+ resetTelemetry();
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ let promise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#extra",
+ {},
+ tab.linkedBrowser
+ );
+ await promise;
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "clicked",
+ target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
+ },
+ ],
+ },
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
+
+add_task(async function test_click_listener_with_ignore_link_regexps() {
+ resetTelemetry();
+
+ TEST_PROVIDER_INFO[0].components = [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ topDown: true,
+ included: {
+ parent: {
+ selector: "nav a",
+ skipCount: true,
+ eventListeners: [
+ {
+ eventType: "click",
+ action: "clicked",
+ },
+ ],
+ },
+ },
+ },
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
+ default: true,
+ },
+ ];
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+
+ let { tab, cleanup } = await openSerpInNewTab(SERP_URL);
+
+ let promise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#images",
+ {},
+ tab.linkedBrowser
+ );
+ await promise;
+
+ assertSERPTelemetry([
+ {
+ impression: IMPRESSION,
+ engagements: [
+ {
+ action: "clicked",
+ target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
+ },
+ ],
+ },
+ {
+ impression: IMPRESSION,
+ },
+ ]);
+
+ await cleanup();
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_nonAdsLinkQueryParamNames.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_nonAdsLinkQueryParamNames.js
new file mode 100644
index 0000000000..93a6b7993e
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_nonAdsLinkQueryParamNames.js
@@ -0,0 +1,252 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * These tests load SERPs and click on links.
+ */
+
+"use strict";
+
+const TEST_PROVIDER_INFO = [
+ {
+ telemetryId: "example",
+ searchPageRegexp:
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetry/,
+ queryParamNames: ["s"],
+ codeParamName: "abc",
+ taggedCodes: ["ff"],
+ adServerAttributes: ["mozAttr"],
+ nonAdsLinkRegexps: [
+ /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetry_redirect_with_js/,
+ ],
+ nonAdsLinkQueryParamNames: ["url"],
+ extraAdServersRegexps: [/^https:\/\/example\.com\/ad/],
+ shoppingTab: {
+ regexp: "&page=shopping",
+ selector: "nav a",
+ inspectRegexpInSERP: true,
+ },
+ components: [
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
+ default: true,
+ },
+ ],
+ },
+];
+
+add_setup(async function () {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+
+ registerCleanupFunction(async () => {
+ SearchSERPTelemetry.overrideSearchTelemetryForTests();
+ resetTelemetry();
+ });
+});
+
+add_task(async function test_click_absolute_url_in_query_param() {
+ resetTelemetry();
+
+ let url = getSERPUrl(
+ "searchTelemetryAd_searchbox_with_redirecting_links.html"
+ );
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ await waitForPageWithAdImpressions();
+
+ let browserLoadedPromise = BrowserTestUtils.browserLoaded(
+ tab.linkedBrowser,
+ true
+ );
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#shopping-redirect-absolute-link",
+ {},
+ tab.linkedBrowser
+ );
+ await browserLoadedPromise;
+ await waitForPageWithAdImpressions();
+
+ assertSERPTelemetry([
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "true",
+ },
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
+ },
+ ],
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "true",
+ is_private: "false",
+ shopping_tab_displayed: "true",
+ },
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ BrowserTestUtils.removeTab(tab);
+
+ // Reset state for other tests.
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+});
+
+add_task(async function test_click_relative_href_in_query_param() {
+ resetTelemetry();
+
+ let url = getSERPUrl(
+ "searchTelemetryAd_searchbox_with_redirecting_links.html"
+ );
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ await waitForPageWithAdImpressions();
+
+ let browserLoadedPromise = BrowserTestUtils.browserLoaded(
+ tab.linkedBrowser,
+ true
+ );
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#shopping-redirect-relative-link",
+ {},
+ tab.linkedBrowser
+ );
+ await browserLoadedPromise;
+ await waitForPageWithAdImpressions();
+
+ assertSERPTelemetry([
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "true",
+ },
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
+ },
+ ],
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "true",
+ is_private: "false",
+ shopping_tab_displayed: "true",
+ },
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ BrowserTestUtils.removeTab(tab);
+
+ // Reset state for other tests.
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+});
+
+add_task(async function test_click_irrelevant_href_in_query_param() {
+ resetTelemetry();
+
+ let url = getSERPUrl(
+ "searchTelemetryAd_searchbox_with_redirecting_links.html"
+ );
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ await waitForPageWithAdImpressions();
+
+ let browserLoadedPromise = BrowserTestUtils.browserLoaded(
+ tab.linkedBrowser,
+ true,
+ "https://example.org/foo/bar"
+ );
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#organic-redirect",
+ {},
+ tab.linkedBrowser
+ );
+ await browserLoadedPromise;
+
+ assertSERPTelemetry([
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "true",
+ },
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
+ target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
+ },
+ ],
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ BrowserTestUtils.removeTab(tab);
+
+ // Reset state for other tests.
+ SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
+ await waitForIdle();
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_target.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_target.js
index b30a7bc0c1..8f7f7f4e05 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_target.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_engagement_target.js
@@ -22,6 +22,7 @@ const TEST_PROVIDER_INFO = [
/^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetryAd_nonAdsLink_redirect.html/,
],
extraAdServersRegexps: [/^https:\/\/example\.com\/ad/],
+ ignoreLinkRegexps: [/^https:\/\/example\.org\/consent\?data=/],
components: [
{
type: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
@@ -90,6 +91,44 @@ const TEST_PROVIDER_INFO = [
type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
default: true,
},
+ {
+ type: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ topDown: true,
+ included: {
+ parent: {
+ selector: "#banner",
+ },
+ children: [
+ {
+ selector: "#cookie_accept",
+ eventListeners: [
+ {
+ eventType: "click",
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED_ACCEPT,
+ },
+ ],
+ },
+ {
+ selector: "#cookie_reject",
+ eventListeners: [
+ {
+ eventType: "click",
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED_REJECT,
+ },
+ ],
+ },
+ {
+ selector: "#cookie_more_options",
+ eventListeners: [
+ {
+ eventType: "click",
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED_MORE_OPTIONS,
+ },
+ ],
+ },
+ ],
+ },
+ },
],
},
];
@@ -455,3 +494,138 @@ add_task(async function test_click_link_with_special_characters_in_path() {
SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
await waitForIdle();
});
+
+// Test that clicking the accept button on the cookie banner is correctly
+// tracked as an engagement event.
+add_task(async function test_click_cookie_banner_accept() {
+ resetTelemetry();
+ let url = getSERPUrl("searchTelemetryAd_components_cookie_banner.html");
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ await waitForPageWithAdImpressions();
+
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#cookie_accept",
+ {},
+ tab.linkedBrowser
+ );
+
+ assertSERPTelemetry([
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+ },
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED_ACCEPT,
+ target: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ },
+ ],
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+// Test that clicking the reject button on the cookie banner is accurately
+// recorded as an engagement event.
+add_task(async function test_click_cookie_banner_reject() {
+ resetTelemetry();
+ let url = getSERPUrl("searchTelemetryAd_components_cookie_banner.html");
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ await waitForPageWithAdImpressions();
+
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#cookie_reject",
+ {},
+ tab.linkedBrowser
+ );
+
+ assertSERPTelemetry([
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+ },
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED_REJECT,
+ target: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ },
+ ],
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+// Test that clicking the more options button on the cookie banner is accurately
+// recorded as an engagement event.
+add_task(async function test_click_cookie_banner_more_options() {
+ resetTelemetry();
+ let url = getSERPUrl("searchTelemetryAd_components_cookie_banner.html");
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ await waitForPageWithAdImpressions();
+
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#cookie_more_options",
+ {},
+ tab.linkedBrowser
+ );
+
+ assertSERPTelemetry([
+ {
+ impression: {
+ provider: "example",
+ tagged: "true",
+ partner_code: "ff",
+ source: "unknown",
+ is_shopping_page: "false",
+ is_private: "false",
+ shopping_tab_displayed: "false",
+ },
+ engagements: [
+ {
+ action: SearchSERPTelemetryUtils.ACTIONS.CLICKED_MORE_OPTIONS,
+ target: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ },
+ ],
+ adImpressions: [
+ {
+ component: SearchSERPTelemetryUtils.COMPONENTS.COOKIE_BANNER,
+ ads_loaded: "1",
+ ads_visible: "1",
+ ads_hidden: "0",
+ },
+ ],
+ },
+ ]);
+
+ BrowserTestUtils.removeTab(tab);
+});
diff --git a/browser/components/search/test/browser/telemetry/browser_search_telemetry_sources_webextension.js b/browser/components/search/test/browser/telemetry/browser_search_telemetry_sources_webextension.js
index f7b22f004b..cb9e123622 100644
--- a/browser/components/search/test/browser/telemetry/browser_search_telemetry_sources_webextension.js
+++ b/browser/components/search/test/browser/telemetry/browser_search_telemetry_sources_webextension.js
@@ -152,7 +152,7 @@ async function track_ad_click(
add_task(async function test_source_webextension_search() {
/* global browser */
- async function background(SEARCH_TERM) {
+ async function background() {
// Search with no tabId
browser.search.search({ query: "searchSuggestion", engine: "Example" });
}
@@ -184,7 +184,7 @@ add_task(async function test_source_webextension_search() {
});
add_task(async function test_source_webextension_query() {
- async function background(SEARCH_TERM) {
+ async function background() {
// Search with no tabId
browser.search.query({
text: "searchSuggestion",
diff --git a/browser/components/search/test/browser/telemetry/domain_category_mappings.json b/browser/components/search/test/browser/telemetry/domain_category_mappings.json
deleted file mode 100644
index 2f8d0d2af2..0000000000
--- a/browser/components/search/test/browser/telemetry/domain_category_mappings.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "DqNorjpE3CBY9OZh0wf1uA==": [2, 90],
- "kpuib0kvhtSp1moICEmGWg==": [2, 95],
- "+5WbbjV3Nmxp0mBZODcJWg==": [2, 78, 4, 10],
- "OIHlWZ/yMyTHHuY78AV9VQ==": [3, 90],
- "r1hDZinn+oNrQjabn8IB9w==": [4, 90],
- "AtlIam7nqWvzFzTGkYI01w==": [4, 90]
-}
diff --git a/browser/components/search/test/browser/telemetry/head.js b/browser/components/search/test/browser/telemetry/head.js
index 416451e400..b798099bdd 100644
--- a/browser/components/search/test/browser/telemetry/head.js
+++ b/browser/components/search/test/browser/telemetry/head.js
@@ -45,6 +45,10 @@ ChromeUtils.defineLazyGetter(this, "SEARCH_AD_CLICK_SCALARS", () => {
];
});
+ChromeUtils.defineLazyGetter(this, "gCryptoHash", () => {
+ return Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
+});
+
// For use with categorization.
const APP_MAJOR_VERSION = parseInt(Services.appinfo.version).toString();
const CHANNEL = SearchUtils.MODIFIED_APP_CHANNEL;
@@ -207,6 +211,11 @@ function resetTelemetry() {
* values we use to validate the recorded Glean impression events.
*/
function assertSERPTelemetry(expectedEvents) {
+ // Do a deep copy of impressions in case the input is using constants, as
+ // we insert impression id into the expected events to make it easier to
+ // run Assert.deepEqual() on the expected and actual result.
+ expectedEvents = JSON.parse(JSON.stringify(expectedEvents));
+
// A single test might run assertImpressionEvents more than once
// so the Set needs to be cleared or else the impression event
// check will throw.
@@ -385,6 +394,46 @@ add_setup(function () {
});
});
+async function openSerpInNewTab(url, expectedAds = true) {
+ let promise;
+ if (expectedAds) {
+ promise = waitForPageWithAdImpressions();
+ }
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ await promise;
+
+ let cleanup = async () => {
+ await BrowserTestUtils.removeTab(tab);
+ resetTelemetry();
+ };
+
+ return { tab, cleanup };
+}
+
+async function synthesizePageAction({
+ selector,
+ event = {},
+ tab,
+ expectEngagement = true,
+} = {}) {
+ let promise;
+ if (expectEngagement) {
+ promise = waitForPageWithAction();
+ } else {
+ // Wait roughly around how much it might take for a possible page action
+ // to be registered in telemetry.
+ /* eslint-disable-next-line mozilla/no-arbitrary-setTimeout */
+ promise = new Promise(resolve => setTimeout(resolve, 50));
+ }
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ selector,
+ event,
+ tab.linkedBrowser
+ );
+
+ await promise;
+}
+
function assertCategorizationValues(expectedResults) {
// TODO Bug 1868476: Replace with calls to Glean telemetry.
let actualResults = [...fakeTelemetryStorage];
@@ -435,6 +484,10 @@ function assertCategorizationValues(expectedResults) {
}
}
+function waitForPageWithAction() {
+ return TestUtils.topicObserved("reported-page-with-action");
+}
+
function waitForPageWithAdImpressions() {
return TestUtils.topicObserved("reported-page-with-ad-impressions");
}
@@ -459,10 +512,9 @@ registerCleanupFunction(async () => {
await PlacesUtils.history.clear();
});
-async function mockRecordWithAttachment({ id, version, filename }) {
+async function mockRecordWithAttachment({ id, version, filename, mapping }) {
// Get the bytes of the file for the hash and size for attachment metadata.
- let data = await IOUtils.readUTF8(getTestFilePath(filename));
- let buffer = new TextEncoder().encode(data).buffer;
+ let buffer = new TextEncoder().encode(JSON.stringify(mapping)).buffer;
let stream = Cc["@mozilla.org/io/arraybuffer-input-stream;1"].createInstance(
Ci.nsIArrayBufferInputStream
);
@@ -506,6 +558,30 @@ async function resetCategorizationCollection(record) {
await client.db.importChanges({}, Date.now());
}
+const MOCK_ATTACHMENT_VALUES = {
+ "abc.com": [2, 95],
+ "abc.org": [4, 90],
+ "def.com": [2, 78, 4, 10],
+ "def.org": [4, 90],
+ "foobar.org": [3, 90],
+};
+
+const CONVERTED_ATTACHMENT_VALUES = convertDomainsToHashes(
+ MOCK_ATTACHMENT_VALUES
+);
+
+function convertDomainsToHashes(domainsToCategories) {
+ let newObj = {};
+ for (let [key, value] of Object.entries(domainsToCategories)) {
+ gCryptoHash.init(gCryptoHash.SHA256);
+ let bytes = new TextEncoder().encode(key);
+ gCryptoHash.update(bytes, key.length);
+ let hash = gCryptoHash.finish(true);
+ newObj[hash] = value;
+ }
+ return newObj;
+}
+
async function insertRecordIntoCollection() {
const client = RemoteSettings(TELEMETRY_CATEGORIZATION_KEY);
const db = client.db;
@@ -515,6 +591,7 @@ async function insertRecordIntoCollection() {
id: "example_id",
version: 1,
filename: "domain_category_mappings.json",
+ mapping: CONVERTED_ATTACHMENT_VALUES,
});
await db.create(record);
await client.attachments.cacheImpl.set(record.id, attachment);
diff --git a/browser/components/search/test/browser/telemetry/searchTelemetryAd_components_cookie_banner.html b/browser/components/search/test/browser/telemetry/searchTelemetryAd_components_cookie_banner.html
new file mode 100644
index 0000000000..e33afb2672
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/searchTelemetryAd_components_cookie_banner.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+ <title>A top-level page with cookie banner</title>
+</head>
+<body>
+ <h1>This is the top-level page</h1>
+ <div id="banner">
+ <button id="cookie_accept">Accept</button>
+ <button id="cookie_reject">Reject</button>
+ <button id="cookie_more_options"
+ onclick="location.href='https:example.org/consent?data='">
+ More Options
+ </button>
+ </div>
+</body>
+</html>
diff --git a/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html b/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html
index 9c4d371691..d23255984f 100644
--- a/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html
+++ b/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html
@@ -11,13 +11,16 @@
</form>
</section>
<nav>
- <a id="images" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html?s=test&page=images">Images</a>
- <a id="shopping" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html?s=test&page=shopping">Shopping</a>
- <a id="extra" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox.html?s=test">Extra Page</a>
+ <a id="images" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html?s=test&page=images&abc=ff">Images</a>
+ <a id="shopping" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html?s=test&page=shopping&abc=ff">Shopping</a>
+ <a id="extra" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox.html?s=test&abc=ff">Extra Page</a>
</nav>
<section class="refined-search-buttons">
+ <button class="arrow arrow-prev">← Prev</button>
<a id="refined-search-button" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html?s=test's">Test's</a>
<a id="refined-search-button-with-partner-code" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_content.html?s=test2&abc=ff">Test 2</a>
+ <a href="javascript:void(0)">Element relying on Javascript</a>
+ <button class="arrow arrow-next">Next →</button>
</section>
<section id="searchresults">
<div class="lhs">
diff --git a/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_redirecting_links.html b/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_redirecting_links.html
new file mode 100644
index 0000000000..2b09409126
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/searchTelemetryAd_searchbox_with_redirecting_links.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="./serp.css" />
+</head>
+<body>
+ <nav>
+ <a href="/">All Results</a>
+ <a id="shopping-redirect-relative-link" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_shopping.html?s=test&page=shopping&abc=ff">Shopping Relative</a>
+ <a id="shopping-redirect-absolute-link" href="https://example.org/browser/browser/components/search/test/browser/telemetry/searchTelemetryAd_shopping.html?s=test&page=shopping&abc=ff">Shopping Absolute</a>
+ </nav>
+ <section>
+ <form role="search">
+ <input type="text" value="test" />
+ </form>
+ </section>
+ <section id="searchresults">
+ <a id="organic-redirect" href="https://example.org/foo/bar">Organic Redirect Result</a>
+ </section>
+</body>
+<script type="text/javascript">
+ const ORIGIN = "https://example.org";
+ const PATH = "/browser/browser/components/search/test/browser/telemetry/"
+ const REDIRECT_URL = `${ORIGIN + PATH}searchTelemetry_redirect_with_js.html`;
+ const SHOPPING_PAGE = "searchTelemetryAd_shopping.html?s=test&page=shopping&abc=ff";
+ document.getElementById("shopping-redirect-relative-link").addEventListener("click", event => {
+ event.preventDefault();
+ window.location.href = `${REDIRECT_URL}?url=${encodeURIComponent(PATH + SHOPPING_PAGE)}`;
+ });
+ document.getElementById("shopping-redirect-absolute-link").addEventListener("click", event => {
+ event.preventDefault();
+ window.location.href = `${REDIRECT_URL}?url=${encodeURIComponent(ORIGIN + PATH + SHOPPING_PAGE)}`;
+ });
+ document.getElementById("organic-redirect").addEventListener("click", event => {
+ event.preventDefault();
+ window.location.href = `${REDIRECT_URL}?url=${encodeURIComponent("https://example.org/foo/bar")}`;
+ });
+</script>
+</html>
diff --git a/browser/components/search/test/browser/telemetry/searchTelemetryDomainExtraction.html b/browser/components/search/test/browser/telemetry/searchTelemetryDomainExtraction.html
index b49e5610ae..28c31af959 100644
--- a/browser/components/search/test/browser/telemetry/searchTelemetryDomainExtraction.html
+++ b/browser/components/search/test/browser/telemetry/searchTelemetryDomainExtraction.html
@@ -25,6 +25,8 @@
<div id="test3">
<div data-layout="organic">
<a href="/dummy-page" data-testid="result-title-a">Extract domain from href (relative URL).</a>
+ <a href="https://example.org/dummy-page" data-testid="result-title-a">Extract domain from href.</a>
+ <a href="https://www.example.org/dummy-page" data-testid="result-title-a">Extract domain from href.</a>
</div>
</div>
@@ -40,7 +42,9 @@
</div>
<div id="test6">
- <a href="example.com/testing?ad_domain=def.com" class="js-carousel-item-title">Extract domain from an href's query param value.</a>
+ <a href="https://www.example.org/testing?ad_domain=def.com" class="js-carousel-item-title">Extract domain from an href's query param value.</a>
+ <a href="https://example.org/testing?ad_domain=bar.com" class="js-carousel-item-title">Extract domain from an href's query param value.</a>
+ <a href="/testing?ad_domain=baz.com" class="js-carousel-item-title">Extract domain from a relative href containing a relevant query param value.</a>
</div>
<div id="test7">
@@ -79,6 +83,179 @@
<div id="test14">
<a href="git://testing.com/testrepo">Non-standard URL scheme.</a>
</div>
+
+ <div id="test15">
+ <h5>Second-level domains to a top-level domain.</h5>
+ <a href="https://www.foobar.gc.ca/">Link</a>
+ <a href="https://www.foobar.gov.uk/">Link</a>
+ <a href="https://foobar.co.uk">Link</a>
+ <a href="https://www.foobar.co.il">Link</a>
+ </div>
+
+ <div id="test16">
+ <a href="https://ab.cd.ef.gh.foobar.com/">URL with a long subdomain</a>
+ </div>
+
+ <div id="test17">
+ <h5>URL with the same top level domain.</h5>
+ <a href="https://foobar.com/">Link</a>
+ <a href="https://www.foobar.com/">Link</a>
+ <a href="https://abc.def.foobar.com/">Link</a>
+ </div>
+
+ <div id="test18">
+ <h5>More than the threshold of links.</h5>
+ <a href="https://foobar1.com/">Link</a>
+ <a href="https://foobar1.com/">Duplicate Link</a>
+ <a href="https://foobar2.com/">Link</a>
+ <a href="https://foobar3.com/">Link</a>
+ <a href="https://foobar4.com/">Link</a>
+ <a href="https://foobar5.com/">Link</a>
+ <a href="https://foobar6.com/">Link</a>
+ <a href="https://foobar7.com/">Link</a>
+ <a href="https://foobar8.com/">Link</a>
+ <a href="https://foobar9.com/">Link</a>
+ <a href="https://foobar10.com/">Link</a>
+ <a href="https://foobar11.com/">Link Outside Threshold</a>
+ </div>
+
+ <div id="test19">
+ <h5>More than the threshold of links using multiple matching selectors.</h5>
+ <a class="foo" href="https://foobar1.com/">Link</a>
+ <a class="foo" href="https://foobar2.com/">Link</a>
+ <a class="foo" href="https://foobar3.com/">Link</a>
+ <a class="foo" href="https://foobar4.com/">Link</a>
+ <a class="foo" href="https://foobar5.com/">Link</a>
+ <a class="foo" href="https://foobar6.com/">Link</a>
+ <a class="foo" href="https://foobar7.com/">Link</a>
+ <a class="foo" href="https://foobar8.com/">Link</a>
+ <a class="foo" href="https://foobar9.com/">Link</a>
+ <a class="baz" href="https://foobaz1.com/">Link</a>
+ <a class="baz" href="https://foobaz2.com/">Link Outside Threshold</a>
+ </div>
+
+ <div id="test20">
+ <div id="b_results">
+ <div class="b_algo">
+ <div class="b_attribution">
+ <cite>https://organic.com</cite>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="test21">
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored.com</cite>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="test22">
+ <div class="adsMvCarousel">
+ <cite>Fixed up from the carousel</cite>
+ </div>
+ </div>
+
+ <div id="test23">
+ <aside>
+ <cite>Fixed up from the sidebar</cite>
+ </aside>
+ </div>
+
+ <div id="test24">
+ <h5>More than the threshold of links using the text content selection method.</h5>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored1.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored2.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored3.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored4.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored5.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored6.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored7.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored8.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored9.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored10.com</cite>
+ </div>
+ </div>
+ </div>
+ <div id="b_results">
+ <div class="b_ad">
+ <div class="b_attribution">
+ <cite>https://sponsored11.com</cite>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="test25">
+ <div id="b_results">
+ <div class="b_algo">
+ <div class="b_attribution">
+ <cite>organic.com</cite>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
</body>
</html>
diff --git a/browser/components/search/test/browser/telemetry/searchTelemetrySinglePageApp.html b/browser/components/search/test/browser/telemetry/searchTelemetrySinglePageApp.html
index 7598da694e..f52088206f 100644
--- a/browser/components/search/test/browser/telemetry/searchTelemetrySinglePageApp.html
+++ b/browser/components/search/test/browser/telemetry/searchTelemetrySinglePageApp.html
@@ -204,7 +204,7 @@
}
})
- window.addEventListener("DOMContentLoaded", (event) => {
+ window.addEventListener("DOMContentLoaded", () => {
let url = new URL(window.location.href);
searchKey = url.searchParams.has("r") ? "r": "s";
@@ -219,7 +219,7 @@
updateSuggestions();
});
- window.addEventListener("popstate", (event) => {
+ window.addEventListener("popstate", () => {
let baseUrl = new URL(window.location.href);
let page = baseUrl.searchParams.get("page");
switch (page) {
diff --git a/browser/components/search/test/browser/telemetry/searchTelemetry_redirect_with_js.html b/browser/components/search/test/browser/telemetry/searchTelemetry_redirect_with_js.html
new file mode 100644
index 0000000000..744fcd2906
--- /dev/null
+++ b/browser/components/search/test/browser/telemetry/searchTelemetry_redirect_with_js.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Page will redirect using the url param</title>
+ <script>
+ let parentWindow = window.parent;
+ let params = new URLSearchParams(window.location.search);
+ let paramValue = params.get("url");
+ if (paramValue) {
+ // Replicate how some SERPs load pages by encoding the true destination
+ // in the query param value.
+ let url = paramValue.startsWith("https://") ?
+ new URL(paramValue).href :
+ new URL(paramValue, "https://example.org/").href;
+ window.location.href = url;
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Redirecting...</h1>
+ </body>
+</html>
diff --git a/browser/components/search/test/unit/domain_category_mappings_1a.json b/browser/components/search/test/unit/domain_category_mappings_1a.json
deleted file mode 100644
index 51b18e12a7..0000000000
--- a/browser/components/search/test/unit/domain_category_mappings_1a.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Wrq9YDsieAMC3Y2DSY5Rcg==": [1, 100]
-}
diff --git a/browser/components/search/test/unit/domain_category_mappings_1b.json b/browser/components/search/test/unit/domain_category_mappings_1b.json
deleted file mode 100644
index 698ef45f1a..0000000000
--- a/browser/components/search/test/unit/domain_category_mappings_1b.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "G99y4E1rUMgqSMfk3TjMaQ==": [2, 90]
-}
diff --git a/browser/components/search/test/unit/domain_category_mappings_2a.json b/browser/components/search/test/unit/domain_category_mappings_2a.json
deleted file mode 100644
index 08db2fa8c2..0000000000
--- a/browser/components/search/test/unit/domain_category_mappings_2a.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Wrq9YDsieAMC3Y2DSY5Rcg==": [1, 80]
-}
diff --git a/browser/components/search/test/unit/domain_category_mappings_2b.json b/browser/components/search/test/unit/domain_category_mappings_2b.json
deleted file mode 100644
index dec2d130c1..0000000000
--- a/browser/components/search/test/unit/domain_category_mappings_2b.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "G99y4E1rUMgqSMfk3TjMaQ==": [2, 50, 4, 80]
-}
diff --git a/browser/components/search/test/unit/test_search_telemetry_categorization_logic.js b/browser/components/search/test/unit/test_search_telemetry_categorization_logic.js
index 947a7aae46..44b9147c50 100644
--- a/browser/components/search/test/unit/test_search_telemetry_categorization_logic.js
+++ b/browser/components/search/test/unit/test_search_telemetry_categorization_logic.js
@@ -15,90 +15,111 @@ ChromeUtils.defineESModuleGetters(this, {
SearchSERPTelemetryUtils: "resource:///modules/SearchSERPTelemetry.sys.mjs",
});
-const TEST_DOMAIN_TO_CATEGORIES_MAP_SIMPLE = {
- "byVQ4ej7T7s2xf/cPqgMyw==": [2, 90],
- "1TEnSjgNCuobI6olZinMiQ==": [2, 95],
- "/Bnju09b9iBPjg7K+5ENIw==": [2, 78, 4, 10],
- "Ja6RJq5LQftdl7NQrX1avQ==": [2, 56, 4, 24],
- "Jy26Qt99JrUderAcURtQ5A==": [2, 89],
- "sZnJyyzY9QcN810Q6jfbvw==": [2, 43],
- "QhmteGKeYk0okuB/bXzwRw==": [2, 65],
- "CKQZZ1IJjzjjE4LUV8vUSg==": [2, 67],
- "FK7mL5E1JaE6VzOiGMmlZg==": [2, 89],
- "mzcR/nhDcrs0ed4kTf+ZFg==": [2, 99],
-};
-
-const TEST_DOMAIN_TO_CATEGORIES_MAP_INCONCLUSIVE = {
- "IkOfhoSlHTMIZzWXkYf7fg==": [0, 0],
- "PIAHxeaBOeDNY2tvZKqQuw==": [0, 0],
- "DKx2mqmFtEvxrHAqpwSevA==": [0, 0],
- "DlZKnz9ryYqbxJq9wodzlA==": [0, 0],
- "n3NWT4N9JlKX0I7MUtAsYg==": [0, 0],
- "A6KyupOlu5zXt8loti90qw==": [0, 0],
- "gf5rpseruOaq8nXOSJPG3Q==": [0, 0],
- "vlQYOvbcbAp6sMx54OwqCQ==": [0, 0],
- "8PcaPATLgmHD9SR0/961Sw==": [0, 0],
- "l+hLycEAW2v/OPE/XFpNwQ==": [0, 0],
-};
-
-const TEST_DOMAIN_TO_CATEGORIES_MAP_UNKNOWN_AND_INCONCLUSIVE = {
- "CEA642T3hV+Fdi2PaRH9BQ==": [0, 0],
- "cVqopYLASYxcWdDW4F+w2w==": [0, 0],
- "X61OdTU20n8pxZ76K2eAHg==": [0, 0],
- "/srrOggOAwgaBGCsPdC4bA==": [0, 0],
- "onnMGn+MmaCQx3RNLBzGOQ==": [0, 0],
-};
-
-const TEST_DOMAIN_TO_CATEGORIES_MAP_ALL_TYPES = {
- "VSXaqgDKYWrJ/yjsFomUdg==": [3, 90],
- "6re74Kk34n2V6VCdLmCD5w==": [3, 88],
- "s8gOGIaFnly5hHX7nPncnw==": [3, 90, 6, 2],
- "zfRJyKV+2jd1RKNsSHm9pw==": [3, 78, 6, 7],
- "zcW+KbRfLRO6Dljf5qnuwQ==": [3, 97],
- "Rau9mfbBcIRiRQIliUxkow==": [0, 0],
- "4AFhUOmLQ8804doOsI4jBA==": [0, 0],
-};
-
-const TEST_DOMAIN_TO_CATEGORIES_MAP_TIE = {
- "fmEqRSc+pBr9noi0l99nGw==": [1, 50, 2, 50],
- "cms8ipz0JQ3WS9o48RtvnQ==": [1, 50, 2, 50],
- "y8Haj7Qdmx+k762RaxCPvA==": [1, 50, 2, 50],
- "tCbLmi5xJ/OrF8tbRm8PrA==": [1, 50, 2, 50],
- "uYNQECmDShqI409HrSTdLQ==": [1, 50, 2, 50],
- "D88hdsmzLWIXYhkrDal33w==": [3, 50, 4, 50],
- "1mhx0I0B4cEaI91x8zor7Q==": [5, 50, 6, 50],
- "dVZYATQixuBHmalCFR9+Lw==": [7, 50, 8, 50],
- "pdOFJG49D7hE/+FtsWDihQ==": [9, 50, 10, 50],
- "+gl+dBhWE0nx0AM69m2g5w==": [11, 50, 12, 50],
-};
-
-const TEST_DOMAIN_TO_CATEGORIES_MAP_RANK_PENALIZATION_1 = {
- "VSXaqgDKYWrJ/yjsFomUdg==": [1, 45],
- "6re74Kk34n2V6VCdLmCD5w==": [2, 45],
- "s8gOGIaFnly5hHX7nPncnw==": [3, 45],
- "zfRJyKV+2jd1RKNsSHm9pw==": [4, 45],
- "zcW+KbRfLRO6Dljf5qnuwQ==": [5, 45],
- "Rau9mfbBcIRiRQIliUxkow==": [6, 45],
- "4AFhUOmLQ8804doOsI4jBA==": [7, 45],
- "YZ3aEL73MR+Cjog0D7A24w==": [8, 45],
- "crMclD9rwInEQ30DpZLg+g==": [9, 45],
- "/r7oPRoE6LJAE95nuwmu7w==": [10, 45],
-};
-
-const TEST_DOMAIN_TO_CATEGORIES_MAP_RANK_PENALIZATION_2 = {
- "sHWSmFwSYL3snycBZCY8Kg==": [1, 35, 2, 4],
- "FZ5zPYh6ByI0KGWKkmpDoA==": [1, 5, 2, 94],
-};
+ChromeUtils.defineLazyGetter(this, "gCryptoHash", () => {
+ return Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
+});
+
+function convertDomainsToHashes(domainsToCategories) {
+ let newObj = {};
+ for (let [key, value] of Object.entries(domainsToCategories)) {
+ gCryptoHash.init(gCryptoHash.SHA256);
+ let bytes = new TextEncoder().encode(key);
+ gCryptoHash.update(bytes, key.length);
+ let hash = gCryptoHash.finish(true);
+ newObj[hash] = value;
+ }
+ return newObj;
+}
+
+const TEST_DOMAIN_TO_CATEGORIES_MAP_SIMPLE = convertDomainsToHashes({
+ "test1.com": [2, 90],
+ "test2.com": [2, 95],
+ "test3.com": [2, 78, 4, 10],
+ "test4.com": [2, 56, 4, 24],
+ "test5.com": [2, 89],
+ "test6.com": [2, 43],
+ "test7.com": [2, 65],
+ "test8.com": [2, 67],
+ "test9.com": [2, 89],
+ "test10.com": [2, 99],
+});
+
+const TEST_DOMAIN_TO_CATEGORIES_MAP_INCONCLUSIVE = convertDomainsToHashes({
+ "test11.com": [0, 0],
+ "test12.com": [0, 0],
+ "test13.com": [0, 0],
+ "test14.com": [0, 0],
+ "test15.com": [0, 0],
+ "test16.com": [0, 0],
+ "test17.com": [0, 0],
+ "test18.com": [0, 0],
+ "test19.com": [0, 0],
+ "test20.com": [0, 0],
+});
+
+const TEST_DOMAIN_TO_CATEGORIES_MAP_UNKNOWN_AND_INCONCLUSIVE =
+ convertDomainsToHashes({
+ "test31.com": [0, 0],
+ "test32.com": [0, 0],
+ "test33.com": [0, 0],
+ "test34.com": [0, 0],
+ "test35.com": [0, 0],
+ });
+
+const TEST_DOMAIN_TO_CATEGORIES_MAP_ALL_TYPES = convertDomainsToHashes({
+ "test51.com": [3, 90],
+ "test52.com": [3, 88],
+ "test53.com": [3, 90, 6, 2],
+ "test54.com": [3, 78, 6, 7],
+ "test55.com": [3, 97],
+ "test56.com": [0, 0],
+ "test57.com": [0, 0],
+});
+
+const TEST_DOMAIN_TO_CATEGORIES_MAP_TIE = convertDomainsToHashes({
+ "test41.com": [1, 50, 2, 50],
+ "test42.com": [1, 50, 2, 50],
+ "test43.com": [1, 50, 2, 50],
+ "test44.com": [1, 50, 2, 50],
+ "test45.com": [1, 50, 2, 50],
+ "test46.com": [3, 50, 4, 50],
+ "test47.com": [5, 50, 6, 50],
+ "test48.com": [7, 50, 8, 50],
+ "test49.com": [9, 50, 10, 50],
+ "test50.com": [11, 50, 12, 50],
+});
+
+const TEST_DOMAIN_TO_CATEGORIES_MAP_RANK_PENALIZATION_1 =
+ convertDomainsToHashes({
+ "test51.com": [1, 45],
+ "test52.com": [2, 45],
+ "test53.com": [3, 45],
+ "test54.com": [4, 45],
+ "test55.com": [5, 45],
+ "test56.com": [6, 45],
+ "test57.com": [7, 45],
+ "test58.com": [8, 45],
+ "test59.com": [9, 45],
+ "test60.com": [10, 45],
+ });
+
+const TEST_DOMAIN_TO_CATEGORIES_MAP_RANK_PENALIZATION_2 =
+ convertDomainsToHashes({
+ "test61.com": [1, 35, 2, 4],
+ "test62.com": [1, 5, 2, 94],
+ });
add_setup(async () => {
+ do_get_profile();
Services.prefs.setBoolPref(
"browser.search.serpEventTelemetryCategorization.enabled",
true
);
+ await SearchSERPDomainToCategoriesMap.init();
});
add_task(async function test_categorization_simple() {
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_SIMPLE
);
@@ -115,8 +136,9 @@ add_task(async function test_categorization_simple() {
"test10.com",
]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.deepEqual(
resultsToReport,
@@ -126,7 +148,7 @@ add_task(async function test_categorization_simple() {
});
add_task(async function test_categorization_inconclusive() {
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_INCONCLUSIVE
);
@@ -143,8 +165,9 @@ add_task(async function test_categorization_inconclusive() {
"test20.com",
]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.deepEqual(
resultsToReport,
@@ -161,7 +184,7 @@ add_task(async function test_categorization_inconclusive() {
add_task(async function test_categorization_unknown() {
// Reusing TEST_DOMAIN_TO_CATEGORIES_MAP_SIMPLE since none of this task's
// domains will be keys within it.
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_SIMPLE
);
@@ -178,8 +201,9 @@ add_task(async function test_categorization_unknown() {
"test30.com",
]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.deepEqual(
resultsToReport,
@@ -194,7 +218,7 @@ add_task(async function test_categorization_unknown() {
});
add_task(async function test_categorization_unknown_and_inconclusive() {
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_UNKNOWN_AND_INCONCLUSIVE
);
@@ -211,8 +235,9 @@ add_task(async function test_categorization_unknown_and_inconclusive() {
"test40.com",
]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.deepEqual(
resultsToReport,
@@ -228,7 +253,7 @@ add_task(async function test_categorization_unknown_and_inconclusive() {
// Tests a mixture of categorized, inconclusive and unknown domains.
add_task(async function test_categorization_all_types() {
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_ALL_TYPES
);
@@ -247,8 +272,9 @@ add_task(async function test_categorization_all_types() {
"test60.com",
]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.deepEqual(
resultsToReport,
@@ -263,7 +289,7 @@ add_task(async function test_categorization_all_types() {
});
add_task(async function test_categorization_tie() {
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_TIE
);
@@ -280,8 +306,9 @@ add_task(async function test_categorization_tie() {
"test50.com",
]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.equal(
[1, 2].includes(resultsToReport.category),
@@ -301,7 +328,7 @@ add_task(async function test_categorization_tie() {
});
add_task(async function test_rank_penalization_equal_scores() {
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_RANK_PENALIZATION_1
);
@@ -318,8 +345,9 @@ add_task(async function test_rank_penalization_equal_scores() {
"test60.com",
]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.deepEqual(
resultsToReport,
@@ -329,14 +357,15 @@ add_task(async function test_rank_penalization_equal_scores() {
});
add_task(async function test_rank_penalization_highest_score_lower_on_page() {
- SearchSERPDomainToCategoriesMap.overrideMapForTests(
+ await SearchSERPDomainToCategoriesMap.overrideMapForTests(
TEST_DOMAIN_TO_CATEGORIES_MAP_RANK_PENALIZATION_2
);
let domains = new Set(["test61.com", "test62.com"]);
- let resultsToReport =
- SearchSERPCategorization.applyCategorizationLogic(domains);
+ let resultsToReport = await SearchSERPCategorization.applyCategorizationLogic(
+ domains
+ );
Assert.deepEqual(
resultsToReport,
diff --git a/browser/components/search/test/unit/test_search_telemetry_categorization_process_domains.js b/browser/components/search/test/unit/test_search_telemetry_categorization_process_domains.js
deleted file mode 100644
index 84acedaa7a..0000000000
--- a/browser/components/search/test/unit/test_search_telemetry_categorization_process_domains.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * This test ensures we are correctly processing the domains that have been
- * extracted from a SERP.
- */
-
-ChromeUtils.defineESModuleGetters(this, {
- BrowserSearchTelemetry: "resource:///modules/BrowserSearchTelemetry.sys.mjs",
- SearchSERPCategorization: "resource:///modules/SearchSERPTelemetry.sys.mjs",
- SearchSERPTelemetry: "resource:///modules/SearchSERPTelemetry.sys.mjs",
- SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs",
- sinon: "resource://testing-common/Sinon.sys.mjs",
-});
-
-// Links including the provider name are not extracted.
-const PROVIDER = "example";
-
-const TESTS = [
- {
- title: "Domains matching the provider.",
- domains: ["example.com", "www.example.com", "www.foobar.com"],
- expected: ["foobar.com"],
- },
- {
- title: "Second-level domains to a top-level domain.",
- domains: [
- "www.foobar.gc.ca",
- "www.foobar.gov.uk",
- "foobar.co.uk",
- "www.foobar.co.il",
- ],
- expected: ["foobar.gc.ca", "foobar.gov.uk", "foobar.co.uk", "foobar.co.il"],
- },
- {
- title: "Long subdomain.",
- domains: ["ab.cd.ef.gh.foobar.com"],
- expected: ["foobar.com"],
- },
- {
- title: "Same top-level domain.",
- domains: ["foobar.com", "www.foobar.com", "abc.def.foobar.com"],
- expected: ["foobar.com"],
- },
- {
- title: "Empty input.",
- domains: [""],
- expected: [],
- },
-];
-
-add_setup(async function () {
- Services.prefs.setBoolPref(
- SearchUtils.BROWSER_SEARCH_PREF + "serpEventTelemetry.enabled",
- true
- );
- Services.prefs.setBoolPref(
- SearchUtils.BROWSER_SEARCH_PREF +
- "serpEventTelemetryCategorization.enabled",
- true
- );
-
- // Required or else BrowserSearchTelemetry will throw.
- sinon.stub(BrowserSearchTelemetry, "shouldRecordSearchCount").returns(true);
- await SearchSERPTelemetry.init();
-});
-
-add_task(async function test_parsing_extracted_urls() {
- for (let i = 0; i < TESTS.length; i++) {
- let currentTest = TESTS[i];
- let domains = new Set(currentTest.domains);
-
- if (currentTest.title) {
- info(currentTest.title);
- }
- let expectedDomains = new Set(currentTest.expected);
- let actualDomains = SearchSERPCategorization.processDomains(
- domains,
- PROVIDER
- );
-
- Assert.deepEqual(
- Array.from(actualDomains),
- Array.from(expectedDomains),
- "Domains should have been parsed correctly."
- );
- }
-});
diff --git a/browser/components/search/test/unit/test_search_telemetry_categorization_sync.js b/browser/components/search/test/unit/test_search_telemetry_categorization_sync.js
index 423ee0a81d..40d38efbba 100644
--- a/browser/components/search/test/unit/test_search_telemetry_categorization_sync.js
+++ b/browser/components/search/test/unit/test_search_telemetry_categorization_sync.js
@@ -16,16 +16,34 @@ ChromeUtils.defineESModuleGetters(this, {
TestUtils: "resource://testing-common/TestUtils.sys.mjs",
});
+ChromeUtils.defineLazyGetter(this, "gCryptoHash", () => {
+ return Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
+});
+
+function convertDomainsToHashes(domainsToCategories) {
+ let newObj = {};
+ for (let [key, value] of Object.entries(domainsToCategories)) {
+ gCryptoHash.init(gCryptoHash.SHA256);
+ let bytes = new TextEncoder().encode(key);
+ gCryptoHash.update(bytes, key.length);
+ let hash = gCryptoHash.finish(true);
+ newObj[hash] = value;
+ }
+ return newObj;
+}
+
async function waitForDomainToCategoriesUpdate() {
return TestUtils.topicObserved("domain-to-categories-map-update-complete");
}
-async function mockRecordWithCachedAttachment({ id, version, filename }) {
+async function mockRecordWithCachedAttachment({
+ id,
+ version,
+ filename,
+ mapping,
+}) {
// Get the bytes of the file for the hash and size for attachment metadata.
- let data = await IOUtils.readUTF8(
- PathUtils.join(do_get_cwd().path, filename)
- );
- let buffer = new TextEncoder().encode(data).buffer;
+ let buffer = new TextEncoder().encode(JSON.stringify(mapping)).buffer;
let stream = Cc["@mozilla.org/io/arraybuffer-input-stream;1"].createInstance(
Ci.nsIArrayBufferInputStream
);
@@ -73,21 +91,33 @@ const RECORDS = {
id: RECORD_A_ID,
version: 1,
filename: "domain_category_mappings_1a.json",
+ mapping: convertDomainsToHashes({
+ "example.com": [1, 100],
+ }),
},
record1b: {
id: RECORD_B_ID,
version: 1,
filename: "domain_category_mappings_1b.json",
+ mapping: convertDomainsToHashes({
+ "example.org": [2, 90],
+ }),
},
record2a: {
id: RECORD_A_ID,
version: 2,
filename: "domain_category_mappings_2a.json",
+ mapping: convertDomainsToHashes({
+ "example.com": [1, 80],
+ }),
},
record2b: {
id: RECORD_B_ID,
version: 2,
filename: "domain_category_mappings_2b.json",
+ mapping: convertDomainsToHashes({
+ "example.org": [2, 50, 4, 80],
+ }),
},
};
@@ -115,13 +145,13 @@ add_task(async function test_initial_import() {
await promise;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[{ category: 1, score: 100 }],
"Return value from lookup of example.com should be the same."
);
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.org"),
+ await SearchSERPDomainToCategoriesMap.get("example.org"),
[{ category: 2, score: 90 }],
"Return value from lookup of example.org should be the same."
);
@@ -167,13 +197,13 @@ add_task(async function test_update_records() {
await promise;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[{ category: 1, score: 80 }],
"Return value from lookup of example.com should have changed."
);
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.org"),
+ await SearchSERPDomainToCategoriesMap.get("example.org"),
[
{ category: 2, score: 50 },
{ category: 4, score: 80 },
@@ -224,13 +254,13 @@ add_task(async function test_delayed_initial_import() {
await promise;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[{ category: 1, score: 100 }],
"Return value from lookup of example.com should be the same."
);
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.org"),
+ await SearchSERPDomainToCategoriesMap.get("example.org"),
[{ category: 2, score: 90 }],
"Return value from lookup of example.org should be the same."
);
@@ -264,7 +294,7 @@ add_task(async function test_remove_record() {
await promise;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[{ category: 1, score: 80 }],
"Initialized properly."
);
@@ -283,13 +313,13 @@ add_task(async function test_remove_record() {
await promise;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[{ category: 1, score: 80 }],
"Return value from lookup of example.com should remain unchanged."
);
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.org"),
+ await SearchSERPDomainToCategoriesMap.get("example.org"),
[],
"Return value from lookup of example.org should be empty."
);
@@ -323,7 +353,7 @@ add_task(async function test_different_versions_coexisting() {
await promise;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[
{
category: 1,
@@ -334,7 +364,7 @@ add_task(async function test_different_versions_coexisting() {
);
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.org"),
+ await SearchSERPDomainToCategoriesMap.get("example.org"),
[
{ category: 2, score: 50 },
{ category: 4, score: 80 },
@@ -367,7 +397,7 @@ add_task(async function test_download_error() {
await promise;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[
{
category: 1,
@@ -406,7 +436,7 @@ add_task(async function test_download_error() {
await observeDownloadError;
Assert.deepEqual(
- SearchSERPDomainToCategoriesMap.get("example.com"),
+ await SearchSERPDomainToCategoriesMap.get("example.com"),
[],
"Domain should not exist in store."
);
diff --git a/browser/components/search/test/unit/xpcshell.toml b/browser/components/search/test/unit/xpcshell.toml
index 61cdb83378..423d218d19 100644
--- a/browser/components/search/test/unit/xpcshell.toml
+++ b/browser/components/search/test/unit/xpcshell.toml
@@ -8,16 +8,8 @@ firefox-appdir = "browser"
["test_search_telemetry_categorization_logic.js"]
-["test_search_telemetry_categorization_process_domains.js"]
-
["test_search_telemetry_categorization_sync.js"]
prefs = ["browser.search.serpEventTelemetryCategorization.enabled=true"]
-support-files = [
- "domain_category_mappings_1a.json",
- "domain_category_mappings_1b.json",
- "domain_category_mappings_2a.json",
- "domain_category_mappings_2b.json",
-]
["test_search_telemetry_compare_urls.js"]