Update On Wed Nov 22 19:42:59 CET 2023

This commit is contained in:
github-action[bot] 2023-11-22 19:42:59 +01:00
parent 0461efa8df
commit 8529fbe8d2
1714 changed files with 541246 additions and 430934 deletions

View file

@ -49,8 +49,8 @@ static gboolean GetPositionCB(AtkTableCell* aCell, gint* aRow, gint* aCol) {
return true;
}
static gboolean GetColumnRowSpanCB(AtkTableCell* aCell, gint* aCol, gint* aRow,
gint* aColExtent, gint* aRowExtent) {
static gboolean GetRowColumnSpanCB(AtkTableCell* aCell, gint* aRow, gint* aCol,
gint* aRowExtent, gint* aColExtent) {
Accessible* acc = GetInternalObj(ATK_OBJECT(aCell));
if (!acc) {
return false;
@ -62,7 +62,7 @@ static gboolean GetColumnRowSpanCB(AtkTableCell* aCell, gint* aCol, gint* aRow,
*aCol = static_cast<gint>(cellAcc->ColIdx());
*aRow = static_cast<gint>(cellAcc->RowIdx());
*aColExtent = static_cast<gint>(cellAcc->ColExtent());
*aRowExtent = static_cast<gint>(cellAcc->ColExtent());
*aRowExtent = static_cast<gint>(cellAcc->RowExtent());
return true;
}
@ -143,6 +143,6 @@ void tableCellInterfaceInitCB(AtkTableCellIface* aIface) {
aIface->get_position = GetPositionCB;
aIface->get_row_span = GetRowSpanCB;
aIface->get_row_header_cells = GetRowHeaderCellsCB;
aIface->get_row_column_span = GetColumnRowSpanCB;
aIface->get_row_column_span = GetRowColumnSpanCB;
aIface->get_table = GetTableCB;
}

View file

@ -13,3 +13,4 @@ prefs = [
]
["browser_role.js"]
["browser_table.js"]

View file

@ -0,0 +1,54 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Test getRowColumnSpan.
*/
addAccessibleTask(
`
<table>
<tr>
<th id="ab" colspan="2">ab</th>
<td id="cf" rowspan="2">cf</td>
</tr>
<tr>
<td id="d">d</td>
<td>e</td>
</tr>
</table>
`,
async function (browser, docAcc) {
let result = await runPython(`
global doc
doc = getDoc()
ab = findByDomId(doc, "ab")
return str(ab.queryTableCell().getRowColumnSpan())
`);
is(
result,
"(row=0, column=0, row_span=1, column_span=2)",
"ab getColumnRowSpan correct"
);
result = await runPython(`
cf = findByDomId(doc, "cf")
return str(cf.queryTableCell().getRowColumnSpan())
`);
is(
result,
"(row=0, column=2, row_span=2, column_span=1)",
"cf getColumnRowSpan correct"
);
result = await runPython(`
d = findByDomId(doc, "d")
return str(d.queryTableCell().getRowColumnSpan())
`);
is(
result,
"(row=1, column=0, row_span=1, column_span=1)",
"d getColumnRowSpan correct"
);
}
);

View file

@ -58,15 +58,14 @@ export class AboutNewTabParent extends JSWindowActorParent {
break;
case "Init": {
let actor = message.target;
let browsingContext = actor.browsingContext;
let browsingContext = this.browsingContext;
let browser = browsingContext.top.embedderElement;
if (!browser) {
return;
}
let tabDetails = {
actor,
actor: this,
browser,
browsingContext,
portID: message.data.portID,
@ -89,10 +88,8 @@ export class AboutNewTabParent extends JSWindowActorParent {
let tabDetails = this.getTabDetails();
if (!tabDetails) {
// When closing a tab, the embedderElement can already be disconnected, so
// an a backup, look up the tab details by browsing context.
tabDetails = this.getByBrowsingContext(
message.target.browsingContext
);
// as a backup, look up the tab details by browsing context.
tabDetails = this.getByBrowsingContext(this.browsingContext);
}
if (!tabDetails) {
@ -127,7 +124,7 @@ export class AboutNewTabParent extends JSWindowActorParent {
}
let messageToSend = {
target: message.target,
target: this,
data: message.data || {},
};

View file

@ -132,6 +132,10 @@ export class PromptParent extends JSWindowActorParent {
switch (message.name) {
case "Prompt:Open":
if (!this.windowContext.isCurrentGlobal) {
return undefined;
}
if (
(args.modalType === Ci.nsIPrompt.MODAL_TYPE_CONTENT &&
!lazy.contentPromptSubDialog) ||

View file

@ -1,3 +1,5 @@
/* eslint-disable @microsoft/sdl/no-insecure-url */
const ANY_URL = undefined;
const { SearchTestUtils } = ChromeUtils.importESModule(
@ -29,21 +31,21 @@ add_task(async function test_setup() {
// New Tab Button opens any link.
add_task(async function single_url() {
await dropText("mochi.test/first", ["http://mochi.test/first"]);
await dropText("example.com/first", ["http://example.com/first"]);
});
add_task(async function single_url2() {
await dropText("mochi.test/second", ["http://mochi.test/second"]);
await dropText("example.com/second", ["http://example.com/second"]);
});
add_task(async function single_url3() {
await dropText("mochi.test/third", ["http://mochi.test/third"]);
await dropText("example.com/third", ["http://example.com/third"]);
});
// Single text/plain item, with multiple links.
add_task(async function multiple_urls() {
await dropText("www.mochi.test/1\nmochi.test/2", [
await dropText("www.example.com/1\nexample.com/2", [
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
"http://www.mochi.test/1",
"http://mochi.test/2",
"http://www.example.com/1",
"http://example.com/2",
]);
});
@ -51,10 +53,10 @@ add_task(async function multiple_urls() {
add_task(async function multiple_items_single_and_multiple_links() {
await drop(
[
[{ type: "text/plain", data: "mochi.test/5" }],
[{ type: "text/plain", data: "mochi.test/6\nmochi.test/7" }],
[{ type: "text/plain", data: "example.com/5" }],
[{ type: "text/plain", data: "example.com/6\nexample.com/7" }],
],
["http://mochi.test/5", "http://mochi.test/6", "http://mochi.test/7"]
["http://example.com/5", "http://example.com/6", "http://example.com/7"]
);
});
@ -66,11 +68,11 @@ add_task(async function single_moz_url_multiple_links() {
[
{
type: "text/x-moz-url",
data: "mochi.test/8\nTITLE8\nmochi.test/9\nTITLE9",
data: "example.com/8\nTITLE8\nexample.com/9\nTITLE9",
},
],
],
["http://mochi.test/8", "http://mochi.test/9"]
["http://example.com/8", "http://example.com/9"]
);
});
@ -79,11 +81,11 @@ add_task(async function single_item_multiple_types() {
await drop(
[
[
{ type: "text/plain", data: "mochi.test/10" },
{ type: "text/x-moz-url", data: "mochi.test/11\nTITLE11" },
{ type: "text/plain", data: "example.com/10" },
{ type: "text/x-moz-url", data: "example.com/11\nTITLE11" },
],
],
["http://mochi.test/11"]
["http://example.com/11"]
);
});
@ -91,14 +93,14 @@ add_task(async function single_item_multiple_types() {
add_task(async function multiple_tabs_under_max() {
let urls = [];
for (let i = 0; i < 5; i++) {
urls.push("mochi.test/multi" + i);
urls.push("example.com/multi" + i);
}
await dropText(urls.join("\n"), [
"http://mochi.test/multi0",
"http://mochi.test/multi1",
"http://mochi.test/multi2",
"http://mochi.test/multi3",
"http://mochi.test/multi4",
"http://example.com/multi0",
"http://example.com/multi1",
"http://example.com/multi2",
"http://example.com/multi3",
"http://example.com/multi4",
]);
});
add_task(async function multiple_tabs_over_max_accept() {
@ -108,14 +110,14 @@ add_task(async function multiple_tabs_over_max_accept() {
let urls = [];
for (let i = 0; i < 5; i++) {
urls.push("mochi.test/accept" + i);
urls.push("example.com/accept" + i);
}
await dropText(urls.join("\n"), [
"http://mochi.test/accept0",
"http://mochi.test/accept1",
"http://mochi.test/accept2",
"http://mochi.test/accept3",
"http://mochi.test/accept4",
"http://example.com/accept0",
"http://example.com/accept1",
"http://example.com/accept2",
"http://example.com/accept3",
"http://example.com/accept4",
]);
await confirmPromise;
@ -129,7 +131,7 @@ add_task(async function multiple_tabs_over_max_cancel() {
let urls = [];
for (let i = 0; i < 5; i++) {
urls.push("mochi.test/cancel" + i);
urls.push("example.com/cancel" + i);
}
await dropText(urls.join("\n"), []);
@ -142,19 +144,19 @@ add_task(async function multiple_tabs_over_max_cancel() {
add_task(async function multiple_urls() {
await dropText(
`
mochi.test/urls0
mochi.test/urls1
mochi.test/urls2
example.com/urls0
example.com/urls1
example.com/urls2
non url0
mochi.test/urls3
example.com/urls3
non url1
non url2
`,
[
"http://mochi.test/urls0",
"http://mochi.test/urls1",
"http://mochi.test/urls2",
"http://mochi.test/urls3",
"http://example.com/urls0",
"http://example.com/urls1",
"http://example.com/urls2",
"http://example.com/urls3",
]
);
});
@ -195,7 +197,7 @@ async function drop(dragData, expectedURLs) {
let awaitDrop = BrowserTestUtils.waitForEvent(newTabButton, "drop");
let loadedPromises = expectedURLs.map(url =>
BrowserTestUtils.waitForNewTab(gBrowser, url, false, true)
BrowserTestUtils.waitForNewTab(gBrowser, url, true, true)
);
EventUtils.synthesizeDrop(

View file

@ -1,3 +1,5 @@
/* eslint-disable @microsoft/sdl/no-insecure-url */
// TODO (Bug 1680996): Investigate why this test takes a long time.
requestLongerTimeout(2);
@ -28,7 +30,7 @@ add_task(async function test_setup() {
});
add_task(async function single_url() {
await dropText("mochi.test/first", ["http://mochi.test/first"]);
await dropText("example.com/first", ["http://example.com/first"]);
});
add_task(async function single_javascript() {
await dropText("javascript:'bad'", []);
@ -40,37 +42,37 @@ add_task(async function single_search() {
await dropText("search this", [ANY_URL]);
});
add_task(async function single_url2() {
await dropText("mochi.test/second", ["http://mochi.test/second"]);
await dropText("example.com/second", ["http://example.com/second"]);
});
add_task(async function single_data_url() {
await dropText("data:text/html,bad", []);
});
add_task(async function single_url3() {
await dropText("mochi.test/third", ["http://mochi.test/third"]);
await dropText("example.com/third", ["http://example.com/third"]);
});
// Single text/plain item, with multiple links.
add_task(async function multiple_urls() {
await dropText("mochi.test/1\nmochi.test/2", [
"http://mochi.test/1",
"http://mochi.test/2",
await dropText("example.com/1\nexample.com/2", [
"http://example.com/1",
"http://example.com/2",
]);
});
add_task(async function multiple_urls_javascript() {
await dropText("javascript:'bad1'\nmochi.test/3", []);
await dropText("javascript:'bad1'\nexample.com/3", []);
});
add_task(async function multiple_urls_data() {
await dropText("mochi.test/4\ndata:text/html,bad1", []);
await dropText("example.com/4\ndata:text/html,bad1", []);
});
// Multiple text/plain items, with single and multiple links.
add_task(async function multiple_items_single_and_multiple_links() {
await drop(
[
[{ type: "text/plain", data: "mochi.test/5" }],
[{ type: "text/plain", data: "mochi.test/6\nmochi.test/7" }],
[{ type: "text/plain", data: "example.com/5" }],
[{ type: "text/plain", data: "example.com/6\nexample.com/7" }],
],
["http://mochi.test/5", "http://mochi.test/6", "http://mochi.test/7"]
["http://example.com/5", "http://example.com/6", "http://example.com/7"]
);
});
@ -82,11 +84,11 @@ add_task(async function single_moz_url_multiple_links() {
[
{
type: "text/x-moz-url",
data: "mochi.test/8\nTITLE8\nmochi.test/9\nTITLE9",
data: "example.com/8\nTITLE8\nexample.com/9\nTITLE9",
},
],
],
["http://mochi.test/8", "http://mochi.test/9"]
["http://example.com/8", "http://example.com/9"]
);
});
@ -95,11 +97,11 @@ add_task(async function single_item_multiple_types() {
await drop(
[
[
{ type: "text/plain", data: "mochi.test/10" },
{ type: "text/x-moz-url", data: "mochi.test/11\nTITLE11" },
{ type: "text/plain", data: "example.com/10" },
{ type: "text/x-moz-url", data: "example.com/11\nTITLE11" },
],
],
["http://mochi.test/11"]
["http://example.com/11"]
);
});
@ -107,14 +109,14 @@ add_task(async function single_item_multiple_types() {
add_task(async function multiple_tabs_under_max() {
let urls = [];
for (let i = 0; i < 5; i++) {
urls.push("mochi.test/multi" + i);
urls.push("example.com/multi" + i);
}
await dropText(urls.join("\n"), [
"http://mochi.test/multi0",
"http://mochi.test/multi1",
"http://mochi.test/multi2",
"http://mochi.test/multi3",
"http://mochi.test/multi4",
"http://example.com/multi0",
"http://example.com/multi1",
"http://example.com/multi2",
"http://example.com/multi3",
"http://example.com/multi4",
]);
});
add_task(async function multiple_tabs_over_max_accept() {
@ -124,14 +126,14 @@ add_task(async function multiple_tabs_over_max_accept() {
let urls = [];
for (let i = 0; i < 5; i++) {
urls.push("mochi.test/accept" + i);
urls.push("example.com/accept" + i);
}
await dropText(urls.join("\n"), [
"http://mochi.test/accept0",
"http://mochi.test/accept1",
"http://mochi.test/accept2",
"http://mochi.test/accept3",
"http://mochi.test/accept4",
"http://example.com/accept0",
"http://example.com/accept1",
"http://example.com/accept2",
"http://example.com/accept3",
"http://example.com/accept4",
]);
await confirmPromise;
@ -145,7 +147,7 @@ add_task(async function multiple_tabs_over_max_cancel() {
let urls = [];
for (let i = 0; i < 5; i++) {
urls.push("mochi.test/cancel" + i);
urls.push("example.com/cancel" + i);
}
await dropText(urls.join("\n"), []);
@ -167,7 +169,7 @@ async function drop(dragData, expectedURLs) {
let awaitDrop = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "drop");
let loadedPromises = expectedURLs.map(url =>
BrowserTestUtils.waitForNewTab(gBrowser, url, false, true)
BrowserTestUtils.waitForNewTab(gBrowser, url, true, true)
);
// A drop type of "link" onto an existing tab would normally trigger a

View file

@ -11,7 +11,7 @@ EXPORTS.mozilla.browser += [
"AboutRedirector.h",
]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
SOURCES += [
"AboutRedirector.cpp",

View file

@ -1,7 +0,0 @@
[DEFAULT]
skip-if = toolkit == 'android' # bug 1730213
head =
# make the firefox services (eg newtab-service) available to xpcshell
firefox-appdir = browser
[test_getURIFlags.js]

View file

@ -0,0 +1,7 @@
[DEFAULT]
skip-if = ["toolkit == 'android'"] # bug 1730213
head = '' # no value from INI
# make the firefox services (eg newtab-service) available to xpcshell
firefox-appdir = "browser"
["test_getURIFlags.js"]

View file

@ -20,4 +20,4 @@ FINAL_TARGET_FILES.actors += [
BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.toml"]
MOCHITEST_CHROME_MANIFESTS += ["tests/chrome/chrome.toml"]
XPCSHELL_TESTS_MANIFESTS += ["tests/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["tests/unit/xpcshell.toml"]

View file

@ -1,7 +0,0 @@
[DEFAULT]
skip-if = toolkit == 'android' # bug 1730213
head = head.js
firefox-appdir = browser
[test_getPotentialBreachesByLoginGUID.js]
tags = remote-settings

View file

@ -0,0 +1,7 @@
[DEFAULT]
skip-if = ["toolkit == 'android'"] # bug 1730213
head = "head.js"
firefox-appdir = "browser"
["test_getPotentialBreachesByLoginGUID.js"]
tags = "remote-settings"

View file

@ -7,7 +7,7 @@
with Files("**"):
BUG_COMPONENT = ("Toolkit", "Telemetry")
XPCSHELL_TESTS_MANIFESTS += ["test/xpcshell/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/xpcshell/xpcshell.toml"]
BROWSER_CHROME_MANIFESTS += ["test/browser/browser.toml"]

View file

@ -1,11 +0,0 @@
[DEFAULT]
firefox-appdir = browser
skip-if = (os != "win" && toolkit != "cocoa") # Only available on Windows and macOS
head = head.js
prefs =
browser.attribution.macos.enabled=true
[test_AttributionCode.js]
[test_MacAttribution.js]
skip-if = toolkit != "cocoa" # osx specific tests
[test_attribution_parsing.js]

View file

@ -0,0 +1,15 @@
[DEFAULT]
firefox-appdir = "browser"
run-if = [
"os == 'win'",
"os == 'mac'",
]
head = "head.js"
prefs = ["browser.attribution.macos.enabled=true"]
["test_AttributionCode.js"]
["test_MacAttribution.js"]
run-if = ["os == 'mac'"] # osx specific tests
["test_attribution_parsing.js"]

View file

@ -9,7 +9,7 @@ DIRS += [
]
BROWSER_CHROME_MANIFESTS += ["test/browser.toml"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
TESTING_JS_MODULES += [
"test/CustomizableUITestUtils.sys.mjs",

View file

@ -1,6 +0,0 @@
[DEFAULT]
head =
skip-if = toolkit == 'android' # bug 1730213
firefox-appdir = browser
[test_unified_extensions_migration.js]

View file

@ -0,0 +1,6 @@
[DEFAULT]
head = '' # no value from INI
skip-if = ["toolkit == 'android'"] # bug 1730213
firefox-appdir = "browser"
["test_unified_extensions_migration.js"]

View file

@ -18,5 +18,5 @@ TESTING_JS_MODULES += [
"DoHTestUtils.sys.mjs",
]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
BROWSER_CHROME_MANIFESTS += ["test/browser/browser.toml"]

View file

@ -1,12 +0,0 @@
[DEFAULT]
skip-if = toolkit == 'android' # bug 1730213
head = head.js
firefox-appdir = browser
support-files =
../../../../../netwerk/test/unit/http2-ca.pem
[test_heuristics.js]
[test_DNSLookup.js]
skip-if = debug # Bug 1617845
[test_LookupAggregator.js]
[test_TRRRacer.js]

View file

@ -0,0 +1,14 @@
[DEFAULT]
skip-if = ["toolkit == 'android'"] # bug 1730213
head = "head.js"
firefox-appdir = "browser"
support-files = ["../../../../../netwerk/test/unit/http2-ca.pem"]
["test_DNSLookup.js"]
skip-if = ["debug"] # Bug 1617845
["test_LookupAggregator.js"]
["test_TRRRacer.js"]
["test_heuristics.js"]

View file

@ -27,4 +27,4 @@ if toolkit == "cocoa":
with Files("**"):
BUG_COMPONENT = ("Firefox", "Downloads Panel")
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]

View file

@ -1,9 +0,0 @@
[DEFAULT]
head = head.js
firefox-appdir = browser
skip-if = toolkit == 'android' # bug 1730213
[test_DownloadLastDir_basics.js]
[test_DownloadsCommon_getMimeInfo.js]
[test_DownloadsCommon_isFileOfType.js]
[test_DownloadsViewableInternally.js]

View file

@ -0,0 +1,12 @@
[DEFAULT]
head = "head.js"
firefox-appdir = "browser"
skip-if = ["toolkit == 'android'"] # bug 1730213
["test_DownloadLastDir_basics.js"]
["test_DownloadsCommon_getMimeInfo.js"]
["test_DownloadsCommon_isFileOfType.js"]
["test_DownloadsViewableInternally.js"]

View file

@ -17,4 +17,4 @@ BROWSER_CHROME_MANIFESTS += [
"browser/show_home_button/browser.toml",
]
XPCSHELL_TESTS_MANIFESTS += ["xpcshell/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["xpcshell/xpcshell.toml"]

View file

@ -1,33 +0,0 @@
[DEFAULT]
skip-if = toolkit == 'android' # bug 1730213
firefox-appdir = browser
head = head.js
support-files =
policytest_v0.1.xpi
[test_3rdparty.js]
[test_addon_update.js]
[test_appupdateurl.js]
[test_bug1658259.js]
[test_cleanup.js]
[test_clear_blocked_cookies.js]
[test_containers.js]
[test_defaultbrowsercheck.js]
[test_empty_policy.js]
[test_exempt_domain_file_type_pairs_from_file_type_download_warnings.js]
[test_extensions.js]
[test_extensionsettings.js]
[test_macosparser_unflatten.js]
skip-if = os != 'mac'
[test_permissions.js]
[test_policy_search_engine.js]
[test_popups_cookies_addons.js]
support-files = config_popups_cookies_addons.json
[test_preferences.js]
[test_proxy.js]
[test_requestedlocales.js]
[test_runOnce_helper.js]
[test_simple_pref_policies.js]
[test_sorted_alphabetically.js]
[test_telemetry.js]
[test_appupdatepin.js]

View file

@ -0,0 +1,55 @@
[DEFAULT]
skip-if = ["toolkit == 'android'"] # bug 1730213
firefox-appdir = "browser"
head = "head.js"
support-files = ["policytest_v0.1.xpi"]
["test_3rdparty.js"]
["test_addon_update.js"]
["test_appupdatepin.js"]
["test_appupdateurl.js"]
["test_bug1658259.js"]
["test_cleanup.js"]
["test_clear_blocked_cookies.js"]
["test_containers.js"]
["test_defaultbrowsercheck.js"]
["test_empty_policy.js"]
["test_exempt_domain_file_type_pairs_from_file_type_download_warnings.js"]
["test_extensions.js"]
["test_extensionsettings.js"]
["test_macosparser_unflatten.js"]
run-if = ["os == 'mac'"]
["test_permissions.js"]
["test_policy_search_engine.js"]
["test_popups_cookies_addons.js"]
support-files = ["config_popups_cookies_addons.json"]
["test_preferences.js"]
["test_proxy.js"]
["test_requestedlocales.js"]
["test_runOnce_helper.js"]
["test_simple_pref_policies.js"]
["test_sorted_alphabetically.js"]
["test_telemetry.js"]

View file

@ -33,5 +33,5 @@ BROWSER_CHROME_MANIFESTS += [
MOCHITEST_MANIFESTS += ["test/mochitest/mochitest.toml"]
XPCSHELL_TESTS_MANIFESTS += [
"test/xpcshell/xpcshell.ini",
"test/xpcshell/xpcshell.toml",
]

View file

@ -1,48 +0,0 @@
[DEFAULT]
skip-if = toolkit == 'android' # bug 1730213
head = head.js
firefox-appdir = browser
tags = webextensions condprof
dupe-manifest =
[test_ext_bookmarks.js]
skip-if = condprof # Bug 1769184 - by design for now
[test_ext_browsingData_downloads.js]
[test_ext_browsingData_passwords.js]
skip-if =
tsan # Times out, bug 1612707
[test_ext_browsingData_settings.js]
[test_ext_chrome_settings_overrides_home.js]
[test_ext_chrome_settings_overrides_update.js]
[test_ext_distribution_popup.js]
[test_ext_history.js]
[test_ext_homepage_overrides_private.js]
[test_ext_manifest.js]
[test_ext_manifest_commands.js]
run-sequentially = very high failure rate in parallel
[test_ext_manifest_omnibox.js]
[test_ext_manifest_permissions.js]
[test_ext_menu_caller.js]
[test_ext_menu_startup.js]
[test_ext_normandyAddonStudy.js]
[test_ext_pageAction_shutdown.js]
[test_ext_pkcs11_management.js]
[test_ext_settings_overrides_defaults.js]
skip-if = condprof # Bug 1776135 - by design, modifies search settings at start of test
support-files =
data/test/manifest.json
data/test2/manifest.json
[test_ext_settings_overrides_search.js]
[test_ext_settings_overrides_search_mozParam.js]
skip-if = condprof # Bug 1776652
support-files =
data/test/manifest.json
[test_ext_settings_overrides_shutdown.js]
[test_ext_settings_validate.js]
[test_ext_topSites.js]
skip-if = condprof # Bug 1769184 - by design for now
[test_ext_url_overrides_newtab.js]
[test_ext_url_overrides_newtab_update.js]
[test_ext_urlbar.js]
skip-if = tsan # Unreasonably slow, bug 1612707
condprof # Bug 1769184 - by design for now

View file

@ -0,0 +1,75 @@
[DEFAULT]
skip-if = ["os == 'android'"] # bug 1730213
head = "head.js"
firefox-appdir = "browser"
tags = "webextensions condprof"
dupe-manifest = ""
["test_ext_bookmarks.js"]
skip-if = ["condprof"] # Bug 1769184 - by design for now
["test_ext_browsingData_downloads.js"]
["test_ext_browsingData_passwords.js"]
skip-if = ["tsan"] # Times out, bug 1612707
["test_ext_browsingData_settings.js"]
["test_ext_chrome_settings_overrides_home.js"]
["test_ext_chrome_settings_overrides_update.js"]
["test_ext_distribution_popup.js"]
["test_ext_history.js"]
["test_ext_homepage_overrides_private.js"]
["test_ext_manifest.js"]
["test_ext_manifest_commands.js"]
run-sequentially = "very high failure rate in parallel"
["test_ext_manifest_omnibox.js"]
["test_ext_manifest_permissions.js"]
["test_ext_menu_caller.js"]
["test_ext_menu_startup.js"]
["test_ext_normandyAddonStudy.js"]
["test_ext_pageAction_shutdown.js"]
["test_ext_pkcs11_management.js"]
["test_ext_settings_overrides_defaults.js"]
skip-if = ["condprof"] # Bug 1776135 - by design, modifies search settings at start of test
support-files = [
"data/test/manifest.json",
"data/test2/manifest.json",
]
["test_ext_settings_overrides_search.js"]
["test_ext_settings_overrides_search_mozParam.js"]
skip-if = ["condprof"] # Bug 1776652
support-files = ["data/test/manifest.json"]
["test_ext_settings_overrides_shutdown.js"]
["test_ext_settings_validate.js"]
["test_ext_topSites.js"]
skip-if = ["condprof"] # Bug 1769184 - by design for now
["test_ext_url_overrides_newtab.js"]
["test_ext_url_overrides_newtab_update.js"]
["test_ext_urlbar.js"]
skip-if = [
"tsan", # Unreasonably slow, bug 1612707
"condprof", # Bug 1769184 - by design for now
]

View file

@ -5,6 +5,7 @@
.search-container {
border: 1px solid var(--fxview-border);
color: var(--fxview-text-primary-color);
display: inline-flex;
position: relative;
}

View file

@ -10,6 +10,10 @@ import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
* search query trigger a `fxview-search-textbox-query` event with the current
* query value.
*
* There is no actual searching done here. That needs to be implemented by the
* `fxview-search-textbox-query` event handler. `searchTabList()` from
* `helpers.mjs` can be used as a starting point.
*
* @property {string} placeholder
* The placeholder text for the search box.
* @property {string} query

View file

@ -9,6 +9,7 @@ import {
when,
} from "chrome://global/content/vendor/lit.all.mjs";
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
import { escapeRegExp } from "./helpers.mjs";
const NOW_THRESHOLD_MS = 91000;
const lazy = {};
@ -548,7 +549,15 @@ export class FxviewTabRow extends MozLitElement {
id="fxview-tab-row-url"
?hidden=${this.compact}
>
${this.formatURIForDisplay(this.url)}
${when(
this.searchQuery,
() =>
this.#highlightSearchMatches(
this.searchQuery,
this.formatURIForDisplay(this.url)
),
() => this.formatURIForDisplay(this.url)
)}
</span>
<span
class="fxview-tab-row-date"
@ -600,7 +609,7 @@ export class FxviewTabRow extends MozLitElement {
*/
#highlightSearchMatches(query, string) {
const fragments = [];
const regex = RegExp(this.#escapeRegExp(query), "dgi");
const regex = RegExp(escapeRegExp(query), "dgi");
let prevIndexEnd = 0;
let result;
while ((result = regex.exec(string)) !== null) {
@ -614,11 +623,6 @@ export class FxviewTabRow extends MozLitElement {
fragments.push(string.substring(prevIndexEnd));
return fragments;
}
// from MDN...
#escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
}
customElements.define("fxview-tab-row", FxviewTabRow);

View file

@ -14,6 +14,15 @@ ChromeUtils.defineLazyGetter(lazy, "relativeTimeFormat", () => {
return new Services.intl.RelativeTimeFormat(undefined, { style: "narrow" });
});
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"searchEnabledPref",
"browser.firefox-view.search.enabled"
);
// Cutoff of 1.5 minutes + 1 second to determine what text string to display
export const NOW_THRESHOLD_MS = 91000;
@ -147,3 +156,33 @@ export function placeLinkOnClipboard(title, uri) {
Services.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
}
/**
* Check the user preference to enable search functionality in Firefox View.
*
* @returns {boolean} The preference value.
*/
export function isSearchEnabled() {
return lazy.searchEnabledPref;
}
/**
* Escape special characters for regular expressions from a string.
*
* @param {string} string
* The string to sanitize.
* @returns {string} The sanitized string.
*/
export function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
/**
* Search a tab list for items that match the given query.
*/
export function searchTabList(query, tabList) {
const regex = RegExp(escapeRegExp(query), "i");
return tabList.filter(
({ title, url }) => regex.test(title) || regex.test(url)
);
}

View file

@ -7,6 +7,7 @@ import {
ifDefined,
when,
} from "chrome://global/content/vendor/lit.all.mjs";
import { isSearchEnabled } from "./helpers.mjs";
import { ViewPage } from "./viewpage.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://browser/content/migration/migration-wizard.mjs";
@ -26,11 +27,6 @@ let XPCOMUtils = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
).XPCOMUtils;
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"searchEnabledPref",
"browser.firefox-view.search.enabled"
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"maxRowsPref",
@ -544,7 +540,7 @@ class HistoryInView extends ViewPage {
></h2>
<div class="history-sort-options">
${when(
lazy.searchEnabledPref,
isSearchEnabled(),
() => html` <div class="history-sort-option">
<fxview-search-textbox
.query=${this.searchQuery}

View file

@ -32,6 +32,7 @@ browser.jar:
content/browser/firefoxview/tab-pickup-container.mjs
content/browser/firefoxview/tab-pickup-list.mjs
content/browser/firefoxview/recently-closed-tabs.mjs
content/browser/firefoxview/recentlyclosed.css
content/browser/firefoxview/recentlyclosed.mjs
content/browser/firefoxview/viewpage.mjs
content/browser/firefoxview/history-empty.svg (content/history-empty.svg)

View file

@ -0,0 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
.search-container {
margin-block-start: 35px;
}

View file

@ -2,7 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { classMap, html } from "chrome://global/content/vendor/lit.all.mjs";
import {
classMap,
html,
ifDefined,
when,
} from "chrome://global/content/vendor/lit.all.mjs";
import { isSearchEnabled, searchTabList } from "./helpers.mjs";
import { ViewPage } from "./viewpage.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://browser/content/firefoxview/card-container.mjs";
@ -31,11 +37,18 @@ class RecentlyClosedTabsInView extends ViewPage {
this.fullyUpdated = false;
this.maxTabsLength = this.recentBrowsing ? 5 : 25;
this.recentlyClosedTabs = [];
this.searchQuery = "";
this.searchResults = null;
}
static properties = {
searchResults: { type: Array },
};
static queries = {
cardEl: "card-container",
emptyState: "fxview-empty-state",
searchTextbox: "fxview-search-textbox",
tabList: "fxview-tab-list",
};
@ -128,6 +141,9 @@ class RecentlyClosedTabsInView extends ViewPage {
this.maxTabsLength
);
this.normalizeRecentlyClosedData();
if (this.searchQuery) {
this.#updateSearchResults();
}
this.requestUpdate();
}
@ -274,11 +290,26 @@ class RecentlyClosedTabsInView extends ViewPage {
rel="stylesheet"
href="chrome://browser/content/firefoxview/firefoxview-next.css"
/>
<link
rel="stylesheet"
href="chrome://browser/content/firefoxview/recentlyclosed.css"
/>
<div class="sticky-container bottom-fade" ?hidden=${!this.selectedTab}>
<h2
class="page-header heading-large"
data-l10n-id="firefoxview-recently-closed-header"
></h2>
${when(
isSearchEnabled(),
() => html`<div class="search-container">
<fxview-search-textbox
.query=${this.searchQuery}
data-l10n-id="firefoxview-search-text-box-recentlyclosed"
data-l10n-attrs="placeholder"
@fxview-search-textbox-query=${this.onSearchQuery}
></fxview-search-textbox>
</div>`
)}
</div>
<div class=${classMap({ "cards-container": this.selectedTab })}>
<card-container
@ -298,7 +329,8 @@ class RecentlyClosedTabsInView extends ViewPage {
?hidden=${!this.recentlyClosedTabs.length}
slot="main"
.maxTabsLength=${this.maxTabsLength}
.tabItems=${this.recentlyClosedTabs}
.searchQuery=${ifDefined(this.searchResults && this.searchQuery)}
.tabItems=${this.searchResults || this.recentlyClosedTabs}
@fxview-tab-list-secondary-action=${this.onDismissTab}
@fxview-tab-list-primary-action=${this.onReopenTab}
></fxview-tab-list>
@ -320,5 +352,16 @@ class RecentlyClosedTabsInView extends ViewPage {
</div>
`;
}
onSearchQuery(e) {
this.searchQuery = e.detail.query;
this.#updateSearchResults();
}
#updateSearchResults() {
this.searchResults = this.searchQuery
? searchTabList(this.searchQuery, this.recentlyClosedTabs)
: null;
}
}
customElements.define("view-recentlyclosed", RecentlyClosedTabsInView);

View file

@ -11,6 +11,7 @@ ChromeUtils.defineESModuleGetters(globalThis, {
const FXVIEW_NEXT_ENABLED_PREF = "browser.tabs.firefox-view-next";
const NEVER_REMEMBER_HISTORY_PREF = "browser.privatebrowsing.autostart";
const SEARCH_ENABLED_PREF = "browser.firefox-view.search.enabled";
const RECENTLY_CLOSED_EVENT = [
["firefoxview_next", "recently_closed", "tabs", undefined],
];
@ -228,7 +229,12 @@ async function recentlyClosedDismissTelemetry() {
}
add_setup(async () => {
await SpecialPowers.pushPrefEnv({ set: [[FXVIEW_NEXT_ENABLED_PREF, true]] });
await SpecialPowers.pushPrefEnv({
set: [
[FXVIEW_NEXT_ENABLED_PREF, true],
[SEARCH_ENABLED_PREF, true],
],
});
registerCleanupFunction(async () => {
await SpecialPowers.popPrefEnv();
clearHistory();
@ -532,3 +538,40 @@ add_task(async function test_observers_removed_when_view_is_hidden() {
BrowserTestUtils.removeTab(tab);
});
});
add_task(async function test_search() {
let { cleanup, expectedURLs } = await prepareClosedTabs();
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
navigateToCategory(document, "recentlyclosed");
const [listElem] = await waitForRecentlyClosedTabsList(document);
const recentlyClosedComponent = document.querySelector(
"view-recentlyclosed:not([slot=recentlyclosed])"
);
const { searchTextbox, tabList } = recentlyClosedComponent;
info("Input a search query.");
EventUtils.synthesizeMouseAtCenter(searchTextbox, {}, content);
EventUtils.sendString("example.com", content);
await TestUtils.waitForCondition(
() => listElem.rowEls.length === 1,
"There is one matching search result."
);
info("Clear the search query.");
EventUtils.synthesizeMouseAtCenter(searchTextbox.clearButton, {}, content);
await TestUtils.waitForCondition(
() => listElem.rowEls.length === expectedURLs.length,
"The original list is restored."
);
info("Input a bogus search query.");
EventUtils.synthesizeMouseAtCenter(searchTextbox, {}, content);
EventUtils.sendString("Bogus Query", content);
await TestUtils.waitForCondition(
() => tabList.shadowRoot.querySelector("fxview-empty-state"),
"There are no matching search results."
);
});
await cleanup();
});

View file

@ -7,7 +7,7 @@
with Files("**"):
BUG_COMPONENT = ("Firefox", "Installer")
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
EXTRA_JS_MODULES += [
"InstallerPrefs.sys.mjs",

View file

@ -1,20 +0,0 @@
[DEFAULT]
head = head.js
firefox-appdir = browser
skip-if = os != 'win'
# These tests must all run sequentially because they use the same registry key.
# It might be possible to get around this requirement by overriding the install
# hash so each test uses a different key, and if a lot more tests are added here
# then it would be worth looking into that.
[test_empty_prefs_list.js]
run-sequentially = Uses the Windows registry
skip-if = os == 'win' && msix # https://bugzilla.mozilla.org/show_bug.cgi?id=1807932
[test_invalid_name.js]
run-sequentially = Uses the Windows registry
[test_nonbool_pref.js]
run-sequentially = Uses the Windows registry
[test_pref_change.js]
run-sequentially = Uses the Windows registry
[test_pref_values.js]
run-sequentially = Uses the Windows registry

View file

@ -0,0 +1,25 @@
[DEFAULT]
head = "head.js"
firefox-appdir = "browser"
skip-if = ["os != 'win'"]
# These tests must all run sequentially because they use the same registry key.
# It might be possible to get around this requirement by overriding the install
# hash so each test uses a different key, and if a lot more tests are added here
# then it would be worth looking into that.
["test_empty_prefs_list.js"]
run-sequentially = "Uses the Windows registry"
skip-if = ["os == 'win' && msix"] # https://bugzilla.mozilla.org/show_bug.cgi?id=1807932
["test_invalid_name.js"]
run-sequentially = "Uses the Windows registry"
["test_nonbool_pref.js"]
run-sequentially = "Uses the Windows registry"
["test_pref_change.js"]
run-sequentially = "Uses the Windows registry"
["test_pref_values.js"]
run-sequentially = "Uses the Windows registry"

View file

@ -4,7 +4,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPCSHELL_TESTS_MANIFESTS += ["tests/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["tests/unit/xpcshell.toml"]
MARIONETTE_UNIT_MANIFESTS += ["tests/marionette/manifest.ini"]

View file

@ -1,61 +0,0 @@
[DEFAULT]
head = head_migration.js
tags = condprof
firefox-appdir = browser
skip-if = toolkit == 'android' # bug 1730213
prefs =
browser.migrate.showBookmarksToolbarAfterMigration=true
support-files =
Library/**
AppData/**
bookmarks.exported.html
bookmarks.exported.json
bookmarks.invalid.html
[test_360se_bookmarks.js]
skip-if = os != "win"
[test_360seMigrationUtils.js]
run-if = os == "win"
[test_BookmarksFileMigrator.js]
[test_ChromeMigrationUtils_path_chromium_snap.js]
run-if = os == "linux"
[test_Chrome_bookmarks.js]
[test_Chrome_corrupt_history.js]
[test_Chrome_credit_cards.js]
skip-if = os != "win" && os != "mac"
condprof # bug 1769154 - not realistic for condprof
[test_Chrome_extensions.js]
[test_Chrome_formdata.js]
[test_Chrome_history.js]
skip-if = os != "mac" # Relies on ULibDir
[test_Chrome_passwords.js]
skip-if = os != "win" && os != "mac"
condprof # bug 1769154 - not realistic for condprof
[test_Chrome_passwords_emptySource.js]
skip-if = os != "win" && os != "mac"
condprof # bug 1769154 - not realistic for condprof
support-files =
LibraryWithNoData/**
[test_ChromeMigrationUtils.js]
[test_ChromeMigrationUtils_path.js]
[test_Chrome_permissions.js]
[test_Edge_db_migration.js]
skip-if = os != "win"
[test_Edge_registry_migration.js]
skip-if = os != "win"
[test_PasswordFileMigrator.js]
[test_fx_telemetry.js]
[test_IE_bookmarks.js]
skip-if = !(os == "win" && bits == 64) # bug 1392396
[test_IE_history.js]
skip-if =
os != "win"
os == "win" && msix # https://bugzilla.mozilla.org/show_bug.cgi?id=1807928
[test_MigrationUtils_timedRetry.js]
skip-if = !debug && os == "mac" #Bug 1558330
[test_Safari_bookmarks.js]
skip-if = os != "mac"
[test_Safari_history.js]
skip-if = os != "mac"
[test_Safari_permissions.js]
skip-if = os != "mac"

View file

@ -0,0 +1,89 @@
[DEFAULT]
head = "head_migration.js"
tags = "condprof"
firefox-appdir = "browser"
skip-if = ["toolkit == 'android'"] # bug 1730213
prefs = ["browser.migrate.showBookmarksToolbarAfterMigration=true"]
support-files = [
"Library/**",
"AppData/**",
"bookmarks.exported.html",
"bookmarks.exported.json",
"bookmarks.invalid.html",
]
["test_360seMigrationUtils.js"]
run-if = ["os == 'win'"]
["test_360se_bookmarks.js"]
run-if = ["os == 'win'"]
["test_BookmarksFileMigrator.js"]
["test_ChromeMigrationUtils.js"]
["test_ChromeMigrationUtils_path.js"]
["test_ChromeMigrationUtils_path_chromium_snap.js"]
run-if = ["os == 'linux'"]
["test_Chrome_bookmarks.js"]
["test_Chrome_corrupt_history.js"]
["test_Chrome_credit_cards.js"]
skip-if = [
"os != 'win' && os != 'mac'",
"condprof", # bug 1769154 - not realistic for condprof
]
["test_Chrome_extensions.js"]
["test_Chrome_formdata.js"]
["test_Chrome_history.js"]
skip-if = ["os != 'mac'"] # Relies on ULibDir
["test_Chrome_passwords.js"]
skip-if = [
"os != 'win' && os != 'mac'",
"condprof", # bug 1769154 - not realistic for condprof
]
["test_Chrome_passwords_emptySource.js"]
skip-if = [
"os != 'win' && os != 'mac'",
"condprof", # bug 1769154 - not realistic for condprof
]
support-files = ["LibraryWithNoData/**"]
["test_Chrome_permissions.js"]
["test_Edge_db_migration.js"]
run-if = ["os == 'win'"]
["test_Edge_registry_migration.js"]
run-if = ["os == 'win'"]
["test_IE_bookmarks.js"]
run-if = ["os == 'win' && bits == 64"] # bug 1392396
["test_IE_history.js"]
run-if = ["os == 'win'"]
skip-if = ["os == 'win' && msix"] # https://bugzilla.mozilla.org/show_bug.cgi?id=1807928
["test_MigrationUtils_timedRetry.js"]
skip-if = ["os == 'mac' && !debug"] #Bug 1558330
["test_PasswordFileMigrator.js"]
["test_Safari_bookmarks.js"]
run-if = ["os == 'mac'"]
["test_Safari_history.js"]
run-if = ["os == 'mac'"]
["test_Safari_permissions.js"]
run-if = ["os == 'mac'"]
["test_fx_telemetry.js"]

View file

@ -109,4 +109,4 @@ if CONFIG["MOZ_UPDATER"]:
"tests/browser/whats_new_page/browser.toml",
]
XPCSHELL_TESTS_MANIFESTS += ["tests/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["tests/unit/xpcshell.toml"]

View file

@ -50,24 +50,6 @@ const LIGHT_WEIGHT_THEMES = {
DARK: "firefox-compact-dark@mozilla.org",
LIGHT: "firefox-compact-light@mozilla.org",
ALPENGLOW: "firefox-alpenglow@mozilla.org",
"PLAYMAKER-SOFT": "playmaker-soft-colorway@mozilla.org",
"PLAYMAKER-BALANCED": "playmaker-balanced-colorway@mozilla.org",
"PLAYMAKER-BOLD": "playmaker-bold-colorway@mozilla.org",
"EXPRESSIONIST-SOFT": "expressionist-soft-colorway@mozilla.org",
"EXPRESSIONIST-BALANCED": "expressionist-balanced-colorway@mozilla.org",
"EXPRESSIONIST-BOLD": "expressionist-bold-colorway@mozilla.org",
"VISIONARY-SOFT": "visionary-soft-colorway@mozilla.org",
"VISIONARY-BALANCED": "visionary-balanced-colorway@mozilla.org",
"VISIONARY-BOLD": "visionary-bold-colorway@mozilla.org",
"ACTIVIST-SOFT": "activist-soft-colorway@mozilla.org",
"ACTIVIST-BALANCED": "activist-balanced-colorway@mozilla.org",
"ACTIVIST-BOLD": "activist-bold-colorway@mozilla.org",
"DREAMER-SOFT": "dreamer-soft-colorway@mozilla.org",
"DREAMER-BALANCED": "dreamer-balanced-colorway@mozilla.org",
"DREAMER-BOLD": "dreamer-bold-colorway@mozilla.org",
"INNOVATOR-SOFT": "innovator-soft-colorway@mozilla.org",
"INNOVATOR-BALANCED": "innovator-balanced-colorway@mozilla.org",
"INNOVATOR-BOLD": "innovator-bold-colorway@mozilla.org",
};
class AboutWelcomeObserver {

View file

@ -188,8 +188,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* harmony import */ var _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6);
/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(11);
/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(19);
/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(10);
/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -792,19 +792,18 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* harmony import */ var _MRColorways__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7);
/* harmony import */ var _MobileDownloads__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8);
/* harmony import */ var _MultiSelect__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9);
/* harmony import */ var _Themes__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(10);
/* harmony import */ var _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(4);
/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(11);
/* harmony import */ var _CTAParagraph__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(12);
/* harmony import */ var _HeroImage__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(13);
/* harmony import */ var _OnboardingVideo__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(14);
/* harmony import */ var _AdditionalCTA__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(15);
/* harmony import */ var _EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(16);
/* harmony import */ var _AddonsPicker__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(17);
/* harmony import */ var _LinkParagraph__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(18);
/* harmony import */ var _MobileDownloads__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7);
/* harmony import */ var _MultiSelect__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8);
/* harmony import */ var _Themes__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9);
/* harmony import */ var _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4);
/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(10);
/* harmony import */ var _CTAParagraph__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(11);
/* harmony import */ var _HeroImage__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(12);
/* harmony import */ var _OnboardingVideo__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(13);
/* harmony import */ var _AdditionalCTA__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(14);
/* harmony import */ var _EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(15);
/* harmony import */ var _AddonsPicker__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(16);
/* harmony import */ var _LinkParagraph__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(17);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -823,7 +822,6 @@ __webpack_require__.r(__webpack_exports__);
const MultiStageProtonScreen = props => {
const {
autoAdvance,
@ -917,7 +915,7 @@ const ProtonScreenActionButtons = props => {
"data-l10n-args": addonName ? JSON.stringify({
"addon-name": addonName
}) : ""
})), content.additional_button ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AdditionalCTA__WEBPACK_IMPORTED_MODULE_12__.AdditionalCTA, {
})), content.additional_button ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AdditionalCTA__WEBPACK_IMPORTED_MODULE_11__.AdditionalCTA, {
content: content,
handleAction: props.handleAction
}) : null, content.checkbox ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
@ -933,7 +931,7 @@ const ProtonScreenActionButtons = props => {
text: content.checkbox.label
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", {
htmlFor: "action-checkbox"
}))) : null, content.secondary_button ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.SecondaryCTA, {
}))) : null, content.secondary_button ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.SecondaryCTA, {
content: content,
handleAction: props.handleAction
}) : null);
@ -1042,27 +1040,23 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
const {
content
} = this.props;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, content.tiles && content.tiles.type === "addons-picker" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AddonsPicker__WEBPACK_IMPORTED_MODULE_14__.AddonsPicker, {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, content.tiles && content.tiles.type === "addons-picker" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AddonsPicker__WEBPACK_IMPORTED_MODULE_13__.AddonsPicker, {
content: content,
message_id: this.props.messageId,
handleAction: this.props.handleAction
}) : null, content.tiles && content.tiles.type === "colorway" && content.tiles.colorways ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MRColorways__WEBPACK_IMPORTED_MODULE_3__.Colorways, {
}) : null, content.tiles && content.tiles.type === "theme" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Themes__WEBPACK_IMPORTED_MODULE_5__.Themes, {
content: content,
activeTheme: this.props.activeTheme,
handleAction: this.props.handleAction
}) : null, content.tiles && content.tiles.type === "theme" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Themes__WEBPACK_IMPORTED_MODULE_6__.Themes, {
content: content,
activeTheme: this.props.activeTheme,
handleAction: this.props.handleAction
}) : null, content.tiles && content.tiles.type === "mobile_downloads" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MobileDownloads__WEBPACK_IMPORTED_MODULE_4__.MobileDownloads, {
}) : null, content.tiles && content.tiles.type === "mobile_downloads" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MobileDownloads__WEBPACK_IMPORTED_MODULE_3__.MobileDownloads, {
data: content.tiles.data,
handleAction: this.props.handleAction
}) : null, content.tiles && content.tiles.type === "multiselect" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiSelect__WEBPACK_IMPORTED_MODULE_5__.MultiSelect, {
}) : null, content.tiles && content.tiles.type === "multiselect" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiSelect__WEBPACK_IMPORTED_MODULE_4__.MultiSelect, {
content: content,
activeMultiSelect: this.props.activeMultiSelect,
setActiveMultiSelect: this.props.setActiveMultiSelect,
handleAction: this.props.handleAction
}) : null, content.tiles && content.tiles.type === "migration-wizard" ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_13__.EmbeddedMigrationWizard, {
}) : null, content.tiles && content.tiles.type === "migration-wizard" ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_12__.EmbeddedMigrationWizard, {
handleAction: this.props.handleAction
}) : null);
}
@ -1082,7 +1076,7 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
}
renderLanguageSwitcher() {
return this.props.content.languageSwitcher ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_LanguageSwitcher__WEBPACK_IMPORTED_MODULE_8__.LanguageSwitcher, {
return this.props.content.languageSwitcher ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_LanguageSwitcher__WEBPACK_IMPORTED_MODULE_7__.LanguageSwitcher, {
content: this.props.content,
handleAction: this.props.handleAction,
negotiatedLanguage: this.props.negotiatedLanguage,
@ -1133,11 +1127,11 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
"aria-valuenow": currentStep,
"aria-valuemin": 1,
"aria-valuemax": total
}, content.progress_bar ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.ProgressBar, {
}, content.progress_bar ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.ProgressBar, {
step: currentStep,
previousStep: previousStep,
totalNumberOfScreens: total
}) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.StepsIndicator, {
}) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.StepsIndicator, {
order: this.props.order,
totalNumberOfScreens: total
}));
@ -1155,7 +1149,7 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "sr-only image-alt",
role: "img"
})), content.hero_image ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_HeroImage__WEBPACK_IMPORTED_MODULE_10__.HeroImage, {
})), content.hero_image ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_HeroImage__WEBPACK_IMPORTED_MODULE_9__.HeroImage, {
url: content.hero_image.url
}) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "message-text"
@ -1174,7 +1168,7 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
for (const item of content) {
switch (item.type) {
case "text":
elements.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_LinkParagraph__WEBPACK_IMPORTED_MODULE_15__.LinkParagraph, {
elements.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_LinkParagraph__WEBPACK_IMPORTED_MODULE_14__.LinkParagraph, {
text_content: item,
handleAction: this.props.handleAction
}));
@ -1235,7 +1229,7 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
className: `section-main ${isEmbeddedMigration ? "embedded-migration" : ""}`,
"hide-secondary-section": content.hide_secondary_section ? String(content.hide_secondary_section) : null,
role: "document"
}, content.secondary_button_top ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.SecondaryCTA, {
}, content.secondary_button_top ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.SecondaryCTA, {
content: content,
handleAction: this.props.handleAction,
position: "top"
@ -1265,10 +1259,10 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
...((_this$props$appAndSys = this.props.appAndSystemLocaleInfo) === null || _this$props$appAndSys === void 0 ? void 0 : _this$props$appAndSys.displayNames)
}),
"aria-flowto": (_this$props$messageId = this.props.messageId) !== null && _this$props$messageId !== void 0 && _this$props$messageId.includes("FEATURE_TOUR") ? "steps" : ""
})) : null, content.cta_paragraph ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_CTAParagraph__WEBPACK_IMPORTED_MODULE_9__.CTAParagraph, {
})) : null, content.cta_paragraph ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_CTAParagraph__WEBPACK_IMPORTED_MODULE_8__.CTAParagraph, {
content: content.cta_paragraph,
handleAction: this.props.handleAction
}) : null), content.video_container ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_OnboardingVideo__WEBPACK_IMPORTED_MODULE_11__.OnboardingVideo, {
}) : null), content.video_container ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_OnboardingVideo__WEBPACK_IMPORTED_MODULE_10__.OnboardingVideo, {
content: content.video_container,
handleAction: this.props.handleAction
}) : null, content.above_button_content ? this.renderOrderedContent(content.above_button_content) : null, this.renderContentTiles(), this.renderLanguageSwitcher(), !hideStepsIndicator && aboveButtonStepsIndicator ? this.renderStepsIndicator() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ProtonScreenActionButtons, {
@ -1289,189 +1283,6 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
/* 7 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ColorwayDescription": () => (/* binding */ ColorwayDescription),
/* harmony export */ "computeColorWay": () => (/* binding */ computeColorWay),
/* harmony export */ "computeVariationIndex": () => (/* binding */ computeVariationIndex),
/* harmony export */ "Colorways": () => (/* binding */ Colorways)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const ColorwayDescription = props => {
const {
colorway
} = props;
if (!colorway) {
return null;
}
const {
label,
description
} = colorway;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: description
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "colorway-text",
"data-l10n-args": JSON.stringify({
colorwayName: label
})
}));
}; // Return colorway as "default" for default theme variations Automatic, Light, Dark,
// Alpenglow theme and legacy colorways which is not supported in Colorway picker.
// For themes other then default, theme names exist in
// format colorway-variationId inside LIGHT_WEIGHT_THEMES in AboutWelcomeParent
function computeColorWay(themeName, systemVariations) {
return !themeName || themeName === "alpenglow" || systemVariations.includes(themeName) ? "default" : themeName.split("-")[0];
} // Set variationIndex based off activetheme value e.g. 'light', 'expressionist-soft'
function computeVariationIndex(themeName, systemVariations, variations, defaultVariationIndex) {
// Check if themeName is in systemVariations, if yes choose variationIndex by themeName
let index = systemVariations.findIndex(theme => theme === themeName);
if (index >= 0) {
return index;
} // If themeName is one of the colorways, select variation index from colorways
let variation = themeName === null || themeName === void 0 ? void 0 : themeName.split("-")[1];
index = variations.findIndex(element => element === variation);
if (index >= 0) {
return index;
}
return defaultVariationIndex;
}
function Colorways(props) {
let {
colorways,
darkVariation,
defaultVariationIndex,
systemVariations,
variations
} = props.content.tiles;
let hasReverted = false; // Active theme id from JSON e.g. "expressionist"
const activeId = computeColorWay(props.activeTheme, systemVariations);
const [colorwayId, setState] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(activeId);
const [variationIndex, setVariationIndex] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(defaultVariationIndex);
function revertToDefaultTheme() {
if (hasReverted) {
return;
} // Spoofing an event with current target value of "navigate_away"
// helps the handleAction method to read the colorways theme as "revert"
// which causes the initial theme to be activated.
// The "navigate_away" action is set in content in the colorways screen JSON config.
// Any value in the JSON for theme will work, provided it is not `<event>`.
const event = {
currentTarget: {
value: "navigate_away"
}
};
props.handleAction(event);
hasReverted = true;
} // Revert to default theme if the user navigates away from the page or spotlight modal
// before clicking on the primary button to officially set theme.
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
addEventListener("beforeunload", revertToDefaultTheme);
addEventListener("pagehide", revertToDefaultTheme);
return () => {
removeEventListener("beforeunload", revertToDefaultTheme);
removeEventListener("pagehide", revertToDefaultTheme);
};
}); // Update state any time activeTheme changes.
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
setState(computeColorWay(props.activeTheme, systemVariations));
setVariationIndex(computeVariationIndex(props.activeTheme, systemVariations, variations, defaultVariationIndex)); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.activeTheme]); //select a random colorway
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
//We don't want the default theme to be selected
const randomIndex = Math.floor(Math.random() * (colorways.length - 1)) + 1;
const randomColorwayId = colorways[randomIndex].id; // Change the variation to be the dark variation if configured and dark.
// Additional colorway changes will remain dark while system is unchanged.
if (darkVariation !== undefined && window.matchMedia("(prefers-color-scheme: dark)").matches) {
variations[variationIndex] = variations[darkVariation];
}
const value = `${randomColorwayId}-${variations[variationIndex]}`;
props.handleAction({
currentTarget: {
value
}
}); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "tiles-theme-container"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("fieldset", {
className: "tiles-theme-section"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: props.content.subtitle
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("legend", {
className: "sr-only"
})), colorways.map(({
id,
label,
tooltip
}) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
key: id + label,
text: typeof tooltip === "object" ? tooltip : {}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", {
className: "theme",
title: label,
"data-l10n-args": JSON.stringify({
colorwayName: label
})
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: typeof tooltip === "object" ? tooltip : {}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
className: "sr-only colorway label",
id: `${id}-label`,
"data-l10n-args": JSON.stringify({
colorwayName: tooltip
})
})), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: typeof label === "object" ? label : {}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", {
type: "radio",
"data-colorway": id,
name: "theme",
value: id === "default" ? systemVariations[variationIndex] : `${id}-${variations[variationIndex]}`,
checked: colorwayId === id,
className: "sr-only input",
onClick: props.handleAction,
"data-l10n-args": JSON.stringify({
colorwayName: label
}),
"aria-labelledby": `${id}-label`
})), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: `icon colorway ${colorwayId === id ? "selected" : ""} ${id}`
})))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ColorwayDescription, {
colorway: colorways.find(colorway => colorway.id === activeId)
}));
}
/***/ }),
/* 8 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "MarketplaceButtons": () => (/* binding */ MarketplaceButtons),
@ -1530,7 +1341,7 @@ const MobileDownloads = props => {
};
/***/ }),
/* 9 */
/* 8 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -1629,7 +1440,7 @@ const MultiSelect = ({
};
/***/ }),
/* 10 */
/* 9 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -1683,7 +1494,7 @@ const Themes = props => {
};
/***/ }),
/* 11 */
/* 10 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -1939,7 +1750,7 @@ function LanguageSwitcher(props) {
}
/***/ }),
/* 12 */
/* 11 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -1983,7 +1794,7 @@ const CTAParagraph = props => {
};
/***/ }),
/* 13 */
/* 12 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2023,7 +1834,7 @@ const HeroImage = props => {
};
/***/ }),
/* 14 */
/* 13 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2063,7 +1874,7 @@ const OnboardingVideo = props => {
};
/***/ }),
/* 15 */
/* 14 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2105,7 +1916,7 @@ const AdditionalCTA = ({
};
/***/ }),
/* 16 */
/* 15 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2159,7 +1970,7 @@ const EmbeddedMigrationWizard = ({
};
/***/ }),
/* 17 */
/* 16 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2251,7 +2062,7 @@ const AddonsPicker = props => {
};
/***/ }),
/* 18 */
/* 17 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2304,7 +2115,7 @@ const LinkParagraph = props => {
};
/***/ }),
/* 19 */
/* 18 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2349,7 +2160,7 @@ function addUtmParams(url, utmTerm) {
}
/***/ }),
/* 20 */
/* 19 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
@ -2360,7 +2171,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* harmony import */ var _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6);
/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(19);
/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -2555,7 +2366,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* harmony import */ var _components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
/* harmony import */ var _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20);
/* harmony import */ var _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(19);
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
/* This Source Code Form is subject to the terms of the Mozilla Public

View file

@ -1526,14 +1526,6 @@ html {
margin-block: -20px auto;
align-items: initial;
}
.onboardingContainer .screen[pos=split] .tiles-theme-container .colorway-text {
text-align: initial;
transition: var(--transition);
font-size: 13px;
line-height: 1.5;
min-height: 4.5em;
margin-block: 10px 20px;
}
.onboardingContainer .screen[pos=split] .tiles-theme-container .theme {
min-width: 38px;
}
@ -1655,10 +1647,6 @@ html {
min-width: 240px;
margin-inline: 0;
}
.onboardingContainer .screen[pos=split] .section-main .main-content .colorway-text {
text-align: center;
margin-inline: 30px;
}
.onboardingContainer .screen[pos=split] .section-main .main-content .steps {
padding-block: 0;
margin: 0;
@ -1887,18 +1875,10 @@ html {
cursor: pointer;
z-index: 0;
}
.onboardingContainer .tiles-theme-section .theme.colorway {
width: auto;
}
.onboardingContainer .tiles-theme-section .theme:focus, .onboardingContainer .tiles-theme-section .theme:active {
outline: initial;
outline-offset: initial;
}
.onboardingContainer .tiles-theme-section .theme .icon.colorway,
.onboardingContainer .tiles-theme-section .theme .label.colorway {
width: 20px;
height: 20px;
}
.onboardingContainer .tiles-theme-section .theme .icon {
background-size: cover;
width: 40px;
@ -1927,27 +1907,6 @@ html {
.onboardingContainer .tiles-theme-section .theme .icon.default, .onboardingContainer .tiles-theme-section .theme .icon.automatic {
background-image: url("resource://default-theme/icon.svg");
}
.onboardingContainer .tiles-theme-section .theme .icon.default.colorway, .onboardingContainer .tiles-theme-section .theme .icon.automatic.colorway {
background-image: url("chrome://activity-stream/content/data/content/assets/default.svg");
}
.onboardingContainer .tiles-theme-section .theme .icon.playmaker {
background-image: url("resource://builtin-themes/colorways/2022playmaker/balanced/icon.svg");
}
.onboardingContainer .tiles-theme-section .theme .icon.expressionist {
background-image: url("resource://builtin-themes/colorways/2022expressionist/balanced/icon.svg");
}
.onboardingContainer .tiles-theme-section .theme .icon.visionary {
background-image: url("resource://builtin-themes/colorways/2022visionary/balanced/icon.svg");
}
.onboardingContainer .tiles-theme-section .theme .icon.dreamer {
background-image: url("resource://builtin-themes/colorways/2022dreamer/balanced/icon.svg");
}
.onboardingContainer .tiles-theme-section .theme .icon.innovator {
background-image: url("resource://builtin-themes/colorways/2022innovator/balanced/icon.svg");
}
.onboardingContainer .tiles-theme-section .theme .icon.activist {
background-image: url("resource://builtin-themes/colorways/2022activist/balanced/icon.svg");
}
.onboardingContainer .tiles-theme-section .theme .text {
display: flex;
color: var(--in-content-page-color);
@ -2293,8 +2252,7 @@ html {
transition-delay: 1s;
}
.onboardingContainer .screen:not(.dialog-initial) .tiles-theme-section,
.onboardingContainer .screen:not(.dialog-initial) .multi-select-container,
.onboardingContainer .screen:not(.dialog-initial) .colorway-text {
.onboardingContainer .screen:not(.dialog-initial) .multi-select-container {
transition-delay: 0.2s;
}
.onboardingContainer .screen:not(.dialog-initial) .primary,
@ -2351,7 +2309,6 @@ html {
.onboardingContainer.transition-in .screen .welcome-text,
.onboardingContainer.transition-in .screen .multi-select-container,
.onboardingContainer.transition-in .screen .tiles-theme-section,
.onboardingContainer.transition-in .screen .colorway-text,
.onboardingContainer.transition-in .screen .primary,
.onboardingContainer.transition-in .screen .checkbox-container:not(.multi-select-item),
.onboardingContainer.transition-in .screen .secondary,
@ -2380,7 +2337,6 @@ html {
transition-delay: 0.1s;
}
.onboardingContainer.transition-out .screen:not(.dialog-last) .tiles-theme-section,
.onboardingContainer.transition-out .screen:not(.dialog-last) .colorway-text,
.onboardingContainer.transition-out .screen:not(.dialog-last) migration-wizard {
opacity: 0;
translate: 0 var(--translate);

View file

@ -782,15 +782,6 @@ html {
margin-block: -20px auto;
align-items: initial;
.colorway-text {
text-align: initial;
transition: var(--transition);
font-size: 13px;
line-height: 1.5;
min-height: 4.5em;
margin-block: 10px 20px;
}
.theme {
min-width: 38px;
}
@ -945,11 +936,6 @@ html {
margin-inline: 0;
}
.colorway-text {
text-align: center;
margin-inline: 30px;
}
.steps {
padding-block: 0;
margin: 0;
@ -1225,22 +1211,12 @@ html {
cursor: pointer;
z-index: 0;
&.colorway {
width: auto;
}
&:focus,
&:active {
outline: initial;
outline-offset: initial;
}
.icon.colorway,
.label.colorway {
width: 20px;
height: 20px;
}
.icon {
background-size: cover;
width: 40px;
@ -1276,34 +1252,6 @@ html {
&.default,
&.automatic {
background-image: url('resource://default-theme/icon.svg');
&.colorway {
background-image: url('chrome://activity-stream/content/data/content/assets/default.svg');
}
}
&.playmaker {
background-image: url('resource://builtin-themes/colorways/2022playmaker/balanced/icon.svg');
}
&.expressionist {
background-image: url('resource://builtin-themes/colorways/2022expressionist/balanced/icon.svg');
}
&.visionary {
background-image: url('resource://builtin-themes/colorways/2022visionary/balanced/icon.svg');
}
&.dreamer {
background-image: url('resource://builtin-themes/colorways/2022dreamer/balanced/icon.svg');
}
&.innovator {
background-image: url('resource://builtin-themes/colorways/2022innovator/balanced/icon.svg');
}
&.activist {
background-image: url('resource://builtin-themes/colorways/2022activist/balanced/icon.svg');
}
}
@ -1714,8 +1662,8 @@ html {
// Delays for transitioning-in of intermediate screens
.screen:not(.dialog-initial) {
.tiles-theme-section,
.multi-select-container,
.colorway-text {
.multi-select-container
{
transition-delay: 0.2s;
}
@ -1790,7 +1738,6 @@ html {
.welcome-text,
.multi-select-container,
.tiles-theme-section,
.colorway-text,
.primary,
.checkbox-container:not(.multi-select-item),
.secondary,
@ -1832,7 +1779,6 @@ html {
// content that is nested between inner main content and navigation CTAs
// requires an additional 0.1s transition to avoid overlap
.tiles-theme-section,
.colorway-text,
migration-wizard {
opacity: 0;
translate: 0 var(--translate);

View file

@ -1,200 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React, { useState, useEffect } from "react";
import { Localized } from "./MSLocalized";
export const ColorwayDescription = props => {
const { colorway } = props;
if (!colorway) {
return null;
}
const { label, description } = colorway;
return (
<Localized text={description}>
<div
className="colorway-text"
data-l10n-args={JSON.stringify({
colorwayName: label,
})}
/>
</Localized>
);
};
// Return colorway as "default" for default theme variations Automatic, Light, Dark,
// Alpenglow theme and legacy colorways which is not supported in Colorway picker.
// For themes other then default, theme names exist in
// format colorway-variationId inside LIGHT_WEIGHT_THEMES in AboutWelcomeParent
export function computeColorWay(themeName, systemVariations) {
return !themeName ||
themeName === "alpenglow" ||
systemVariations.includes(themeName)
? "default"
: themeName.split("-")[0];
}
// Set variationIndex based off activetheme value e.g. 'light', 'expressionist-soft'
export function computeVariationIndex(
themeName,
systemVariations,
variations,
defaultVariationIndex
) {
// Check if themeName is in systemVariations, if yes choose variationIndex by themeName
let index = systemVariations.findIndex(theme => theme === themeName);
if (index >= 0) {
return index;
}
// If themeName is one of the colorways, select variation index from colorways
let variation = themeName?.split("-")[1];
index = variations.findIndex(element => element === variation);
if (index >= 0) {
return index;
}
return defaultVariationIndex;
}
export function Colorways(props) {
let {
colorways,
darkVariation,
defaultVariationIndex,
systemVariations,
variations,
} = props.content.tiles;
let hasReverted = false;
// Active theme id from JSON e.g. "expressionist"
const activeId = computeColorWay(props.activeTheme, systemVariations);
const [colorwayId, setState] = useState(activeId);
const [variationIndex, setVariationIndex] = useState(defaultVariationIndex);
function revertToDefaultTheme() {
if (hasReverted) {
return;
}
// Spoofing an event with current target value of "navigate_away"
// helps the handleAction method to read the colorways theme as "revert"
// which causes the initial theme to be activated.
// The "navigate_away" action is set in content in the colorways screen JSON config.
// Any value in the JSON for theme will work, provided it is not `<event>`.
const event = {
currentTarget: {
value: "navigate_away",
},
};
props.handleAction(event);
hasReverted = true;
}
// Revert to default theme if the user navigates away from the page or spotlight modal
// before clicking on the primary button to officially set theme.
useEffect(() => {
addEventListener("beforeunload", revertToDefaultTheme);
addEventListener("pagehide", revertToDefaultTheme);
return () => {
removeEventListener("beforeunload", revertToDefaultTheme);
removeEventListener("pagehide", revertToDefaultTheme);
};
});
// Update state any time activeTheme changes.
useEffect(() => {
setState(computeColorWay(props.activeTheme, systemVariations));
setVariationIndex(
computeVariationIndex(
props.activeTheme,
systemVariations,
variations,
defaultVariationIndex
)
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.activeTheme]);
//select a random colorway
useEffect(() => {
//We don't want the default theme to be selected
const randomIndex = Math.floor(Math.random() * (colorways.length - 1)) + 1;
const randomColorwayId = colorways[randomIndex].id;
// Change the variation to be the dark variation if configured and dark.
// Additional colorway changes will remain dark while system is unchanged.
if (
darkVariation !== undefined &&
window.matchMedia("(prefers-color-scheme: dark)").matches
) {
variations[variationIndex] = variations[darkVariation];
}
const value = `${randomColorwayId}-${variations[variationIndex]}`;
props.handleAction({ currentTarget: { value } });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className="tiles-theme-container">
<div>
<fieldset className="tiles-theme-section">
<Localized text={props.content.subtitle}>
<legend className="sr-only" />
</Localized>
{colorways.map(({ id, label, tooltip }) => (
<Localized
key={id + label}
text={typeof tooltip === "object" ? tooltip : {}}
>
<label
className="theme"
title={label}
data-l10n-args={JSON.stringify({
colorwayName: label,
})}
>
<Localized text={typeof tooltip === "object" ? tooltip : {}}>
<span
className="sr-only colorway label"
id={`${id}-label`}
data-l10n-args={JSON.stringify({
colorwayName: tooltip,
})}
/>
</Localized>
<Localized text={typeof label === "object" ? label : {}}>
<input
type="radio"
data-colorway={id}
name="theme"
value={
id === "default"
? systemVariations[variationIndex]
: `${id}-${variations[variationIndex]}`
}
checked={colorwayId === id}
className="sr-only input"
onClick={props.handleAction}
data-l10n-args={JSON.stringify({
colorwayName: label,
})}
aria-labelledby={`${id}-label`}
/>
</Localized>
<div
className={`icon colorway ${
colorwayId === id ? "selected" : ""
} ${id}`}
/>
</label>
</Localized>
))}
</fieldset>
</div>
<ColorwayDescription
colorway={colorways.find(colorway => colorway.id === activeId)}
/>
</div>
);
}

View file

@ -5,7 +5,6 @@
import React, { useEffect, useState } from "react";
import { Localized } from "./MSLocalized";
import { AboutWelcomeUtils } from "../../lib/aboutwelcome-utils";
import { Colorways } from "./MRColorways";
import { MobileDownloads } from "./MobileDownloads";
import { MultiSelect } from "./MultiSelect";
import { Themes } from "./Themes";
@ -277,15 +276,6 @@ export class ProtonScreen extends React.PureComponent {
/>
) : null}
{content.tiles &&
content.tiles.type === "colorway" &&
content.tiles.colorways ? (
<Colorways
content={content}
activeTheme={this.props.activeTheme}
handleAction={this.props.handleAction}
/>
) : null}
{content.tiles &&
content.tiles.type === "theme" &&
content.tiles.data ? (
<Themes

View file

@ -16,7 +16,6 @@ Please note that some targeting attributes require stricter controls on the tele
* [backgroundTaskName](#backgroundtaskname)
* [blockedCountByType](#blockedcountbytype)
* [browserSettings](#browsersettings)
* [colorwaysActive](#colorwaysActive)
* [creditCardsSaved](#creditcardssaved)
* [currentDate](#currentdate)
* [defaultPDFHandler](#defaultpdfhandler)
@ -66,7 +65,6 @@ Please note that some targeting attributes require stricter controls on the tele
* [topFrecentSites](#topfrecentsites)
* [totalBlockedCount](#totalblockedcount)
* [totalBookmarksCount](#totalbookmarkscount)
* [userEnabledActiveColorway](#userEnabledActiveColorway)
* [userId](#userid)
* [userMonthlyActivity](#usermonthlyactivity)
* [userPrefersReducedMotion](#userprefersreducedmotion)

View file

@ -1,6 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.0334 4.89145C20.8652 6.70398 22 9.21946 22 12C22 17.5228 17.5228 22 12 22C9.91269 22 7.97474 21.3605 6.37141 20.2667L19.0334 4.89145ZM17.4788 3.63307L4.83963 18.9806C3.08254 17.1786 2 14.7157 2 12C2 6.47715 6.47715 2 12 2C14.0227 2 15.9052 2.60055 17.4788 3.63307ZM12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0Z" fill="#5B5B66"/>
</svg>

Before

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

View file

@ -32,7 +32,7 @@ SPHINX_TREES["docs"] = "docs"
SPHINX_TREES["content-src/asrouter/docs"] = "content-src/asrouter/docs"
XPCSHELL_TESTS_MANIFESTS += [
"test/xpcshell/xpcshell.ini",
"test/xpcshell/xpcshell.toml",
]
XPIDL_SOURCES += [

View file

@ -1,328 +0,0 @@
import React from "react";
import { shallow } from "enzyme";
import {
Colorways,
computeColorWay,
ColorwayDescription,
computeVariationIndex,
} from "content-src/aboutwelcome/components/MRColorways";
import { WelcomeScreen } from "content-src/aboutwelcome/components/MultiStageAboutWelcome";
describe("Multistage AboutWelcome module", () => {
let sandbox;
let COLORWAY_SCREEN_PROPS;
beforeEach(() => {
sandbox = sinon.createSandbox();
COLORWAY_SCREEN_PROPS = {
id: "test-colorway-screen",
totalNumberofScreens: 1,
content: {
subtitle: "test subtitle",
tiles: {
type: "colorway",
action: {
theme: "<event>",
},
defaultVariationIndex: 0,
systemVariations: ["automatic", "light"],
variations: ["soft", "bold"],
colorways: [
{
id: "default",
label: "Default",
},
{
id: "abstract",
label: "Abstract",
},
],
},
primary_button: {
action: {},
label: "test button",
},
},
messageId: "test-mr-colorway-screen",
activeTheme: "automatic",
};
});
afterEach(() => {
sandbox.restore();
});
describe("MRColorway component", () => {
it("should render WelcomeScreen", () => {
const wrapper = shallow(<WelcomeScreen {...COLORWAY_SCREEN_PROPS} />);
assert.ok(wrapper.exists());
});
it("should use default when activeTheme is not set", () => {
const wrapper = shallow(<Colorways {...COLORWAY_SCREEN_PROPS} />);
wrapper.setProps({ activeTheme: null });
const colorwaysOptionIcons = wrapper.find(
".tiles-theme-section .theme .icon"
);
assert.strictEqual(colorwaysOptionIcons.length, 2);
// Default automatic theme is selected by default
assert.strictEqual(
colorwaysOptionIcons.first().prop("className").includes("selected"),
true
);
assert.strictEqual(
colorwaysOptionIcons.first().prop("className").includes("default"),
true
);
});
it("should use default when activeTheme is alpenglow", () => {
const wrapper = shallow(<Colorways {...COLORWAY_SCREEN_PROPS} />);
wrapper.setProps({ activeTheme: "alpenglow" });
const colorwaysOptionIcons = wrapper.find(
".tiles-theme-section .theme .icon"
);
assert.strictEqual(colorwaysOptionIcons.length, 2);
// Default automatic theme is selected when unsupported in colorway alpenglow theme is active
assert.strictEqual(
colorwaysOptionIcons.first().prop("className").includes("selected"),
true
);
assert.strictEqual(
colorwaysOptionIcons.first().prop("className").includes("default"),
true
);
});
it("should render colorways options", () => {
const wrapper = shallow(<Colorways {...COLORWAY_SCREEN_PROPS} />);
const colorwaysOptions = wrapper.find(
".tiles-theme-section .theme input[name='theme']"
);
const colorwaysOptionIcons = wrapper.find(
".tiles-theme-section .theme .icon"
);
const colorwaysLabels = wrapper.find(
".tiles-theme-section .theme span.sr-only"
);
assert.strictEqual(colorwaysOptions.length, 2);
assert.strictEqual(colorwaysOptionIcons.length, 2);
assert.strictEqual(colorwaysLabels.length, 2);
// First colorway option
// Default theme radio option is selected by default
assert.strictEqual(
colorwaysOptionIcons.first().prop("className").includes("selected"),
true
);
//Colorway should be using id property
assert.strictEqual(
colorwaysOptions.first().prop("data-colorway"),
"default"
);
// Second colorway option
assert.strictEqual(
colorwaysOptionIcons.last().prop("className").includes("selected"),
false
);
//Colorway should be using id property
assert.strictEqual(
colorwaysOptions.last().prop("data-colorway"),
"abstract"
);
//Colorway should be labelled for screen readers (parent label is for tooltip only, and does not describe the Colorway)
assert.strictEqual(
colorwaysOptions.last().prop("aria-labelledby"),
"abstract-label"
);
});
it("should handle colorway clicks", () => {
sandbox.stub(React, "useEffect").callsFake((fn, vals) => {
if (vals === undefined) {
fn();
} else if (vals[0] === "in") {
fn();
}
});
const handleAction = sandbox.stub();
const wrapper = shallow(
<Colorways handleAction={handleAction} {...COLORWAY_SCREEN_PROPS} />
);
const colorwaysOptions = wrapper.find(
".tiles-theme-section .theme input[name='theme']"
);
let props = wrapper.find(ColorwayDescription).props();
assert.propertyVal(props.colorway, "label", "Default");
const option = colorwaysOptions.last();
assert.propertyVal(option.props(), "value", "abstract-soft");
colorwaysOptions.last().simulate("click");
assert.calledOnce(handleAction);
});
it("should render colorway description", () => {
const wrapper = shallow(<Colorways {...COLORWAY_SCREEN_PROPS} />);
let descriptionsWrapper = wrapper.find(ColorwayDescription);
assert.ok(descriptionsWrapper.exists());
let props = descriptionsWrapper.props();
// Colorway description should display Default theme desc by default
assert.strictEqual(props.colorway.label, "Default");
});
it("ColorwayDescription should display active colorway desc", () => {
let TEST_COLORWAY_PROPS = {
colorway: {
label: "Activist",
description: "Test Activist",
},
};
const descWrapper = shallow(
<ColorwayDescription {...TEST_COLORWAY_PROPS} />
);
assert.ok(descWrapper.exists());
const descText = descWrapper.find(".colorway-text");
assert.equal(
descText.props()["data-l10n-args"].includes("Activist"),
true
);
});
it("should computeColorWayId for default active theme", () => {
let TEST_COLORWAY_PROPS = {
...COLORWAY_SCREEN_PROPS,
};
const colorwayId = computeColorWay(
TEST_COLORWAY_PROPS.activeTheme,
TEST_COLORWAY_PROPS.content.tiles.systemVariations
);
assert.strictEqual(colorwayId, "default");
});
it("should computeColorWayId for non-default active theme", () => {
let TEST_COLORWAY_PROPS = {
...COLORWAY_SCREEN_PROPS,
activeTheme: "abstract-soft",
};
const colorwayId = computeColorWay(
TEST_COLORWAY_PROPS.activeTheme,
TEST_COLORWAY_PROPS.content.tiles.systemVariations
);
assert.strictEqual(colorwayId, "abstract");
});
it("should computeVariationIndex for default active theme", () => {
let TEST_COLORWAY_PROPS = {
...COLORWAY_SCREEN_PROPS,
};
const variationIndex = computeVariationIndex(
TEST_COLORWAY_PROPS.activeTheme,
TEST_COLORWAY_PROPS.content.tiles.systemVariations,
TEST_COLORWAY_PROPS.content.tiles.variations,
TEST_COLORWAY_PROPS.content.tiles.defaultVariationIndex
);
assert.strictEqual(
variationIndex,
TEST_COLORWAY_PROPS.content.tiles.defaultVariationIndex
);
});
it("should computeVariationIndex for active theme", () => {
let TEST_COLORWAY_PROPS = {
...COLORWAY_SCREEN_PROPS,
};
const variationIndex = computeVariationIndex(
"light",
TEST_COLORWAY_PROPS.content.tiles.systemVariations,
TEST_COLORWAY_PROPS.content.tiles.variations,
TEST_COLORWAY_PROPS.content.tiles.defaultVariationIndex
);
assert.strictEqual(variationIndex, 1);
});
it("should computeVariationIndex for colorway theme", () => {
let TEST_COLORWAY_PROPS = {
...COLORWAY_SCREEN_PROPS,
};
const variationIndex = computeVariationIndex(
"abstract-bold",
TEST_COLORWAY_PROPS.content.tiles.systemVariations,
TEST_COLORWAY_PROPS.content.tiles.variations,
TEST_COLORWAY_PROPS.content.tiles.defaultVariationIndex
);
assert.strictEqual(variationIndex, 1);
});
describe("random colorways", () => {
let test;
beforeEach(() => {
COLORWAY_SCREEN_PROPS.handleAction = sandbox.stub();
sandbox.stub(window, "matchMedia");
// eslint-disable-next-line max-nested-callbacks
sandbox.stub(React, "useEffect").callsFake((fn, vals) => {
if (vals?.length === 0) {
fn();
}
});
test = () => {
shallow(<Colorways {...COLORWAY_SCREEN_PROPS} />);
return COLORWAY_SCREEN_PROPS.handleAction.firstCall.firstArg
.currentTarget;
};
});
it("should select a random colorway", () => {
const { value } = test();
assert.strictEqual(value, "abstract-soft");
assert.calledThrice(React.useEffect);
assert.notCalled(window.matchMedia);
});
it("should select a random soft colorway when not dark", () => {
window.matchMedia.returns({ matches: false });
COLORWAY_SCREEN_PROPS.content.tiles.darkVariation = 1;
const { value } = test();
assert.strictEqual(value, "abstract-soft");
assert.calledThrice(React.useEffect);
assert.calledOnce(window.matchMedia);
});
it("should select a random bold colorway when dark", () => {
window.matchMedia.returns({ matches: true });
COLORWAY_SCREEN_PROPS.content.tiles.darkVariation = 1;
const { value } = test();
assert.strictEqual(value, "abstract-bold");
assert.calledThrice(React.useEffect);
assert.calledOnce(window.matchMedia);
});
});
});
});

View file

@ -1,32 +0,0 @@
[DEFAULT]
head = head.js
firefox-appdir = browser
skip-if = toolkit == 'android' # bug 1730213
prefs =
browser.startup.homepage.abouthome_cache.enabled=true
browser.startup.homepage.abouthome_cache.testing=true
browser.attribution.macos.enabled=true
[test_AboutHomeStartupCacheChild.js]
[test_AboutHomeStartupCacheWorker.js]
support-files =
topstories.json
skip-if =
socketprocess_networking # Bug 1759035
[test_AboutNewTab.js]
[test_AboutWelcomeAttribution.js]
[test_ASRouterTargeting_attribution.js]
skip-if =
toolkit != "cocoa" # osx specific tests
[test_ASRouter_getTargetingParameters.js]
[test_ASRouterTargeting_snapshot.js]
[test_AboutWelcomeTelemetry.js]
[test_CFRMessageProvider.js]
[test_InflightAssetsMessageProvider.js]
[test_NimbusRolloutMessageProvider.js]
[test_OnboardingMessageProvider.js]
[test_PanelTestProvider.js]
[test_reach_experiments.js]
[test_remoteExperiments.js]
[test_AboutWelcomeTelemetry_glean.js]

View file

@ -0,0 +1,44 @@
[DEFAULT]
head = "head.js"
firefox-appdir = "browser"
skip-if = ["toolkit == 'android'"] # bug 1730213
prefs = [
"browser.startup.homepage.abouthome_cache.enabled=true",
"browser.startup.homepage.abouthome_cache.testing=true",
"browser.attribution.macos.enabled=true",
]
["test_ASRouterTargeting_attribution.js"]
run-if = ["os == 'mac'"] # osx specific tests
["test_ASRouterTargeting_snapshot.js"]
["test_ASRouter_getTargetingParameters.js"]
["test_AboutHomeStartupCacheChild.js"]
["test_AboutHomeStartupCacheWorker.js"]
support-files = ["topstories.json"]
skip-if = ["socketprocess_networking"] # Bug 1759035
["test_AboutNewTab.js"]
["test_AboutWelcomeAttribution.js"]
["test_AboutWelcomeTelemetry.js"]
["test_AboutWelcomeTelemetry_glean.js"]
["test_CFRMessageProvider.js"]
["test_InflightAssetsMessageProvider.js"]
["test_NimbusRolloutMessageProvider.js"]
["test_OnboardingMessageProvider.js"]
["test_PanelTestProvider.js"]
["test_reach_experiments.js"]
["test_remoteExperiments.js"]

View file

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPCSHELL_TESTS_MANIFESTS += [
"tests/unit/xpcshell.ini",
"tests/unit/xpcshell.toml",
]
BROWSER_CHROME_MANIFESTS += [
"tests/browser/browser.toml",

View file

@ -1,14 +0,0 @@
[DEFAULT]
firefox-appdir = browser
skip-if = toolkit == 'android' # bug 1730213
support-files =
head.js
head = head.js
[test_pagedata_basic.js]
[test_pagedata_schema.js]
[test_opengraph.js]
[test_queue.js]
[test_schemaorg.js]
[test_schemaorg_parse.js]
[test_twitter.js]

View file

@ -0,0 +1,19 @@
[DEFAULT]
firefox-appdir = "browser"
skip-if = ["toolkit == 'android'"] # bug 1730213
support-files = ["head.js"]
head = "head.js"
["test_opengraph.js"]
["test_pagedata_basic.js"]
["test_pagedata_schema.js"]
["test_queue.js"]
["test_schemaorg.js"]
["test_schemaorg_parse.js"]
["test_twitter.js"]

View file

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPCSHELL_TESTS_MANIFESTS += [
"tests/unit/xpcshell.ini",
"tests/unit/xpcshell.toml",
]
MOCHITEST_CHROME_MANIFESTS += ["tests/chrome/chrome.toml"]
BROWSER_CHROME_MANIFESTS += [

View file

@ -33,18 +33,18 @@ add_task(async function test_change_location_from_Toolbar() {
let children = [
{
title: "first",
url: "http://www.mochi.test/first",
url: "http://www.example.com/first",
},
{
title: "second",
url: "http://www.mochi.test/second",
url: "http://www.example.com/second",
},
{
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
},
{
title: "third",
url: "http://www.mochi.test/third",
url: "http://www.example.com/third",
},
];
let guid = PlacesUtils.history.makeGuid();
@ -65,7 +65,7 @@ add_task(async function test_change_location_from_Toolbar() {
let loadedPromises = children
.filter(item => "url" in item)
.map(item =>
BrowserTestUtils.waitForNewTab(gBrowser, item.url, false, true)
BrowserTestUtils.waitForNewTab(gBrowser, item.url, true, true)
);
let srcX = 10,

View file

@ -1,24 +0,0 @@
[DEFAULT]
head = head_bookmarks.js
firefox-appdir = browser
skip-if = toolkit == 'android' # bug 1730213
support-files =
bookmarks.glue.html
bookmarks.glue.json
corruptDB.sqlite
distribution.ini
[test_browserGlue_bookmarkshtml.js]
[test_browserGlue_corrupt.js]
[test_browserGlue_corrupt_nobackup.js]
[test_browserGlue_corrupt_nobackup_default.js]
[test_browserGlue_distribution.js]
[test_browserGlue_migrate.js]
[test_browserGlue_prefs.js]
[test_browserGlue_restore.js]
[test_clearHistory_shutdown.js]
[test_interactions_blocklist.js]
[test_invalid_defaultLocation.js]
[test_PUIU_batchUpdatesForNode.js]
[test_PUIU_setCharsetForPage.js]
[test_PUIU_title_difference_spotter.js]

View file

@ -0,0 +1,38 @@
[DEFAULT]
head = "head_bookmarks.js"
firefox-appdir = "browser"
skip-if = ["toolkit == 'android'"] # bug 1730213
support-files = [
"bookmarks.glue.html",
"bookmarks.glue.json",
"corruptDB.sqlite",
"distribution.ini",
]
["test_PUIU_batchUpdatesForNode.js"]
["test_PUIU_setCharsetForPage.js"]
["test_PUIU_title_difference_spotter.js"]
["test_browserGlue_bookmarkshtml.js"]
["test_browserGlue_corrupt.js"]
["test_browserGlue_corrupt_nobackup.js"]
["test_browserGlue_corrupt_nobackup_default.js"]
["test_browserGlue_distribution.js"]
["test_browserGlue_migrate.js"]
["test_browserGlue_prefs.js"]
["test_browserGlue_restore.js"]
["test_clearHistory_shutdown.js"]
["test_interactions_blocklist.js"]
["test_invalid_defaultLocation.js"]

View file

@ -19,7 +19,7 @@ BROWSER_CHROME_MANIFESTS += [
MARIONETTE_UNIT_MANIFESTS += ["test/marionette/manifest.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
JAR_MANIFESTS += ["jar.mn"]

View file

@ -136,6 +136,9 @@ support-files = ["searchTelemetryAd_shopping.html"]
["browser_search_telemetry_sources.js"]
support-files = ["searchTelemetry.html", "searchTelemetryAd.html"]
["browser_search_telemetry_sources_about.js"]
support-files = ["searchTelemetry.html", "searchTelemetryAd.html"]
["browser_search_telemetry_sources_ads.js"]
support-files = ["searchTelemetry.html", "searchTelemetryAd.html"]
@ -161,3 +164,6 @@ support-files = ["searchTelemetryAd_searchbox_with_content.html"]
["browser_search_telemetry_sources_navigation.js"]
support-files = ["searchTelemetry.html", "searchTelemetryAd.html"]
["browser_search_telemetry_sources_webextension.js"]
support-files = ["searchTelemetry.html", "searchTelemetryAd.html"]

View file

@ -46,8 +46,9 @@ async function verifyEventsRecorded() {
gBrowser,
getSERPUrl("searchTelemetryAd.html")
);
await waitForPageWithAdImpressions();
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -58,27 +59,43 @@ async function verifyEventsRecorded() {
is_private: "false",
shopping_tab_displayed: "false",
},
},
]);
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
BrowserTestUtils.removeTab(tab);
assertAbandonmentEvent({
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.TAB_CLOSE,
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.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.TAB_CLOSE,
},
},
});
]);
}
add_setup(async function () {

View file

@ -136,11 +136,22 @@ add_task(async function test_navigation_via_back_button() {
info("Previous page (example.com) is now loaded after back navigation.");
});
assertAbandonmentEvent({
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
assertSERPTelemetry([
{
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
source: "unknown",
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
});
]);
});
add_task(async function test_click_ad() {

View file

@ -82,13 +82,6 @@ const TEST_PROVIDER_INFO = [
},
];
async function promiseAdImpressionReceived() {
return TestUtils.waitForCondition(() => {
let adImpressions = Glean.serp.adImpression.testGetValue() ?? [];
return adImpressions.length;
}, "Should have received an ad impression.");
}
async function promiseResize(width, height) {
return TestUtils.waitForCondition(() => {
return window.outerWidth === width && window.outerHeight === height;
@ -131,14 +124,27 @@ add_task(async function test_ad_impressions_with_one_carousel() {
let url = getSERPUrl("searchTelemetryAd_components_carousel.html");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "3",
ads_hidden: "0",
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.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "3",
ads_hidden: "0",
},
],
},
]);
@ -162,14 +168,27 @@ add_task(async function test_ad_impressions_with_two_carousels() {
content.scrollTo(0, el.top + el.height + 100);
});
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "8",
ads_visible: "6",
ads_hidden: "0",
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.AD_CAROUSEL,
ads_loaded: "8",
ads_visible: "6",
ads_hidden: "0",
},
],
},
]);
@ -184,14 +203,27 @@ add_task(
);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "3",
ads_hidden: "0",
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.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "3",
ads_hidden: "0",
},
],
},
]);
@ -203,11 +235,7 @@ add_task(async function test_ad_impressions_with_carousels_tabhistory() {
resetTelemetry();
let url = getSERPUrl("searchTelemetryAd_components_carousel.html");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
// Reset telemetry because we care about the telemetry upon going back.
resetTelemetry();
await waitForPageWithAdImpressions();
let browserLoadedPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
BrowserTestUtils.startLoadingURIString(
@ -216,6 +244,9 @@ add_task(async function test_ad_impressions_with_carousels_tabhistory() {
);
await browserLoadedPromise;
// Reset telemetry because we care about the telemetry upon going back.
resetTelemetry();
let pageShowPromise = BrowserTestUtils.waitForContentEvent(
tab.linkedBrowser,
"pageshow"
@ -223,14 +254,27 @@ add_task(async function test_ad_impressions_with_carousels_tabhistory() {
tab.linkedBrowser.goBack();
await pageShowPromise;
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "3",
ads_hidden: "0",
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
source: "tabhistory",
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "3",
ads_hidden: "0",
},
],
},
]);
@ -242,14 +286,27 @@ add_task(async function test_ad_impressions_with_hidden_carousels() {
let url = getSERPUrl("searchTelemetryAd_components_carousel_hidden.html");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "0",
ads_hidden: "4",
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.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "0",
ads_hidden: "4",
},
],
},
]);
@ -263,14 +320,27 @@ add_task(async function test_ad_impressions_with_carousel_scrolled_left() {
);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "2",
ads_hidden: "0",
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.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -284,14 +354,27 @@ add_task(async function test_ad_impressions_with_carousel_below_the_fold() {
);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "0",
ads_hidden: "0",
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.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "0",
ads_hidden: "0",
},
],
},
]);
@ -303,28 +386,42 @@ add_task(async function test_ad_impressions_with_text_links() {
let url = getSERPUrl("searchTelemetryAd_components_text.html");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SIDEBAR,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
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.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SIDEBAR,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
BrowserTestUtils.removeTab(tab);
});
@ -348,16 +445,30 @@ add_task(async function test_ad_visibility() {
content.scrollTo(0, el.top + el.height + 100);
});
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "6",
ads_visible: "4",
ads_hidden: "0",
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.AD_LINK,
ads_loaded: "6",
ads_visible: "4",
ads_hidden: "0",
},
],
},
]);
BrowserTestUtils.removeTab(tab);
});
@ -366,15 +477,29 @@ add_task(async function test_impressions_without_ads() {
let url = getSERPUrl("searchTelemetryAd_searchbox_with_content.html");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promiseAdImpressionReceived();
await waitForPageWithAdImpressions();
assertAdImpressionEvents([
assertSERPTelemetry([
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
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.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
BrowserTestUtils.removeTab(tab);
});

View file

@ -135,7 +135,7 @@ add_task(async function test_click_cached_page() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -152,6 +152,20 @@ add_task(async function test_click_cached_page() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "5",
ads_visible: "5",
ads_hidden: "0",
},
],
},
{
impression: {
@ -169,6 +183,20 @@ add_task(async function test_click_cached_page() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "5",
ads_visible: "5",
ads_hidden: "0",
},
],
},
]);

View file

@ -104,12 +104,9 @@ add_task(async function test_click_tab() {
tab.linkedBrowser
);
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -126,6 +123,20 @@ add_task(async function test_click_tab() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -137,6 +148,20 @@ add_task(async function test_click_tab() {
is_private: "false",
shopping_tab_displayed: "true",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -158,12 +183,9 @@ add_task(async function test_click_shopping() {
tab.linkedBrowser
);
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -180,6 +202,20 @@ add_task(async function test_click_shopping() {
target: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -191,6 +227,20 @@ add_task(async function test_click_shopping() {
is_private: "false",
shopping_tab_displayed: "true",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -216,12 +266,9 @@ add_task(async function test_click_related_search_in_new_tab() {
tab.linkedBrowser
);
let tab2 = await tabPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -238,6 +285,20 @@ add_task(async function test_click_related_search_in_new_tab() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -249,6 +310,20 @@ add_task(async function test_click_related_search_in_new_tab() {
is_private: "false",
shopping_tab_displayed: "true",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -277,14 +352,9 @@ add_task(async function test_click_redirect_search_in_newtab() {
tab.linkedBrowser
);
let tab2 = await tabPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -301,6 +371,20 @@ add_task(async function test_click_redirect_search_in_newtab() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -312,6 +396,20 @@ add_task(async function test_click_redirect_search_in_newtab() {
is_private: "false",
shopping_tab_displayed: "true",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -347,12 +445,9 @@ add_task(async function test_content_source_reset() {
tab.linkedBrowser
);
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression.testGetValue()?.length == 3;
}, "Should have three impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -373,6 +468,20 @@ add_task(async function test_content_source_reset() {
target: SearchSERPTelemetryUtils.COMPONENTS.INCONTENT_SEARCHBOX,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -390,6 +499,20 @@ add_task(async function test_content_source_reset() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -401,6 +524,20 @@ add_task(async function test_content_source_reset() {
is_private: "false",
shopping_tab_displayed: "true",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -434,12 +571,9 @@ add_task(async function test_click_refinement_button() {
tab.linkedBrowser
);
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -456,6 +590,20 @@ add_task(async function test_click_refinement_button() {
target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -467,6 +615,20 @@ add_task(async function test_click_refinement_button() {
is_private: "false",
shopping_tab_displayed: "true",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);

View file

@ -64,7 +64,7 @@ add_task(async function test_click_non_ads_link() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -81,6 +81,14 @@ add_task(async function test_click_non_ads_link() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "13",
ads_visible: "13",
ads_hidden: "0",
},
],
},
]);
@ -113,7 +121,7 @@ add_task(async function test_click_non_ad_with_no_ads() {
);
await browserLoadedPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",

View file

@ -81,7 +81,7 @@ add_task(async function test_click_links() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -98,6 +98,20 @@ add_task(async function test_click_links() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -115,7 +129,7 @@ add_task(async function test_click_links() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -132,6 +146,20 @@ add_task(async function test_click_links() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -149,6 +177,20 @@ add_task(async function test_click_links() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -182,7 +224,7 @@ add_task(async function test_click_link_with_more_parameters() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -199,6 +241,20 @@ add_task(async function test_click_link_with_more_parameters() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -231,7 +287,7 @@ add_task(async function test_click_link_with_fewer_parameters() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -248,6 +304,20 @@ add_task(async function test_click_link_with_fewer_parameters() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -280,7 +350,7 @@ add_task(async function test_click_link_with_reordered_parameters() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -297,6 +367,20 @@ add_task(async function test_click_link_with_reordered_parameters() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);

View file

@ -72,7 +72,7 @@ add_task(async function test_click_non_ads_link_redirected() {
await browserLoadedPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -89,6 +89,14 @@ add_task(async function test_click_non_ads_link_redirected() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "14",
ads_visible: "14",
ads_hidden: "0",
},
],
},
]);
@ -124,7 +132,7 @@ add_task(async function test_click_non_ads_link_redirected_new_tab() {
});
let tab2 = await tabPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -141,6 +149,14 @@ add_task(async function test_click_non_ads_link_redirected_new_tab() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "14",
ads_visible: "14",
ads_hidden: "0",
},
],
},
]);
@ -172,7 +188,7 @@ add_task(async function test_click_non_ads_link_redirect_non_top_level() {
await browserPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -189,6 +205,14 @@ add_task(async function test_click_non_ads_link_redirect_non_top_level() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "14",
ads_visible: "14",
ads_hidden: "0",
},
],
},
]);
@ -217,7 +241,7 @@ add_task(async function test_multiple_redirects_non_ad_link() {
await browserLoadedPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -234,6 +258,14 @@ add_task(async function test_multiple_redirects_non_ad_link() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "14",
ads_visible: "14",
ads_hidden: "0",
},
],
},
]);
@ -262,7 +294,7 @@ add_task(async function test_click_ad_link_redirected() {
await browserLoadedPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -279,6 +311,14 @@ add_task(async function test_click_ad_link_redirected() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "14",
ads_visible: "14",
ads_hidden: "0",
},
],
},
]);
@ -302,7 +342,7 @@ add_task(async function test_click_ad_link_redirected_new_tab() {
);
let tab2 = await tabPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -319,6 +359,14 @@ add_task(async function test_click_ad_link_redirected_new_tab() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "14",
ads_visible: "14",
ads_hidden: "0",
},
],
},
]);

View file

@ -143,7 +143,7 @@ add_task(async function test_click_second_ad_in_component() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -160,6 +160,20 @@ add_task(async function test_click_second_ad_in_component() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "5",
ads_visible: "5",
ads_hidden: "0",
},
],
},
]);
@ -185,7 +199,7 @@ add_task(async function test_click_ads_link_modified() {
});
await browserLoadedPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -202,6 +216,20 @@ add_task(async function test_click_ads_link_modified() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "5",
ads_visible: "5",
ads_hidden: "0",
},
],
},
]);
@ -224,12 +252,9 @@ add_task(async function test_click_and_submit_incontent_searchbox() {
);
EventUtils.synthesizeKey("KEY_Enter");
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -285,12 +310,9 @@ add_task(async function test_click_autosuggest() {
tab.linkedBrowser
);
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -336,7 +358,7 @@ add_task(async function test_click_carousel_expand() {
content.document.querySelector("button").click();
});
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -353,6 +375,14 @@ add_task(async function test_click_carousel_expand() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_CAROUSEL,
ads_loaded: "4",
ads_visible: "3",
ads_hidden: "0",
},
],
},
]);
@ -388,7 +418,7 @@ add_task(async function test_click_link_with_special_characters_in_path() {
);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -405,6 +435,20 @@ add_task(async function test_click_link_with_special_characters_in_path() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_SITELINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "5",
ads_visible: "5",
ads_hidden: "0",
},
],
},
]);

View file

@ -52,33 +52,30 @@ add_task(async function load_2_pbm_serps_and_1_non_pbm_serp() {
});
info("Load SERP in a new tab.");
let impression = TestUtils.topicObserved("reported-page-with-impression");
let url = getSERPUrl("searchTelemetry.html");
let tab = await BrowserTestUtils.openNewForegroundTab(
privateWindow.gBrowser,
url
);
info("Wait for page impression.");
await impression;
await waitForPageWithAdImpressions();
info("Load another SERP in the same tab.");
impression = TestUtils.topicObserved("reported-page-with-impression");
url = getSERPUrl("searchTelemetryAd.html");
BrowserTestUtils.startLoadingURIString(privateWindow.gBrowser, url);
info("Wait for page impression.");
await impression;
await waitForPageWithAdImpressions();
info("Close private window.");
BrowserTestUtils.removeTab(tab);
await BrowserTestUtils.closeWindow(privateWindow);
info("Load SERP in non-private window.");
impression = TestUtils.topicObserved("reported-page-with-impression");
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
info("Wait for page impression.");
await impression;
await waitForPageWithAdImpressions();
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -89,6 +86,9 @@ add_task(async function load_2_pbm_serps_and_1_non_pbm_serp() {
is_private: "true",
shopping_tab_displayed: "false",
},
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
{
impression: {
@ -100,6 +100,17 @@ add_task(async function load_2_pbm_serps_and_1_non_pbm_serp() {
is_private: "true",
shopping_tab_displayed: "false",
},
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
{
impression: {
@ -111,6 +122,14 @@ add_task(async function load_2_pbm_serps_and_1_non_pbm_serp() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);

View file

@ -117,24 +117,20 @@ add_task(async function update_telemetry_tab_already_open() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
info("Wait a brief amount of time for a possible SERP impression.");
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 10));
await waitForIdle();
info("Assert no impressions are found.");
assertImpressionEvents([]);
assertSERPTelemetry([]);
info("Update search-telemetry-v2 with a matching queryParamName.");
await updateClientWithRecords(RECORDS);
info("Reload page.");
let promise = TestUtils.topicObserved("reported-page-with-impression");
let adPromise = TestUtils.topicObserved("reported-page-with-ad-impressions");
gBrowser.reload();
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
await waitForPageWithAdImpressions();
await promise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -145,16 +141,14 @@ add_task(async function update_telemetry_tab_already_open() {
is_private: "false",
shopping_tab_displayed: "false",
},
},
]);
await adPromise;
assertAdImpressionEvents([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -175,11 +169,10 @@ add_task(async function update_telemetry_tab_closed() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
info("Wait a brief amount of time for a possible SERP impression.");
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 10));
await waitForIdle();
info("Assert no impressions are found.");
assertImpressionEvents([]);
assertSERPTelemetry([]);
info("Remove tab.");
await BrowserTestUtils.removeTab(tab);
@ -188,12 +181,9 @@ add_task(async function update_telemetry_tab_closed() {
await updateClientWithRecords(RECORDS);
info("Load SERP in a new tab.");
let promise = TestUtils.topicObserved("reported-page-with-impression");
let adPromise = TestUtils.topicObserved("reported-page-with-ad-impressions");
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await promise;
assertImpressionEvents([
await waitForPageWithAdImpressions();
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -204,16 +194,14 @@ add_task(async function update_telemetry_tab_closed() {
is_private: "false",
shopping_tab_displayed: "false",
},
},
]);
await adPromise;
assertAdImpressionEvents([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -236,25 +224,20 @@ add_task(async function update_telemetry_multiple_tabs() {
}
info("Wait a brief amount of time for a possible SERP impression.");
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 10));
await waitForIdle();
info("Assert no impressions are found.");
assertImpressionEvents([]);
assertSERPTelemetry([]);
info("Update search-telemetry-v2 with a matching queryParamName.");
await updateClientWithRecords(RECORDS);
for (let tab of tabs) {
await BrowserTestUtils.switchTab(gBrowser, tab);
let promise = TestUtils.topicObserved("reported-page-with-impression");
let adPromise = TestUtils.topicObserved(
"reported-page-with-ad-impressions"
);
gBrowser.reload();
await waitForPageWithAdImpressions();
await promise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -265,20 +248,18 @@ add_task(async function update_telemetry_multiple_tabs() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await adPromise;
assertAdImpressionEvents([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
]);
resetTelemetry();
await BrowserTestUtils.removeTab(tab);
resetTelemetry();
}
info("Update search-telemetry-v2 with non-matching queryParamName.");
@ -304,25 +285,20 @@ add_task(async function update_telemetry_multiple_processes_and_tabs() {
}
info("Wait a brief amount of time for a possible SERP impression.");
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 10));
await waitForIdle();
info("Assert no impressions are found.");
assertImpressionEvents([]);
assertSERPTelemetry([]);
info("Update search-telemetry-v2 with a matching queryParamName.");
await updateClientWithRecords(RECORDS);
for (let tab of tabs) {
await BrowserTestUtils.switchTab(gBrowser, tab);
let promise = TestUtils.topicObserved("reported-page-with-impression");
let adPromise = TestUtils.topicObserved(
"reported-page-with-ad-impressions"
);
gBrowser.reload();
await waitForPageWithAdImpressions();
await promise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -333,20 +309,19 @@ add_task(async function update_telemetry_multiple_processes_and_tabs() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await adPromise;
assertAdImpressionEvents([
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
]);
resetTelemetry();
await BrowserTestUtils.removeTab(tab);
resetTelemetry();
}
info("Update search-telemetry-v2 with non-matching queryParamName.");

View file

@ -74,8 +74,9 @@ async function loadSerpAndClickShoppingTab(page) {
gBrowser,
getSERPUrl(page)
);
await waitForPageWithAdImpressions();
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -86,15 +87,22 @@ async function loadSerpAndClickShoppingTab(page) {
is_private: "false",
shopping_tab_displayed: "true",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
await waitForPageWithAdImpressions();
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
BrowserTestUtils.synthesizeMouseAtCenter("#shopping", {}, tab.linkedBrowser);
await pageLoadPromise;
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -111,6 +119,14 @@ async function loadSerpAndClickShoppingTab(page) {
target: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.SHOPPING_TAB,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);

View file

@ -109,6 +109,7 @@ async function track_ad_click(
let expectedWithAdsScalar = `browser.search.withads.${expectedScalarSource}`;
let expectedAdClicksScalar = `browser.search.adclicks.${expectedScalarSource}`;
let adImpressionPromise = waitForPageWithAdImpressions();
let tab = await searchAdsFn();
await assertSearchSourcesTelemetry(
@ -121,24 +122,7 @@ async function track_ad_click(
}
);
assertImpressionEvents([
{
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
source: expectedScalarSource,
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
},
]);
// Ad impression data is needed to categorize ads on the page in order to
// register ad click events before a click occurs. We don't assert their
// precise values here because other tests cover that the component
// categorizations are valid.
await promiseAdImpressionReceived();
await adImpressionPromise;
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser);
@ -156,7 +140,7 @@ async function track_ad_click(
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -173,6 +157,14 @@ async function track_ad_click(
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -330,61 +322,6 @@ add_task(async function test_source_searchbar() {
);
});
async function checkAboutPage(
page,
expectedHistogramSource,
expectedScalarSource
) {
let tab;
await track_ad_click(
expectedHistogramSource,
expectedScalarSource,
async () => {
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, page);
await BrowserTestUtils.browserStopped(tab.linkedBrowser, page);
// Wait for the full load.
await SpecialPowers.pushPrefEnv({
set: [
[
"browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar",
false,
],
],
});
await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
await ContentTaskUtils.waitForCondition(
() => content.wrappedJSObject.gContentSearchController.defaultEngine
);
});
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
await typeInSearchField(
tab.linkedBrowser,
"test query",
"newtab-search-text"
);
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, tab.linkedBrowser);
await p;
return tab;
},
async () => {
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
}
);
}
add_task(async function test_source_about_home() {
await checkAboutPage("about:home", "abouthome", "about_home");
});
add_task(async function test_source_about_newtab() {
await checkAboutPage("about:newtab", "newtab", "about_newtab");
});
add_task(async function test_source_system() {
let tab;
await track_ad_click(
@ -412,71 +349,3 @@ add_task(async function test_source_system() {
}
);
});
add_task(async function test_source_webextension_search() {
/* global browser */
async function background(SEARCH_TERM) {
// Search with no tabId
browser.search.search({ query: "searchSuggestion", engine: "Example" });
}
let searchExtension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["search", "tabs"],
},
background,
useAddonManager: "temporary",
});
let tab;
await track_ad_click(
"webextension",
"webextension",
async () => {
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
await searchExtension.startup();
return (tab = await tabPromise);
},
async () => {
await searchExtension.unload();
BrowserTestUtils.removeTab(tab);
}
);
});
add_task(async function test_source_webextension_query() {
async function background(SEARCH_TERM) {
// Search with no tabId
browser.search.query({
text: "searchSuggestion",
disposition: "NEW_TAB",
});
}
let searchExtension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["search", "tabs"],
},
background,
useAddonManager: "temporary",
});
let tab;
await track_ad_click(
"webextension",
"webextension",
async () => {
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
await searchExtension.startup();
return (tab = await tabPromise);
},
async () => {
await searchExtension.unload();
BrowserTestUtils.removeTab(tab);
}
);
});

