1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/ */
6 Services.scriptloader.loadSubScript(
7 "chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/head-common.js",
11 ChromeUtils.defineESModuleGetters(this, {
12 QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs",
17 XPCOMUtils.defineLazyGetter(lazy, "QuickSuggestTestUtils", () => {
18 const { QuickSuggestTestUtils: module } = ChromeUtils.importESModule(
19 "resource://testing-common/QuickSuggestTestUtils.sys.mjs"
25 XPCOMUtils.defineLazyGetter(this, "MerinoTestUtils", () => {
26 const { MerinoTestUtils: module } = ChromeUtils.importESModule(
27 "resource://testing-common/MerinoTestUtils.sys.mjs"
33 ChromeUtils.defineESModuleGetters(lazy, {
34 UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.sys.mjs",
35 sinon: "resource://testing-common/Sinon.sys.mjs",
38 async function addTopSites(url) {
39 for (let i = 0; i < 5; i++) {
40 await PlacesTestUtils.addVisits(url);
42 await updateTopSites(sites => {
43 return sites && sites[0] && sites[0].url == url;
47 function assertAbandonmentTelemetry(expectedExtraList) {
48 _assertGleanTelemetry("abandonment", expectedExtraList);
51 function assertEngagementTelemetry(expectedExtraList) {
52 _assertGleanTelemetry("engagement", expectedExtraList);
55 function assertImpressionTelemetry(expectedExtraList) {
56 _assertGleanTelemetry("impression", expectedExtraList);
59 function assertExposureTelemetry(expectedExtraList) {
60 _assertGleanTelemetry("exposure", expectedExtraList);
63 function _assertGleanTelemetry(telemetryName, expectedExtraList) {
64 const telemetries = Glean.urlbar[telemetryName].testGetValue() ?? [];
67 expectedExtraList.length,
68 "Telemetry event length matches expected event length."
71 for (let i = 0; i < telemetries.length; i++) {
72 const telemetry = telemetries[i];
73 Assert.equal(telemetry.category, "urlbar");
74 Assert.equal(telemetry.name, telemetryName);
76 const expectedExtra = expectedExtraList[i];
77 for (const key of Object.keys(expectedExtra)) {
87 async function ensureQuickSuggestInit({
88 merinoSuggestions = undefined,
91 return lazy.QuickSuggestTestUtils.ensureQuickSuggestInit({
94 remoteSettingsResults: [
100 url: "https://example.com/sponsored",
101 title: "Sponsored suggestion",
102 keywords: ["sponsored"],
103 click_url: "https://example.com/click",
104 impression_url: "https://example.com/impression",
105 advertiser: "TestAdvertiser",
106 iab_category: "22 - Shopping",
110 url: `https://example.com/nonsponsored`,
111 title: "Non-sponsored suggestion",
112 keywords: ["nonsponsored"],
113 click_url: "https://example.com/click",
114 impression_url: "https://example.com/impression",
115 advertiser: "TestAdvertiser",
116 iab_category: "5 - Education",
124 async function doBlur() {
125 await UrlbarTestUtils.promisePopupClose(window, () => {
130 async function doClick() {
131 const selected = UrlbarTestUtils.getSelectedRow(window);
132 const onLoad = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
133 EventUtils.synthesizeMouseAtCenter(selected, {});
137 async function doClickSubButton(selector) {
138 const selected = UrlbarTestUtils.getSelectedElement(window);
139 const button = selected.closest(".urlbarView-row").querySelector(selector);
140 EventUtils.synthesizeMouseAtCenter(button, {});
143 async function doDropAndGo(data) {
144 const onLoad = BrowserTestUtils.browserLoaded(browser);
145 EventUtils.synthesizeDrop(
146 document.getElementById("back-button"),
148 [[{ type: "text/plain", data }]],
155 async function doEnter(modifier = {}) {
156 const onLoad = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
157 EventUtils.synthesizeKey("KEY_Enter", modifier);
161 async function doPaste(data) {
162 await SimpleTest.promiseClipboardChange(data, () => {
163 clipboardHelper.copyString(data);
168 document.commandDispatcher
169 .getControllerForCommand("cmd_paste")
170 .doCommand("cmd_paste");
171 await UrlbarTestUtils.promiseSearchComplete(window);
174 async function doPasteAndGo(data) {
175 await SimpleTest.promiseClipboardChange(data, () => {
176 clipboardHelper.copyString(data);
178 const inputBox = gURLBar.querySelector("moz-input-box");
179 const contextMenu = inputBox.menupopup;
180 const onPopup = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
181 EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {
186 const onLoad = BrowserTestUtils.browserLoaded(browser);
187 const menuitem = inputBox.getMenuItem("paste-and-go");
188 contextMenu.activateItem(menuitem);
192 async function doTest(testFn) {
193 await Services.fog.testFlushAllChildren();
194 Services.fog.testResetFOG();
195 // Enable recording telemetry for abandonment, engagement and impression.
196 Services.fog.setMetricsFeatureConfig(
198 "urlbar.abandonment": true,
199 "urlbar.engagement": true,
200 "urlbar.impression": true,
204 gURLBar.controller.engagementEvent.reset();
205 await PlacesUtils.history.clear();
206 await PlacesUtils.bookmarks.eraseEverything();
207 await PlacesTestUtils.clearHistoryVisits();
208 await PlacesTestUtils.clearInputHistory();
209 await UrlbarTestUtils.formHistory.clear(window);
210 await QuickSuggest.blockedSuggestions.clear();
211 await QuickSuggest.blockedSuggestions._test_readyPromise;
212 await updateTopSites(() => true);
215 await BrowserTestUtils.withNewTab(gBrowser, testFn);
217 Services.fog.setMetricsFeatureConfig("{}");
221 async function initGroupTest() {
222 /* import-globals-from head-groups.js */
223 Services.scriptloader.loadSubScript(
224 "chrome://mochitests/content/browser/browser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js",
230 async function initInteractionTest() {
231 /* import-globals-from head-interaction.js */
232 Services.scriptloader.loadSubScript(
233 "chrome://mochitests/content/browser/browser/components/urlbar/tests/engagementTelemetry/browser/head-interaction.js",
239 async function initNCharsAndNWordsTest() {
240 /* import-globals-from head-n_chars_n_words.js */
241 Services.scriptloader.loadSubScript(
242 "chrome://mochitests/content/browser/browser/components/urlbar/tests/engagementTelemetry/browser/head-n_chars_n_words.js",
248 async function initSapTest() {
249 /* import-globals-from head-sap.js */
250 Services.scriptloader.loadSubScript(
251 "chrome://mochitests/content/browser/browser/components/urlbar/tests/engagementTelemetry/browser/head-sap.js",
257 async function initSearchModeTest() {
258 /* import-globals-from head-search_mode.js */
259 Services.scriptloader.loadSubScript(
260 "chrome://mochitests/content/browser/browser/components/urlbar/tests/engagementTelemetry/browser/head-search_mode.js",
266 async function initExposureTest() {
267 /* import-globals-from head-exposure.js */
268 Services.scriptloader.loadSubScript(
269 "chrome://mochitests/content/browser/browser/components/urlbar/tests/engagementTelemetry/browser/head-exposure.js",
275 function loadOmniboxAddon({ keyword }) {
276 return ExtensionTestUtils.loadExtension({
278 permissions: ["tabs"],
285 browser.omnibox.setDefaultSuggestion({
288 browser.omnibox.onInputEntered.addListener(() => {
289 browser.tabs.update({ url: "https://example.com/" });
291 browser.omnibox.onInputChanged.addListener((text, suggest) => {
298 async function loadRemoteTab(url) {
299 await SpecialPowers.pushPrefEnv({
301 ["browser.urlbar.suggest.searches", false],
302 ["browser.urlbar.maxHistoricalSearchSuggestions", 0],
303 ["browser.urlbar.autoFill", false],
304 ["services.sync.username", "fake"],
305 ["services.sync.syncedTabs.showRemoteTabs", true],
312 lastModified: 1492201200,
314 clientType: "desktop",
320 icon: UrlbarUtils.ICON.DEFAULT,
322 lastUsed: Math.floor(Date.now() / 1000),
327 const sandbox = lazy.sinon.createSandbox();
328 // eslint-disable-next-line no-undef
329 const syncedTabs = SyncedTabs;
330 const originalSyncedTabsInternal = syncedTabs._internal;
331 syncedTabs._internal = {
332 isConfiguredToSyncTabs: true,
333 hasSyncedThisSession: true,
335 return Promise.resolve([]);
338 return Promise.resolve();
341 const weaveXPCService = Cc["@mozilla.org/weave/service;1"].getService(
344 const oldWeaveServiceReady = weaveXPCService.ready;
345 weaveXPCService.ready = true;
347 .stub(syncedTabs._internal, "getTabClients")
348 .callsFake(() => Promise.resolve(Cu.cloneInto([REMOTE_TAB], {})));
353 weaveXPCService.ready = oldWeaveServiceReady;
354 syncedTabs._internal = originalSyncedTabsInternal;
355 // Reset internal cache in UrlbarProviderRemoteTabs.
356 Services.obs.notifyObservers(null, "weave:engine:sync:finish", "tabs");
357 await SpecialPowers.popPrefEnv();
362 async function openPopup(input) {
363 await UrlbarTestUtils.promisePopupOpen(window, async () => {
364 await UrlbarTestUtils.inputIntoURLBar(window, input);
366 await UrlbarTestUtils.promiseSearchComplete(window);
369 async function selectRowByURL(url) {
370 for (let i = 0; i < UrlbarTestUtils.getResultCount(window); i++) {
371 const detail = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
372 if (detail.url === url) {
373 UrlbarTestUtils.setSelectedRowIndex(window, i);
379 async function selectRowByProvider(provider) {
380 for (let i = 0; i < UrlbarTestUtils.getResultCount(window); i++) {
381 const detail = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
382 if (detail.result.providerName === provider) {
383 UrlbarTestUtils.setSelectedRowIndex(window, i);
389 async function selectRowByType(type) {
390 for (let i = 0; i < UrlbarTestUtils.getResultCount(window); i++) {
391 const detail = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
392 if (detail.result.payload.type === type) {
393 UrlbarTestUtils.setSelectedRowIndex(window, i);
399 async function setup() {
400 await SpecialPowers.pushPrefEnv({
402 ["browser.urlbar.searchEngagementTelemetry.enabled", true],
403 ["browser.urlbar.quickactions.enabled", true],
404 ["browser.urlbar.quickactions.minimumSearchString", 0],
405 ["browser.urlbar.suggest.quickactions", true],
406 ["browser.urlbar.shortcuts.quickactions", true],
408 "browser.urlbar.searchEngagementTelemetry.pauseImpressionIntervalMs",
414 const engine = await SearchTestUtils.promiseNewSearchEngine({
415 url: "chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/searchSuggestionEngine.xml",
417 const originalDefaultEngine = await Services.search.getDefault();
418 await Services.search.setDefault(
420 Ci.nsISearchService.CHANGE_REASON_UNKNOWN
422 await Services.search.moveEngine(engine, 0);
424 registerCleanupFunction(async function () {
425 await SpecialPowers.popPrefEnv();
426 await Services.search.setDefault(
427 originalDefaultEngine,
428 Ci.nsISearchService.CHANGE_REASON_UNKNOWN
433 async function setupNimbus(variables) {
434 return lazy.UrlbarTestUtils.initNimbusFeature(variables);
437 async function showResultByArrowDown() {
440 await UrlbarTestUtils.promisePopupOpen(window, () => {
441 EventUtils.synthesizeKey("KEY_ArrowDown");
443 await UrlbarTestUtils.promiseSearchComplete(window);
446 async function waitForPauseImpression() {
447 await new Promise(r =>
450 UrlbarPrefs.get("searchEngagementTelemetry.pauseImpressionIntervalMs")
453 await Services.fog.testFlushAllChildren();