fune/browser/components/search/test/unit/test_urlTelemetry_generic.js

316 lines
9.6 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
ChromeUtils.defineESModuleGetters(this, {
BrowserSearchTelemetry: "resource:///modules/BrowserSearchTelemetry.sys.mjs",
NetUtil: "resource://gre/modules/NetUtil.sys.mjs",
SearchSERPTelemetry: "resource:///modules/SearchSERPTelemetry.sys.mjs",
SearchSERPTelemetryUtils: "resource:///modules/SearchSERPTelemetry.sys.mjs",
SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs",
TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs",
sinon: "resource://testing-common/Sinon.sys.mjs",
});
const TEST_PROVIDER_INFO = [
{
telemetryId: "example",
searchPageRegexp: /^https:\/\/www\.example\.com\/search/,
queryParamName: "q",
codeParamName: "abc",
taggedCodes: ["ff", "tb"],
expectedOrganicCodes: ["baz"],
organicCodes: ["foo"],
followOnParamNames: ["a"],
extraAdServersRegexps: [/^https:\/\/www\.example\.com\/ad2/],
shoppingTab: {
regexp: "&site=shop",
},
components: [
{
type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
default: true,
},
],
},
{
telemetryId: "example2",
searchPageRegexp: /^https:\/\/www\.example2\.com\/search/,
queryParamName: "q",
codeParamName: "abc",
taggedCodes: ["ff", "tb"],
expectedOrganicCodes: ["baz"],
organicCodes: ["foo"],
followOnParamNames: ["a"],
extraAdServersRegexps: [/^https:\/\/www\.example\.com\/ad2/],
components: [
{
type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
default: true,
},
],
},
];
const TESTS = [
{
title: "Tagged search",
trackingUrl: "https://www.example.com/search?q=test&abc=ff",
expectedSearchCountEntry: "example:tagged:ff",
expectedAdKey: "example:tagged",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Tagged search with shopping",
trackingUrl: "https://www.example.com/search?q=test&abc=ff&site=shop",
expectedSearchCountEntry: "example:tagged:ff",
expectedAdKey: "example:tagged",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
is_shopping_page: "true",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Tagged follow-on",
trackingUrl: "https://www.example.com/search?q=test&abc=tb&a=next",
expectedSearchCountEntry: "example:tagged-follow-on:tb",
expectedAdKey: "example:tagged-follow-on",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "true",
partner_code: "tb",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Organic search matched code",
trackingUrl: "https://www.example.com/search?q=test&abc=foo",
expectedSearchCountEntry: "example:organic:foo",
expectedAdKey: "example:organic",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "false",
partner_code: "foo",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Organic search non-matched code",
trackingUrl: "https://www.example.com/search?q=test&abc=ff123",
expectedSearchCountEntry: "example:organic:other",
expectedAdKey: "example:organic",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "false",
partner_code: "other",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Organic search non-matched code 2",
trackingUrl: "https://www.example.com/search?q=test&abc=foo123",
expectedSearchCountEntry: "example:organic:other",
expectedAdKey: "example:organic",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "false",
partner_code: "other",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Organic search expected organic matched code",
trackingUrl: "https://www.example.com/search?q=test&abc=baz",
expectedSearchCountEntry: "example:organic:none",
expectedAdKey: "example:organic",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "false",
partner_code: "",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Organic search no codes",
trackingUrl: "https://www.example.com/search?q=test",
expectedSearchCountEntry: "example:organic:none",
expectedAdKey: "example:organic",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example",
tagged: "false",
partner_code: "",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
{
title: "Different engines using the same adUrl",
trackingUrl: "https://www.example2.com/search?q=test",
expectedSearchCountEntry: "example2:organic:none",
expectedAdKey: "example2:organic",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example2",
tagged: "false",
partner_code: "",
is_shopping_page: "false",
shopping_tab_displayed: "false",
source: "unknown",
},
},
];
/**
* This function is primarily for testing the Ad URL regexps that are triggered
* when a URL is clicked on. These regexps are also used for the `withads`
* probe. However, we test the adclicks route as that is easier to hit.
*
* @param {string} serpUrl
* The url to simulate where the page the click came from.
* @param {string} adUrl
* The ad url to simulate being clicked.
* @param {string} [expectedAdKey]
* The expected key to be logged for the scalar. Omit if no scalar should be
* logged.
*/
async function testAdUrlClicked(serpUrl, adUrl, expectedAdKey) {
info(`Testing Ad URL: ${adUrl}`);
let channel = NetUtil.newChannel({
uri: NetUtil.newURI(adUrl),
triggeringPrincipal: Services.scriptSecurityManager.createContentPrincipal(
NetUtil.newURI(serpUrl),
{}
),
loadUsingSystemPrincipal: true,
});
SearchSERPTelemetry._contentHandler.observeActivity(
channel,
Ci.nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION,
Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE
);
// Since the content handler takes a moment to allow the channel information
// to settle down, wait the same amount of time here.
await new Promise(resolve => Services.tm.dispatchToMainThread(resolve));
const scalars = TelemetryTestUtils.getProcessScalars("parent", true, true);
if (!expectedAdKey) {
Assert.ok(
!("browser.search.adclicks.unknown" in scalars),
"Should not have recorded an ad click"
);
} else {
TelemetryTestUtils.assertKeyedScalar(
scalars,
"browser.search.adclicks.unknown",
expectedAdKey,
1
);
}
}
do_get_profile();
add_task(async function setup() {
Services.prefs.setBoolPref(SearchUtils.BROWSER_SEARCH_PREF + "log", true);
Services.prefs.setBoolPref(
SearchUtils.BROWSER_SEARCH_PREF + "serpEventTelemetry.enabled",
true
);
Services.fog.initializeFOG();
await SearchSERPTelemetry.init();
SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
sinon.stub(BrowserSearchTelemetry, "shouldRecordSearchCount").returns(true);
});
add_task(async function test_parsing_search_urls() {
for (const test of TESTS) {
info(`Running ${test.title}`);
if (test.setUp) {
test.setUp();
}
let browser = {
getTabBrowser: () => {},
};
SearchSERPTelemetry.updateTrackingStatus(browser, test.trackingUrl);
SearchSERPTelemetry.reportPageImpression(
{
url: test.trackingUrl,
shoppingTabDisplayed: false,
},
browser
);
let scalars = TelemetryTestUtils.getProcessScalars("parent", true, true);
TelemetryTestUtils.assertKeyedScalar(
scalars,
"browser.search.content.unknown",
test.expectedSearchCountEntry,
1
);
if ("adUrls" in test) {
for (const adUrl of test.adUrls) {
await testAdUrlClicked(test.trackingUrl, adUrl, test.expectedAdKey);
}
for (const nonAdUrls of test.nonAdUrls) {
await testAdUrlClicked(test.trackingUrl, nonAdUrls);
}
}
let recordedEvents = Glean.serp.impression.testGetValue();
Assert.equal(
recordedEvents.length,
1,
"should only see one impression event"
);
// To allow deep equality.
test.impression.impression_id = recordedEvents[0].extra.impression_id;
Assert.deepEqual(recordedEvents[0].extra, test.impression);
if (test.tearDown) {
test.tearDown();
}
// We need to clear Glean events so they don't accumulate for each iteration.
Services.fog.testResetFOG();
}
});