View file

@ -0,0 +1,227 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/*
* Main tests for SearchSERPTelemetry - general engine visiting and link
* clicking on about pages.
*
*/
"use strict";
const TEST_PROVIDER_INFO = [
{
telemetryId: "example",
searchPageRegexp:
/^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetry(?:Ad)?/,
queryParamNames: ["s"],
codeParamName: "abc",
taggedCodes: ["ff"],
followOnParamNames: ["a"],
extraAdServersRegexps: [/^https:\/\/example\.com\/ad2?/],
components: [
{
type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
default: true,
},
],
},
];
/**
* Returns the index of the first search suggestion in the urlbar results.
*
* @returns {number} An index, or -1 if there are no search suggestions.
*/
async function getFirstSuggestionIndex() {
const matchCount = UrlbarTestUtils.getResultCount(window);
for (let i = 0; i < matchCount; i++) {
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
if (
result.type == UrlbarUtils.RESULT_TYPE.SEARCH &&
result.searchParams.suggestion
) {
return i;
}
}
return -1;
}
SearchTestUtils.init(this);
add_setup(async function () {
SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
await waitForIdle();
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.suggest.searches", true],
[
"browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar",
true,
],
// Ensure to add search suggestion telemetry as search_suggestion not search_formhistory.
["browser.urlbar.maxHistoricalSearchSuggestions", 0],
["browser.search.serpEventTelemetry.enabled", true],
],
});
// Enable local telemetry recording for the duration of the tests.
let oldCanRecord = Services.telemetry.canRecordExtended;
Services.telemetry.canRecordExtended = true;
Services.prefs.setBoolPref("browser.search.log", true);
await SearchTestUtils.installSearchExtension(
{
search_url: getPageUrl(true),
search_url_get_params: "s={searchTerms}&abc=ff",
suggest_url:
"https://example.org/browser/browser/components/search/test/browser/searchSuggestionEngine.sjs",
suggest_url_get_params: "query={searchTerms}",
},
{ setAsDefault: true }
);
await gCUITestUtils.addSearchBar();
registerCleanupFunction(async () => {
gCUITestUtils.removeSearchBar();
Services.prefs.clearUserPref("browser.search.log");
SearchSERPTelemetry.overrideSearchTelemetryForTests();
Services.telemetry.canRecordExtended = oldCanRecord;
resetTelemetry();
});
});
async function track_ad_click(
expectedHistogramSource,
expectedScalarSource,
searchAdsFn,
cleanupFn
) {
searchCounts.clear();
Services.telemetry.clearScalars();
let expectedContentScalarKey = "example:tagged:ff";
let expectedScalarKey = "example:tagged";
let expectedHistogramSAPSourceKey = `other-Example.${expectedHistogramSource}`;
let expectedContentScalar = `browser.search.content.${expectedScalarSource}`;
let expectedWithAdsScalar = `browser.search.withads.${expectedScalarSource}`;
let expectedAdClicksScalar = `browser.search.adclicks.${expectedScalarSource}`;
let adImpressionPromise = waitForPageWithAdImpressions();
let tab = await searchAdsFn();
await assertSearchSourcesTelemetry(
{
[expectedHistogramSAPSourceKey]: 1,
},
{
[expectedContentScalar]: { [expectedContentScalarKey]: 1 },
[expectedWithAdsScalar]: { [expectedScalarKey]: 1 },
}
);
await adImpressionPromise;
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser);
await pageLoadPromise;
await promiseWaitForAdLinkCheck();
await assertSearchSourcesTelemetry(
{
[expectedHistogramSAPSourceKey]: 1,
},
{
[expectedContentScalar]: { [expectedContentScalarKey]: 1 },
[expectedWithAdsScalar]: { [expectedScalarKey]: 1 },
[expectedAdClicksScalar]: { [expectedScalarKey]: 1 },
}
);
assertSERPTelemetry([
{
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
source: expectedScalarSource,
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
engagements: [
{
action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await cleanupFn();
Services.fog.testResetFOG();
}
async function checkAboutPage(
page,
expectedHistogramSource,
expectedScalarSource
) {
let tab;
await track_ad_click(
expectedHistogramSource,
expectedScalarSource,
async () => {
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, page);
await BrowserTestUtils.browserStopped(tab.linkedBrowser, page);
// Wait for the full load.
await SpecialPowers.pushPrefEnv({
set: [
[
"browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar",
false,
],
],
});
await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
await ContentTaskUtils.waitForCondition(
() => content.wrappedJSObject.gContentSearchController.defaultEngine
);
});
let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
await typeInSearchField(
tab.linkedBrowser,
"test query",
"newtab-search-text"
);
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, tab.linkedBrowser);
await p;
return tab;
},
async () => {
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
}
);
}
add_task(async function test_source_about_home() {
await checkAboutPage("about:home", "abouthome", "about_home");
});
add_task(async function test_source_about_newtab() {
await checkAboutPage("about:newtab", "newtab", "about_newtab");
});

