Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* Any copyright is dedicated to the Public Domain.
*/
/**
* This file tests the urlbar.searchmode.* scalars telemetry with search mode
* related actions.
*/
"use strict";
const ENTRY_SCALAR_PREFIX = "urlbar.searchmode.";
const PICKED_SCALAR_PREFIX = "urlbar.picked.searchmode.";
const ENGINE_ALIAS = "alias";
const TEST_QUERY = "test";
let engineName;
let engineDomain;
// The preference to enable suggestions.
const SUGGEST_PREF = "browser.search.suggest.enabled";
ChromeUtils.defineESModuleGetters(this, {
UrlbarProviderTabToSearch:
});
XPCOMUtils.defineLazyServiceGetter(
this,
"TouchBarHelper",
"@mozilla.org/widget/touchbarhelper;1",
"nsITouchBarHelper"
);
/**
* Asserts that search mode telemetry was recorded correctly. Checks both the
* urlbar.searchmode.* and urlbar.searchmode_picked.* probes.
*
* @param {string} entry
* A search mode entry point.
* @param {string} engineOrSource
* An engine name or a search mode source.
* @param {number} [resultIndex]
* The index of the result picked while in search mode. Only pass this
* parameter if a result is picked.
*/
function assertSearchModeScalars(entry, engineOrSource, resultIndex = -1) {
// Check if the urlbar.searchmode.entry scalar contains the expected value.
const scalars = TelemetryTestUtils.getProcessScalars("parent", true, false);
TelemetryTestUtils.assertKeyedScalar(
scalars,
ENTRY_SCALAR_PREFIX + entry,
engineOrSource,
1
);
for (let e of UrlbarUtils.SEARCH_MODE_ENTRY) {
if (e == entry) {
Assert.equal(
Object.keys(scalars[ENTRY_SCALAR_PREFIX + entry]).length,
1,
`This search must only increment one entry in the correct scalar: ${e}`
);
} else {
Assert.ok(
!scalars[ENTRY_SCALAR_PREFIX + e],
`No other urlbar.searchmode scalars should be recorded. Checking ${e}`
);
}
}
if (resultIndex >= 0) {
TelemetryTestUtils.assertKeyedScalar(
scalars,
PICKED_SCALAR_PREFIX + entry,
resultIndex,
1
);
}
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
}
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
// Disable tab-to-search onboarding results for general tests. They are
// enabled in tests that specifically address onboarding.
["browser.urlbar.tabToSearch.onboard.interactionsLeft", 0],
],
});
// Create an engine to generate search suggestions and add it as default
// for this test.
let suggestionEngine = await SearchTestUtils.promiseNewSearchEngine({
url: getRootDirectory(gTestPath) + "urlbarTelemetrySearchSuggestions.xml",
setAsDefault: true,
});
suggestionEngine.alias = ENGINE_ALIAS;
engineDomain = suggestionEngine.searchUrlDomain;
engineName = suggestionEngine.name;
// And the first one-off engine.
await Services.search.moveEngine(suggestionEngine, 0);
// Enable local telemetry recording for the duration of the tests.
let oldCanRecord = Services.telemetry.canRecordExtended;
Services.telemetry.canRecordExtended = true;
// Clear history so that history added by previous tests doesn't mess up this
// test when it selects results in the urlbar.
await PlacesUtils.history.clear();
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
// Clear historical search suggestions to avoid interference from previous
// tests.
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.maxHistoricalSearchSuggestions", 0]],
});
// Make sure to restore the engine once we're done.
registerCleanupFunction(async function () {
Services.telemetry.canRecordExtended = oldCanRecord;
await PlacesUtils.history.clear();
Services.telemetry.setEventRecordingEnabled("navigation", false);
});
});
// Clicks the first one off.
add_task(async function test_oneoff_remote() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: TEST_QUERY,
});
// Enters search mode by clicking a one-off.
await UrlbarTestUtils.enterSearchMode(window);
let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
EventUtils.synthesizeKey("KEY_Enter");
await loadPromise;
assertSearchModeScalars("oneoff", "other", 0);
BrowserTestUtils.removeTab(tab);
});
// Clicks the history one off.
add_task(async function test_oneoff_local() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: TEST_QUERY,
});
// Enters search mode by clicking a one-off.
await UrlbarTestUtils.enterSearchMode(window, {
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
});
let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
EventUtils.synthesizeKey("KEY_ArrowDown");
EventUtils.synthesizeKey("KEY_Enter");
await loadPromise;
assertSearchModeScalars("oneoff", "history", 0);
BrowserTestUtils.removeTab(tab);
});
// Checks that the Amazon search mode name is collapsed to "Amazon".
add_task(async function test_oneoff_amazon() {
// Disable suggestions to avoid hitting Amazon servers.
await SpecialPowers.pushPrefEnv({
set: [[SUGGEST_PREF, false]],
});
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: TEST_QUERY,
});
// Enters search mode by clicking a one-off.
await UrlbarTestUtils.enterSearchMode(window, {
engineName: "Amazon.com",
});
assertSearchModeScalars("oneoff", "Amazon");
await UrlbarTestUtils.exitSearchMode(window);
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
});
// Checks that the Wikipedia search mode name is collapsed to "Wikipedia".
add_task(async function test_oneoff_wikipedia() {
// Disable suggestions to avoid hitting Wikipedia servers.
await SpecialPowers.pushPrefEnv({
set: [[SUGGEST_PREF, false]],
});
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: TEST_QUERY,
});
// Enters search mode by clicking a one-off.
await UrlbarTestUtils.enterSearchMode(window, {
engineName: "Wikipedia (en)",
});
assertSearchModeScalars("oneoff", "Wikipedia");
await UrlbarTestUtils.exitSearchMode(window);
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
});
// Enters search mode by pressing the keyboard shortcut.
add_task(async function test_shortcut() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: TEST_QUERY,
});
// Enter search mode by pressing the keyboard shortcut.
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("k", { accelKey: true });
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
engineName,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
entry: "shortcut",
});
assertSearchModeScalars("shortcut", "other");
BrowserTestUtils.removeTab(tab);
});
// Enters search mode by selecting a Top Site from the Urlbar.
add_task(async function test_topsites_urlbar() {
// Disable suggestions to avoid hitting Amazon servers.
await SpecialPowers.pushPrefEnv({
set: [[SUGGEST_PREF, false]],
});
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
// Enter search mode by selecting a Top Site from the Urlbar.
await UrlbarTestUtils.promisePopupOpen(window, () => {
if (gURLBar.getAttribute("pageproxystate") == "invalid") {
gURLBar.handleRevert();
}
EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
});
await UrlbarTestUtils.promiseSearchComplete(window);
let amazonSearch = await UrlbarTestUtils.waitForAutocompleteResultAt(
window,
0
);
Assert.equal(
amazonSearch.result.payload.keyword,
"@amazon",
"First result should have the Amazon keyword."
);
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeMouseAtCenter(amazonSearch, {});
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
engineName: amazonSearch.result.payload.engine,
entry: "topsites_urlbar",
});
assertSearchModeScalars("topsites_urlbar", "Amazon");
await UrlbarTestUtils.exitSearchMode(window);
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
});
// Enters search mode by selecting a keyword offer result.
add_task(async function test_keywordoffer() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
// Do a search for "@" + our test alias. It should autofill with a trailing
// space, and the heuristic result should be an autofill result with a keyword
// offer.
let alias = "@" + ENGINE_ALIAS;
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: alias,
});
let keywordOfferResult = await UrlbarTestUtils.getDetailsOfResultAt(
window,
0
);
Assert.equal(
keywordOfferResult.searchParams.keyword,
alias,
"The first result should be a keyword search result with the correct alias."
);
// Pick the keyword offer result.
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("KEY_Enter");
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
engineName,
entry: "keywordoffer",
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "foo",
});
let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
EventUtils.synthesizeKey("KEY_Enter");
await loadPromise;
assertSearchModeScalars("keywordoffer", "other", 0);
BrowserTestUtils.removeTab(tab);
});
// Enters search mode by typing an alias.
add_task(async function test_typed() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
// Enter search mode by selecting a keywordoffer result.
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: `${ENGINE_ALIAS} `,
});
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey(" ");
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
engineName,
entry: "typed",
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "foo",
});
let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
EventUtils.synthesizeKey("KEY_Enter");
await loadPromise;
assertSearchModeScalars("typed", "other", 0);
BrowserTestUtils.removeTab(tab);
});
// Enters search mode by calling the same function called by the Search
// Bookmarks menu item in Library > Bookmarks.
add_task(async function test_bookmarkmenu() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
PlacesCommandHook.searchBookmarks();
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
entry: "bookmarkmenu",
});
assertSearchModeScalars("bookmarkmenu", "bookmarks");
BrowserTestUtils.removeTab(tab);
});
// Enters search mode by calling the same function called from a History
// menu.
add_task(async function test_historymenu() {
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
PlacesCommandHook.searchHistory();
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
entry: "historymenu",
});
assertSearchModeScalars("historymenu", "history");
});
// Enters search mode by calling the same function called by the Search Tabs
// menu item in the tab overflow menu.
add_task(async function test_tabmenu() {
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
gTabsPanel.searchTabs();
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
source: UrlbarUtils.RESULT_SOURCE.TABS,
entry: "tabmenu",
});
assertSearchModeScalars("tabmenu", "tabs");
});
// Enters search mode by performing a search handoff on about:privatebrowsing.
// Note that handoff-to-search-mode only occurs when suggestions are disabled
// in the Urlbar.
// NOTE: We don't test handoff on about:home. Running mochitests on about:home
// is quite difficult. This subtest verifies that `handoff` is a valid scalar
// suffix and that a call to UrlbarInput.handoff(value, searchEngine) records
// values in the urlbar.searchmode.handoff scalar. PlacesFeed.test.js verfies that
// about:home handoff makes that exact call.
add_task(async function test_handoff_pbm() {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.suggest.searches", false]],
});
let win = await BrowserTestUtils.openNewBrowserWindow({
private: true,
waitForTabURL: "about:privatebrowsing",
});
let tab = win.gBrowser.selectedBrowser;
await SpecialPowers.spawn(tab, [], async function () {
let btn = content.document.getElementById("search-handoff-button");
btn.click();
});
let searchPromise = UrlbarTestUtils.promiseSearchComplete(win);
await new Promise(r => EventUtils.synthesizeKey("f", {}, win, r));
await searchPromise;
await UrlbarTestUtils.assertSearchMode(win, {
engineName,
entry: "handoff",
});
assertSearchModeScalars("handoff", "other");
await UrlbarTestUtils.exitSearchMode(win);
await UrlbarTestUtils.promisePopupClose(win);
await BrowserTestUtils.closeWindow(win);
await SpecialPowers.popPrefEnv();
});
// Enters search mode by tapping a search shortcut on the Touch Bar.
add_task(async function test_touchbar() {
if (AppConstants.platform != "macosx") {
return;
}
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: TEST_QUERY,
});
// We have to fake the tap on the Touch Bar since mochitests have no way of
// interacting with the Touch Bar.
TouchBarHelper.insertRestrictionInUrlbar(UrlbarTokenizer.RESTRICT.HISTORY);
await UrlbarTestUtils.assertSearchMode(window, {
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
entry: "touchbar",
});
let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
EventUtils.synthesizeKey("KEY_ArrowDown");
EventUtils.synthesizeKey("KEY_Enter");
await loadPromise;
assertSearchModeScalars("touchbar", "history", 0);
BrowserTestUtils.removeTab(tab);
});
// Enters search mode by selecting a tab-to-search result.
// Tests that tab-to-search results preview search mode when highlighted. These
// results are worth testing separately since they do not set the
// payload.keyword parameter.
add_task(async function test_tabtosearch() {
await SpecialPowers.pushPrefEnv({
set: [
// Do not show the onboarding result for this subtest.
["browser.urlbar.tabToSearch.onboard.interactionsLeft", 0],
],
});
await PlacesTestUtils.addVisits([`http://${engineDomain}/`]);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: engineDomain.slice(0, 4),
});
let tabToSearchResult = (
await UrlbarTestUtils.waitForAutocompleteResultAt(window, 1)
).result;
Assert.equal(
tabToSearchResult.providerName,
"TabToSearch",
"The second result is a tab-to-search result."
);
Assert.equal(
tabToSearchResult.payload.engine,
engineName,
"The tab-to-search result is for the correct engine."
);
await UrlbarTestUtils.assertSearchMode(window, null);
EventUtils.synthesizeKey("KEY_ArrowDown");
Assert.equal(
UrlbarTestUtils.getSelectedRowIndex(window),
1,
"Sanity check: The second result is selected."
);
// Pick the tab-to-search result.
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("KEY_Enter");
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
engineName,
entry: "tabtosearch",
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "foo",
});
let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
EventUtils.synthesizeKey("KEY_Enter");
await loadPromise;
assertSearchModeScalars("tabtosearch", "other", 0);
BrowserTestUtils.removeTab(tab);
await PlacesUtils.history.clear();
await SpecialPowers.popPrefEnv();
});
// Enters search mode by selecting a tab-to-search onboarding result.
add_task(async function test_tabtosearch_onboard() {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.tabToSearch.onboard.interactionsLeft", 3]],
});
await PlacesTestUtils.addVisits([`http://${engineDomain}/`]);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: engineDomain.slice(0, 4),
fireInputEvent: true,
});
let tabToSearchResult = (
await UrlbarTestUtils.waitForAutocompleteResultAt(window, 1)
).result;
Assert.equal(
tabToSearchResult.providerName,
"TabToSearch",
"The second result is a tab-to-search result."
);
Assert.equal(
tabToSearchResult.payload.engine,
engineName,
"The tab-to-search result is for the correct engine."
);
Assert.equal(
tabToSearchResult.payload.dynamicType,
"onboardTabToSearch",
"The tab-to-search result is an onboarding result."
);
await UrlbarTestUtils.assertSearchMode(window, null);
EventUtils.synthesizeKey("KEY_ArrowDown");
Assert.equal(
UrlbarTestUtils.getSelectedRowIndex(window),
1,
"Sanity check: The second result is selected."
);
// Pick the tab-to-search onboarding result.
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("KEY_Enter");
await searchPromise;
await UrlbarTestUtils.assertSearchMode(window, {
engineName,
entry: "tabtosearch_onboard",
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "foo",
});
let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
EventUtils.synthesizeKey("KEY_Enter");
await loadPromise;
assertSearchModeScalars("tabtosearch_onboard", "other", 0);
UrlbarPrefs.set("tabToSearch.onboard.interactionsLeft", 3);
delete UrlbarProviderTabToSearch.onboardingInteractionAtTime;
BrowserTestUtils.removeTab(tab);
await PlacesUtils.history.clear();
await SpecialPowers.popPrefEnv();
});