View file

@ -70,7 +70,7 @@ add_task(async function test_simple_search_page_visit() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -81,6 +81,9 @@ add_task(async function test_simple_search_page_visit() {
is_private: "false",
shopping_tab_displayed: "false",
},
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
]);
});
@ -110,7 +113,7 @@ add_task(async function test_simple_search_page_visit_telemetry() {
Assert.notEqual(scalars[key].example, 0, "bandwidth logged");
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -121,6 +124,9 @@ add_task(async function test_simple_search_page_visit_telemetry() {
is_private: "false",
shopping_tab_displayed: "false",
},
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
]);
});
@ -143,7 +149,7 @@ add_task(async function test_follow_on_visit() {
);
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -154,6 +160,9 @@ add_task(async function test_follow_on_visit() {
is_private: "false",
shopping_tab_displayed: "false",
},
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
{
impression: {
@ -165,6 +174,9 @@ add_task(async function test_follow_on_visit() {
is_private: "false",
shopping_tab_displayed: "false",
},
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
]);
});
@ -176,6 +188,7 @@ add_task(async function test_track_ad() {
gBrowser,
getSERPUrl("searchTelemetryAd.html")
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -185,7 +198,7 @@ add_task(async function test_track_ad() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -196,6 +209,14 @@ add_task(async function test_track_ad() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -209,6 +230,7 @@ add_task(async function test_track_ad_organic() {
gBrowser,
getSERPUrl("searchTelemetryAd.html", true)
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -218,7 +240,7 @@ add_task(async function test_track_ad_organic() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -229,6 +251,14 @@ add_task(async function test_track_ad_organic() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -247,6 +277,7 @@ add_task(async function test_track_ad_new_window() {
false,
url
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -256,7 +287,7 @@ add_task(async function test_track_ad_new_window() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -267,6 +298,14 @@ add_task(async function test_track_ad_new_window() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -285,12 +324,15 @@ add_task(async function test_track_ad_pages_without_ads() {
getSERPUrl("searchTelemetry.html")
)
);
await waitForPageWithAdImpressions();
tabs.push(
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
getSERPUrl("searchTelemetryAd.html")
)
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -300,7 +342,7 @@ add_task(async function test_track_ad_pages_without_ads() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -322,6 +364,14 @@ add_task(async function test_track_ad_pages_without_ads() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);

View file

@ -63,6 +63,7 @@ async function track_ad_click(testOrganic) {
gBrowser,
getSERPUrl("searchTelemetryAd.html", testOrganic)
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -74,7 +75,7 @@ async function track_ad_click(testOrganic) {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -85,9 +86,16 @@ async function track_ad_click(testOrganic) {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived(1);
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser);
@ -103,7 +111,7 @@ async function track_ad_click(testOrganic) {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -120,6 +128,14 @@ async function track_ad_click(testOrganic) {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -127,7 +143,7 @@ async function track_ad_click(testOrganic) {
pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
gBrowser.goBack();
await pageLoadPromise;
await promiseWaitForAdLinkCheck();
await waitForPageWithAdImpressions();
// We've gone back, so we register an extra display & if it is with ads or not.
await assertSearchSourcesTelemetry(
@ -141,7 +157,7 @@ async function track_ad_click(testOrganic) {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -158,6 +174,14 @@ async function track_ad_click(testOrganic) {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
{
impression: {
@ -169,9 +193,16 @@ async function track_ad_click(testOrganic) {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived(2);
pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser);
@ -190,7 +221,7 @@ async function track_ad_click(testOrganic) {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -207,6 +238,14 @@ async function track_ad_click(testOrganic) {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
{
impression: {
@ -224,6 +263,14 @@ async function track_ad_click(testOrganic) {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -241,7 +288,9 @@ add_task(async function test_track_ad_click_organic() {
add_task(async function test_track_ad_click_with_location_change_other_tab() {
resetTelemetry();
const url = getSERPUrl("searchTelemetryAd.html");
let adImpressionPromise = waitForPageWithAdImpressions();
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -251,7 +300,7 @@ add_task(async function test_track_ad_click_with_location_change_other_tab() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -262,9 +311,17 @@ add_task(async function test_track_ad_click_with_location_change_other_tab() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived();
await adImpressionPromise;
const newTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
@ -286,7 +343,7 @@ add_task(async function test_track_ad_click_with_location_change_other_tab() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -303,6 +360,14 @@ add_task(async function test_track_ad_click_with_location_change_other_tab() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);

View file

@ -55,6 +55,7 @@ add_task(async function test_track_ad_on_data_attributes() {
gBrowser,
getSERPUrl("searchTelemetryAd_dataAttributes.html")
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -68,7 +69,7 @@ add_task(async function test_track_ad_on_data_attributes() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example-data-attributes",
@ -79,6 +80,14 @@ add_task(async function test_track_ad_on_data_attributes() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -92,6 +101,7 @@ add_task(async function test_track_ad_on_data_attributes_and_hrefs() {
gBrowser,
getSERPUrl("searchTelemetryAd_dataAttributes_href.html")
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -105,7 +115,7 @@ add_task(async function test_track_ad_on_data_attributes_and_hrefs() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example-data-attributes",
@ -116,6 +126,14 @@ add_task(async function test_track_ad_on_data_attributes_and_hrefs() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -129,6 +147,7 @@ add_task(async function test_track_no_ad_on_data_attributes_and_hrefs() {
gBrowser,
getSERPUrl("searchTelemetryAd_dataAttributes_none.html")
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -139,7 +158,7 @@ add_task(async function test_track_no_ad_on_data_attributes_and_hrefs() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example-data-attributes",

View file

@ -77,7 +77,7 @@ add_task(async function test_track_ad_on_DOMContentLoaded() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "slow-page-load",
@ -88,6 +88,14 @@ add_task(async function test_track_ad_on_DOMContentLoaded() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
@ -101,6 +109,7 @@ add_task(async function test_track_ad_on_load_event() {
gBrowser,
getSERPUrl("slow_loading_page_with_ads_on_load_event.html")
);
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{},
@ -110,7 +119,7 @@ add_task(async function test_track_ad_on_load_event() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "slow-page-load",
@ -121,6 +130,14 @@ add_task(async function test_track_ad_on_load_event() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);

View file

@ -78,12 +78,9 @@ add_task(async function test_source_opened_in_new_tab_via_middle_click() {
tab1.linkedBrowser
);
let tab2 = await tabPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -100,6 +97,14 @@ add_task(async function test_source_opened_in_new_tab_via_middle_click() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -111,6 +116,14 @@ add_task(async function test_source_opened_in_new_tab_via_middle_click() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -139,12 +152,9 @@ add_task(async function test_source_opened_in_new_tab_via_target_blank() {
tab1.linkedBrowser
);
let tab2 = await tabPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -161,6 +171,14 @@ add_task(async function test_source_opened_in_new_tab_via_target_blank() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -172,6 +190,14 @@ add_task(async function test_source_opened_in_new_tab_via_target_blank() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -214,12 +240,9 @@ add_task(async function test_source_opened_in_new_tab_via_context_menu() {
contextMenu.activateItem(openLinkInNewTabMenuItem);
let tab2 = await tabPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -236,6 +259,14 @@ add_task(async function test_source_opened_in_new_tab_via_context_menu() {
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -247,6 +278,14 @@ add_task(async function test_source_opened_in_new_tab_via_context_menu() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -268,12 +307,9 @@ add_task(
tab.linkedBrowser
);
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -290,6 +326,15 @@ add_task(
target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
},
],
adImpressions: [
{
component:
SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -301,6 +346,15 @@ add_task(
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component:
SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -322,12 +376,9 @@ add_task(
tab.linkedBrowser
);
await pageLoadPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -344,6 +395,15 @@ add_task(
target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
},
],
adImpressions: [
{
component:
SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -355,6 +415,15 @@ add_task(
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component:
SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);
@ -385,12 +454,9 @@ add_task(async function test_refinement_button_vs_opened_in_new_tab() {
tab1.linkedBrowser
);
let tab2 = await tabPromise;
await waitForPageWithAdImpressions();
await TestUtils.waitForCondition(() => {
return Glean.serp.impression?.testGetValue()?.length == 2;
}, "Should have two impressions.");
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -407,6 +473,14 @@ add_task(async function test_refinement_button_vs_opened_in_new_tab() {
target: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
{
impression: {
@ -418,6 +492,14 @@ add_task(async function test_refinement_button_vs_opened_in_new_tab() {
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.REFINED_SEARCH_BUTTONS,
ads_loaded: "1",
ads_visible: "1",
ads_hidden: "0",
},
],
},
]);

View file

@ -84,7 +84,7 @@ add_setup(async function () {
Services.prefs.clearUserPref("browser.search.log");
SearchSERPTelemetry.overrideSearchTelemetryForTests();
Services.telemetry.canRecordExtended = oldCanRecord;
Services.telemetry.clearScalars();
resetTelemetry();
});
});
@ -110,6 +110,7 @@ add_task(async function test_search() {
Services.fog.testResetFOG();
// Load a page via the address bar.
await loadSearchPage();
await waitForPageWithAdImpressions();
await assertSearchSourcesTelemetry(
{
@ -121,7 +122,7 @@ add_task(async function test_search() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -132,15 +133,24 @@ add_task(async function test_search() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
});
add_task(async function test_reload() {
let adImpressionPromise = waitForPageWithAdImpressions();
let promise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
tab.linkedBrowser.reload();
await promise;
await promiseWaitForAdLinkCheck();
await adImpressionPromise;
await assertSearchSourcesTelemetry(
{
@ -154,7 +164,7 @@ add_task(async function test_reload() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -165,6 +175,17 @@ add_task(async function test_reload() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
{
impression: {
@ -176,9 +197,16 @@ add_task(async function test_reload() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived();
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
await BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser);
@ -197,7 +225,7 @@ add_task(async function test_reload() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -208,6 +236,17 @@ add_task(async function test_reload() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
{
impression: {
@ -225,6 +264,14 @@ add_task(async function test_reload() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
});
@ -235,7 +282,9 @@ add_task(async function test_fresh_search() {
resetTelemetry();
// Load a page via the address bar.
let adImpressionPromise = waitForPageWithAdImpressions();
await loadSearchPage();
await adImpressionPromise;
searchUrl = tab.linkedBrowser.url;
@ -249,7 +298,7 @@ add_task(async function test_fresh_search() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -260,9 +309,16 @@ add_task(async function test_fresh_search() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived(1);
});
add_task(async function test_click_ad() {
@ -281,7 +337,7 @@ add_task(async function test_click_ad() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -298,15 +354,24 @@ add_task(async function test_click_ad() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
});
add_task(async function test_go_back() {
let adImpressionPromise = waitForPageWithAdImpressions();
let promise = BrowserTestUtils.waitForLocationChange(gBrowser, searchUrl);
tab.linkedBrowser.goBack();
await promise;
await promiseWaitForAdLinkCheck();
await adImpressionPromise;
await assertSearchSourcesTelemetry(
{
@ -321,7 +386,7 @@ add_task(async function test_go_back() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -338,6 +403,14 @@ add_task(async function test_go_back() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
{
impression: {
@ -349,9 +422,16 @@ add_task(async function test_go_back() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived(2);
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
await BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser);
@ -371,7 +451,7 @@ add_task(async function test_go_back() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -388,6 +468,14 @@ add_task(async function test_go_back() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
{
impression: {
@ -405,6 +493,14 @@ add_task(async function test_go_back() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
});
@ -421,7 +517,9 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
});
// Load a SERP once in order to show the search term in the Urlbar.
let adImpressionPromise = waitForPageWithAdImpressions();
await loadSearchPage();
await adImpressionPromise;
await assertSearchSourcesTelemetry(
{
"other-Example.urlbar": 1,
@ -432,7 +530,7 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -443,12 +541,21 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived(1);
// Do another search from the context of the default SERP.
adImpressionPromise = waitForPageWithAdImpressions();
await loadSearchPage();
await adImpressionPromise;
await assertSearchSourcesTelemetry(
{
"other-Example.urlbar": 1,
@ -462,7 +569,7 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -473,6 +580,17 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
{
impression: {
@ -484,9 +602,16 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await promiseAdImpressionReceived(2);
// Click on an ad.
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
@ -507,7 +632,7 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
}
);
assertImpressionEvents([
assertSERPTelemetry([
{
impression: {
provider: "example",
@ -518,6 +643,17 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
is_shopping_page: "false",
is_private: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
abandonment: {
reason: SearchSERPTelemetryUtils.ABANDONMENTS.NAVIGATION,
},
},
{
impression: {
@ -535,6 +671,14 @@ add_task(async function test_fresh_search_with_urlbar_persisted() {
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);

View file

@ -0,0 +1,221 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/*
* Main tests for SearchSERPTelemetry - general engine visiting and
* link clicking with Web Extensions.
*
*/
"use strict";
const TEST_PROVIDER_INFO = [
{
telemetryId: "example",
searchPageRegexp:
/^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/telemetry\/searchTelemetry(?:Ad)?/,
queryParamNames: ["s"],
codeParamName: "abc",
taggedCodes: ["ff"],
followOnParamNames: ["a"],
extraAdServersRegexps: [/^https:\/\/example\.com\/ad2?/],
components: [
{
type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
default: true,
},
],
},
];
SearchTestUtils.init(this);
add_setup(async function () {
SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO);
await waitForIdle();
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.suggest.searches", true],
[
"browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar",
true,
],
// Ensure to add search suggestion telemetry as search_suggestion not search_formhistory.
["browser.urlbar.maxHistoricalSearchSuggestions", 0],
["browser.search.serpEventTelemetry.enabled", true],
],
});
// Enable local telemetry recording for the duration of the tests.
let oldCanRecord = Services.telemetry.canRecordExtended;
Services.telemetry.canRecordExtended = true;
Services.prefs.setBoolPref("browser.search.log", true);
await SearchTestUtils.installSearchExtension(
{
search_url: getPageUrl(true),
search_url_get_params: "s={searchTerms}&abc=ff",
suggest_url:
"https://example.org/browser/browser/components/search/test/browser/searchSuggestionEngine.sjs",
suggest_url_get_params: "query={searchTerms}",
},
{ setAsDefault: true }
);
await gCUITestUtils.addSearchBar();
registerCleanupFunction(async () => {
gCUITestUtils.removeSearchBar();
Services.prefs.clearUserPref("browser.search.log");
SearchSERPTelemetry.overrideSearchTelemetryForTests();
Services.telemetry.canRecordExtended = oldCanRecord;
resetTelemetry();
});
});
async function track_ad_click(
expectedHistogramSource,
expectedScalarSource,
searchAdsFn,
cleanupFn
) {
searchCounts.clear();
Services.telemetry.clearScalars();
let expectedContentScalarKey = "example:tagged:ff";
let expectedScalarKey = "example:tagged";
let expectedHistogramSAPSourceKey = `other-Example.${expectedHistogramSource}`;
let expectedContentScalar = `browser.search.content.${expectedScalarSource}`;
let expectedWithAdsScalar = `browser.search.withads.${expectedScalarSource}`;
let expectedAdClicksScalar = `browser.search.adclicks.${expectedScalarSource}`;
let adImpressionPromise = waitForPageWithAdImpressions();
let tab = await searchAdsFn();
await assertSearchSourcesTelemetry(
{
[expectedHistogramSAPSourceKey]: 1,
},
{
[expectedContentScalar]: { [expectedContentScalarKey]: 1 },
[expectedWithAdsScalar]: { [expectedScalarKey]: 1 },
}
);
await adImpressionPromise;
let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser);
BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser);
await pageLoadPromise;
await promiseWaitForAdLinkCheck();
await assertSearchSourcesTelemetry(
{
[expectedHistogramSAPSourceKey]: 1,
},
{
[expectedContentScalar]: { [expectedContentScalarKey]: 1 },
[expectedWithAdsScalar]: { [expectedScalarKey]: 1 },
[expectedAdClicksScalar]: { [expectedScalarKey]: 1 },
}
);
assertSERPTelemetry([
{
impression: {
provider: "example",
tagged: "true",
partner_code: "ff",
source: expectedScalarSource,
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
engagements: [
{
action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await cleanupFn();
Services.fog.testResetFOG();
}
add_task(async function test_source_webextension_search() {
/* global browser */
async function background(SEARCH_TERM) {
// Search with no tabId
browser.search.search({ query: "searchSuggestion", engine: "Example" });
}
let searchExtension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["search", "tabs"],
},
background,
useAddonManager: "temporary",
});
let tab;
await track_ad_click(
"webextension",
"webextension",
async () => {
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
await searchExtension.startup();
return (tab = await tabPromise);
},
async () => {
await searchExtension.unload();
BrowserTestUtils.removeTab(tab);
}
);
});
add_task(async function test_source_webextension_query() {
async function background(SEARCH_TERM) {
// Search with no tabId
browser.search.query({
text: "searchSuggestion",
disposition: "NEW_TAB",
});
}
let searchExtension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["search", "tabs"],
},
background,
useAddonManager: "temporary",
});
let tab;
await track_ad_click(
"webextension",
"webextension",
async () => {
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
await searchExtension.startup();
return (tab = await tabPromise);
},
async () => {
await searchExtension.unload();
BrowserTestUtils.removeTab(tab);
}
);
});

View file

@ -190,7 +190,7 @@ function resetTelemetry() {
* @param {Array} expectedEvents The expected impression events whose keys and
* values we use to validate the recorded Glean impression events.
*/
function assertImpressionEvents(expectedEvents) {
function assertSERPTelemetry(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.
@ -201,7 +201,7 @@ function assertImpressionEvents(expectedEvents) {
Assert.equal(
recordedImpressions.length,
expectedEvents.length,
"Should have the correct number of impressions."
"Number of impressions matches expected events."
);
// Assert the impression events.
@ -209,12 +209,12 @@ function assertImpressionEvents(expectedEvents) {
let impressionId = recordedImpressions[idx].extra.impression_id;
Assert.ok(
UUID_REGEX.test(impressionId),
"Should have an impression_id with a valid UUID."
"Impression has an impression_id with a valid UUID."
);
Assert.ok(
!impressionIdsSet.has(impressionId),
"Should have a unique impression_id."
"Impression has a unique impression_id."
);
impressionIdsSet.add(impressionId);
@ -226,16 +226,22 @@ function assertImpressionEvents(expectedEvents) {
Assert.deepEqual(
recordedImpressions[idx].extra,
expectedEvent.impression,
"Should have matched impression values."
"Matching SERP impression values."
);
// Once the impression check is sufficient, add the impression_id to
// each of the expected engagements for later deep equal checks.
// each of the expected engagements and ad impressions for deep equal
// checks.
if (expectedEvent.engagements) {
for (let expectedEngagment of expectedEvent.engagements) {
expectedEngagment.impression_id = impressionId;
}
}
if (expectedEvent.adImpressions) {
for (let adImpression of expectedEvent.adImpressions) {
adImpression.impression_id = impressionId;
}
}
}
// Group engagement events into separate array fetchable by their
@ -246,10 +252,7 @@ function assertImpressionEvents(expectedEvents) {
for (let recordedEngagement of recordedEngagements) {
let impressionId = recordedEngagement.extra.impression_id;
Assert.ok(
impressionId,
"Should have an engagement event with an impression_id"
);
Assert.ok(impressionId, "Engagement event has impression_id.");
let arr = idToEngagements.get(impressionId) ?? [];
arr.push(recordedEngagement.extra);
@ -266,7 +269,7 @@ function assertImpressionEvents(expectedEvents) {
Assert.deepEqual(
recorded,
expectedEngagements,
"Should have matched engagement values."
"Matching engagement value."
);
totalExpectedEngagements += expectedEngagements.length;
}
@ -275,33 +278,78 @@ function assertImpressionEvents(expectedEvents) {
Assert.equal(
recordedEngagements.length,
totalExpectedEngagements,
"Should have equal number of engagements."
);
}
function assertAdImpressionEvents(expectedAdImpressions) {
let adImpressions = Glean.serp.adImpression.testGetValue() ?? [];
let impressions = Glean.serp.impression.testGetValue() ?? [];
Assert.equal(impressions.length, 1, "Should have a SERP impression event.");
Assert.equal(
adImpressions.length,
expectedAdImpressions.length,
"Should have equal number of ad impression events."
"Number of engagements"
);
expectedAdImpressions = expectedAdImpressions.map(expectedAdImpression => {
expectedAdImpression.impression_id = impressions[0].extra.impression_id;
return expectedAdImpression;
});
let recordedAdImpressions = Glean.serp.adImpression.testGetValue() ?? [];
let idToAdImpressions = new Map();
let totalExpectedAdImpressions = 0;
for (let [index, expectedAdImpression] of expectedAdImpressions.entries()) {
Assert.deepEqual(
adImpressions[index]?.extra,
expectedAdImpression,
"Should have equal values for an ad impression."
);
// The list of ad impressions are contained in a flat list. Separate them
// into arrays organized by impressionId to make it easier to determine if
// the page load that matches the expected ads on the page.
for (let recordedAdImpression of recordedAdImpressions) {
let impressionId = recordedAdImpression.extra.impression_id;
Assert.ok(impressionId, "Ad impression has impression_id");
let arr = idToAdImpressions.get(impressionId) ?? [];
arr.push(recordedAdImpression.extra);
idToAdImpressions.set(impressionId, arr);
}
for (let expectedEvent of expectedEvents) {
let impressionId = expectedEvent.impression.impression_id;
let expectedAdImpressions = expectedEvent.adImpressions ?? [];
if (expectedAdImpressions.length) {
let recorded = idToAdImpressions.get(impressionId) ?? {};
Assert.deepEqual(
recorded,
expectedAdImpressions,
"Matching ad impression value."
);
}
totalExpectedAdImpressions += expectedAdImpressions.length;
}
Assert.equal(
recordedAdImpressions.length,
totalExpectedAdImpressions,
"Recorded and expected ad impression counts match."
);
// Assert abandonment events.
let recordedAbandonments = Glean.serp.abandonment.testGetValue() ?? [];
let idTorecordedAbandonments = new Map();
let totalExpectedrecordedAbandonments = 0;
for (let recordedAbandonment of recordedAbandonments) {
let impressionId = recordedAbandonment.extra.impression_id;
Assert.ok(impressionId, "Ad impression event has an impression_id.");
let arr = idTorecordedAbandonments.get(impressionId) ?? [];
arr.push(idTorecordedAbandonments.extra);
idTorecordedAbandonments.set(impressionId, arr);
}
for (let expectedEvent of expectedEvents) {
let impressionId = expectedEvent.impression.impression_id;
let expectedAbandonment = expectedEvent.abandonment;
if (expectedAbandonment) {
let recorded = idTorecordedAbandonments.get(impressionId);
Assert.deepEqual(
recorded,
expectedAbandonment,
"Abandonment value matches."
);
}
totalExpectedrecordedAbandonments += expectedAbandonment ? 1 : 0;
}
Assert.equal(
recordedAbandonments.length,
totalExpectedrecordedAbandonments,
"Recorded and expected abandonment counts match."
);
}
function assertAbandonmentEvent(expectedAbandonment) {
@ -314,53 +362,12 @@ function assertAbandonmentEvent(expectedAbandonment) {
);
}
async function promiseAdImpressionReceived(num) {
if (num) {
return TestUtils.waitForCondition(() => {
let adImpressions = Glean.serp.adImpression.testGetValue() ?? [];
return adImpressions.length == num;
}, `Should have received ${num} ad impressions.`);
}
return TestUtils.waitForCondition(() => {
let adImpressions = Glean.serp.adImpression.testGetValue() ?? [];
return adImpressions.length;
}, "Should have received an ad impression.");
function waitForPageWithAdImpressions() {
return TestUtils.topicObserved("reported-page-with-ad-impressions");
}
async function waitForPageWithAdImpressions() {
return new Promise(resolve => {
let listener = win => {
Services.obs.removeObserver(
listener,
"reported-page-with-ad-impressions"
);
resolve();
};
Services.obs.addObserver(listener, "reported-page-with-ad-impressions");
});
}
async function waitForPageWithCategorizedDomains() {
return new Promise(resolve => {
let listener = win => {
Services.obs.removeObserver(
listener,
"reported-page-with-categorized-domains"
);
resolve();
};
Services.obs.addObserver(
listener,
"reported-page-with-categorized-domains"
);
});
}
async function promiseImpressionReceived() {
return TestUtils.waitForCondition(() => {
let adImpressions = Glean.serp.adImpression.testGetValue() ?? [];
return adImpressions.length;
}, "Should have received an ad impression.");
function waitForPageWithCategorizedDomains() {
return TestUtils.topicObserved("reported-page-with-categorized-domains");
}
registerCleanupFunction(async () => {

View file

@ -1,20 +0,0 @@
[DEFAULT]
support-files =
../../../../../services/settings/dumps/main/search-config-v2.json
skip-if = toolkit == 'android' # bug 1730213
firefox-appdir = browser
[test_search_telemetry_categorization_logic.js]
[test_search_telemetry_categorization_process_domains.js]
[test_search_telemetry_categorization_sync.js]
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]
[test_search_telemetry_config_validation.js]
support-files =
../../schema/search-telemetry-schema.json
[test_urlTelemetry.js]
[test_urlTelemetry_generic.js]

View file

@ -0,0 +1,25 @@
[DEFAULT]
support-files = ["../../../../../services/settings/dumps/main/search-config-v2.json"]
skip-if = ["toolkit == 'android'"] # bug 1730213
firefox-appdir = "browser"
["test_search_telemetry_categorization_logic.js"]
["test_search_telemetry_categorization_process_domains.js"]
["test_search_telemetry_categorization_sync.js"]
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"]
["test_search_telemetry_config_validation.js"]
support-files = ["../../schema/search-telemetry-schema.json"]
["test_urlTelemetry.js"]
["test_urlTelemetry_generic.js"]

View file

@ -4,7 +4,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
BROWSER_CHROME_MANIFESTS += ["test/browser.toml"]
JAR_MANIFESTS += ["jar.mn"]

View file

@ -572,7 +572,6 @@ skip-if = [
]
["browser_urlbarSearchMode.js"]
fail-if = ["a11y_checks"] # Bug 1854529 clicked urlbar-engine-one-off-item-history button may not be focusable
["browser_userTyped_restored_after_discard.js"]

View file

@ -1,21 +0,0 @@
[DEFAULT]
head = head.js
tags = condprof
firefox-appdir = browser
skip-if = toolkit == 'android' # bug 1730213
support-files =
data/sessionCheckpoints_all.json
data/sessionstore_invalid.js
data/sessionstore_valid.js
[test_backup_once.js]
skip-if = condprof # 1769154
[test_final_write_cleanup.js]
[test_histogram_corrupt_files.js]
[test_migration_lz4compression.js]
skip-if = condprof # 1769154
[test_startup_nosession_async.js]
skip-if = condprof # 1769154
[test_startup_session_async.js]
[test_startup_invalid_session.js]
skip-if = condprof # 1769154

View file

@ -0,0 +1,28 @@
[DEFAULT]
head = "head.js"
tags = "condprof"
firefox-appdir = "browser"
skip-if = ["toolkit == 'android'"] # bug 1730213
support-files = [
"data/sessionCheckpoints_all.json",
"data/sessionstore_invalid.js",
"data/sessionstore_valid.js",
]
["test_backup_once.js"]
skip-if = ["condprof"] # 1769154
["test_final_write_cleanup.js"]
["test_histogram_corrupt_files.js"]
["test_migration_lz4compression.js"]
skip-if = ["condprof"] # 1769154
["test_startup_invalid_session.js"]
skip-if = ["condprof"] # 1769154
["test_startup_nosession_async.js"]
skip-if = ["condprof"] # 1769154
["test_startup_session_async.js"]

View file

@ -8,7 +8,7 @@
LOCAL_INCLUDES += ["/xpcom/build"]
BROWSER_CHROME_MANIFESTS += ["test/browser.toml"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.ini"]
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
JAR_MANIFESTS += ["jar.mn"]

View file

@ -1,6 +0,0 @@
[DEFAULT]
skip-if = toolkit == 'android' # bug 1730213
firefox-appdir = browser
[test_macOS_showSecurityPreferences.js]
skip-if = toolkit != "cocoa"

View file

@ -0,0 +1,6 @@
[DEFAULT]
skip-if = ["toolkit == 'android'"] # bug 1730213
firefox-appdir = "browser"
["test_macOS_showSecurityPreferences.js"]
run-if = ["os == 'mac'"]

Some files were not shown because too many files have changed in this diff Show more