Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* Any copyright is dedicated to the Public Domain.
"use strict";
/**
* Tests search suggestions in search mode.
*/
const DEFAULT_ENGINE_NAME = "Test";
const SUGGESTIONS_ENGINE_NAME = "searchSuggestionEngine.xml";
const MANY_SUGGESTIONS_ENGINE_NAME = "searchSuggestionEngineMany.xml";
const MAX_RESULT_COUNT = UrlbarPrefs.get("maxRichResults");
let suggestionsEngine;
let expectedFormHistoryResults = [];
add_setup(async function () {
suggestionsEngine = await SearchTestUtils.promiseNewSearchEngine({
url: getRootDirectory(gTestPath) + SUGGESTIONS_ENGINE_NAME,
});
await SearchTestUtils.installSearchExtension(
{
name: DEFAULT_ENGINE_NAME,
keyword: "@test",
},
{ setAsDefault: true }
);
await Services.search.moveEngine(suggestionsEngine, 0);
async function cleanup() {
await PlacesUtils.history.clear();
await PlacesUtils.bookmarks.eraseEverything();
}
await cleanup();
registerCleanupFunction(cleanup);
// Add some form history for our test engine.
for (let i = 0; i < MAX_RESULT_COUNT; i++) {
let value = `hello formHistory ${i}`;
await UrlbarTestUtils.formHistory.add([
{ value, source: suggestionsEngine.name },
]);
expectedFormHistoryResults.push({
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
searchParams: {
suggestion: value,
engine: suggestionsEngine.name,
},
});
}
// Add other form history.
await UrlbarTestUtils.formHistory.add([
{ value: "hello formHistory global" },
{ value: "hello formHistory other", source: "other engine" },
]);
registerCleanupFunction(async () => {
await UrlbarTestUtils.formHistory.clear();
});
await SpecialPowers.pushPrefEnv({
set: [
["browser.search.separatePrivateDefault.ui.enabled", false],
["browser.urlbar.suggest.quickactions", false],
["browser.urlbar.suggest.trending", false],
["browser.urlbar.suggest.recentsearches", false],
],
});
});
add_task(async function emptySearch() {
await BrowserTestUtils.withNewTab("about:robots", async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update2.emptySearchBehavior", 2]],
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await UrlbarTestUtils.enterSearchMode(window);
Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
// For the empty search case, we expect to get the form history relative to
// the picked engine and no heuristic.
await checkResults(expectedFormHistoryResults);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
});
});
add_task(async function emptySearch_withRestyledHistory() {
// URLs with the same host as the search engine.
await PlacesTestUtils.addVisits([
// Should not be returned because it's a redirect target.
{
transition: PlacesUtils.history.TRANSITIONS.REDIRECT_TEMPORARY,
},
// Can be restyled and dupes form history.
// Can be restyled but does not dupe form history.
]);
await BrowserTestUtils.withNewTab("about:robots", async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update2.emptySearchBehavior", 2]],
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await UrlbarTestUtils.enterSearchMode(window);
Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
// For the empty search case, we expect to get the form history relative to
// the picked engine, history without redirects, and no heuristic.
await checkResults([
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
searchParams: {
suggestion: "ciao",
engine: suggestionsEngine.name,
},
},
...expectedFormHistoryResults.slice(0, MAX_RESULT_COUNT - 3),
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
});
await PlacesUtils.history.clear();
});
add_task(async function emptySearch_withRestyledHistory_noSearchHistory() {
// URLs with the same host as the search engine.
await PlacesTestUtils.addVisits([
// Can be restyled but does not dupe form history.
]);
await BrowserTestUtils.withNewTab("about:robots", async function () {
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.update2.emptySearchBehavior", 2],
["browser.urlbar.maxHistoricalSearchSuggestions", 0],
],
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await UrlbarTestUtils.enterSearchMode(window);
Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
// maxHistoricalSearchSuggestions == 0, so form history should not be
// present.
await checkResults([
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
});
await PlacesUtils.history.clear();
});
add_task(async function emptySearch_behavior() {
// URLs with the same host as the search engine.
await PlacesTestUtils.addVisits([`http://mochi.test/`]);
await BrowserTestUtils.withNewTab("about:robots", async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update2.emptySearchBehavior", 0]],
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await UrlbarTestUtils.enterSearchMode(window);
Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
// For the empty search case, we expect to get the form history relative to
// the picked engine, history without redirects, and no heuristic.
await checkResults([]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
// We should still show history for empty searches when not in search mode.
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: " ",
});
await checkResults([
{
heuristic: true,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query: " ",
engine: DEFAULT_ENGINE_NAME,
},
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
},
]);
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
});
await BrowserTestUtils.withNewTab("about:robots", async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update2.emptySearchBehavior", 1]],
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await UrlbarTestUtils.enterSearchMode(window);
Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
// For the empty search case, we expect to get the form history relative to
// the picked engine, history without redirects, and no heuristic.
await checkResults([...expectedFormHistoryResults]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
});
await PlacesUtils.history.clear();
});
add_task(async function emptySearch_local() {
await PlacesTestUtils.addVisits([`http://mochi.test/`]);
await BrowserTestUtils.withNewTab("about:robots", async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update2.emptySearchBehavior", 0]],
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await UrlbarTestUtils.enterSearchMode(window, {
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
});
Assert.equal(gURLBar.value, "", "Urlbar value should be cleared.");
// Even when emptySearchBehavior is 0, we still show the user's most frecent
// history for an empty search.
await checkResults([
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
});
await PlacesUtils.history.clear();
});
add_task(async function nonEmptySearch() {
await BrowserTestUtils.withNewTab("about:robots", async function () {
let query = "hello";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: query,
});
await UrlbarTestUtils.enterSearchMode(window);
Assert.equal(gURLBar.value, query, "Urlbar value should be set.");
// We expect to get the heuristic and all the suggestions.
await checkResults([
{
heuristic: true,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
engine: suggestionsEngine.name,
},
},
...expectedFormHistoryResults.slice(0, MAX_RESULT_COUNT - 3),
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
suggestion: `${query}foo`,
engine: suggestionsEngine.name,
},
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
suggestion: `${query}bar`,
engine: suggestionsEngine.name,
},
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
});
});
add_task(async function nonEmptySearch_nonMatching() {
await BrowserTestUtils.withNewTab("about:robots", async function () {
let query = "ciao";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: query,
});
await UrlbarTestUtils.enterSearchMode(window);
Assert.equal(gURLBar.value, query, "Urlbar value should be set.");
// We expect to get the heuristic and the remote suggestions since the local
// ones don't match.
await checkResults([
{
heuristic: true,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
engine: suggestionsEngine.name,
},
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
suggestion: `${query}foo`,
engine: suggestionsEngine.name,
},
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
suggestion: `${query}bar`,
engine: suggestionsEngine.name,
},
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
});
});
add_task(async function nonEmptySearch_withHistory() {
let manySuggestionsEngine = await SearchTestUtils.promiseNewSearchEngine({
url: getRootDirectory(gTestPath) + MANY_SUGGESTIONS_ENGINE_NAME,
});
// URLs with the same host as the search engine.
let query = "ciao";
await PlacesTestUtils.addVisits([
`http://mochi.test/${query}1`,
// Should not be returned because it has a different host, even if it
// matches the host in the path.
]);
function makeSuggestionResult(suffix) {
return {
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
suggestion: `${query}${suffix}`,
engine: manySuggestionsEngine.name,
},
};
}
await BrowserTestUtils.withNewTab("about:robots", async function () {
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: query,
});
await UrlbarTestUtils.enterSearchMode(window, {
engineName: manySuggestionsEngine.name,
});
Assert.equal(gURLBar.value, query, "Urlbar value should be set.");
await checkResults([
{
heuristic: true,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
engine: manySuggestionsEngine.name,
},
},
makeSuggestionResult("foo"),
makeSuggestionResult("bar"),
makeSuggestionResult("1"),
makeSuggestionResult("2"),
makeSuggestionResult("3"),
makeSuggestionResult("4"),
makeSuggestionResult("5"),
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
url: `http://mochi.test/${query}1`,
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
url: `http://mochi.test/${query}`,
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
info("Test again with history before suggestions");
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.showSearchSuggestionsFirst", false]],
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: query,
});
await UrlbarTestUtils.enterSearchMode(window, {
engineName: manySuggestionsEngine.name,
});
Assert.equal(gURLBar.value, query, "Urlbar value should be set.");
await checkResults([
{
heuristic: true,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
engine: manySuggestionsEngine.name,
},
},
makeSuggestionResult("foo"),
makeSuggestionResult("bar"),
makeSuggestionResult("1"),
makeSuggestionResult("2"),
makeSuggestionResult("3"),
makeSuggestionResult("4"),
makeSuggestionResult("5"),
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
url: `http://mochi.test/${query}1`,
},
{
heuristic: false,
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.HISTORY,
url: `http://mochi.test/${query}`,
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
});
await PlacesUtils.history.clear();
});
add_task(async function nonEmptySearch_url() {
await BrowserTestUtils.withNewTab("about:robots", async function () {
let query = "http://www.example.com/";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: query,
});
await UrlbarTestUtils.enterSearchMode(window);
// The heuristic result for a search that's a valid URL should be a search
// result, not a URL result.
await checkResults([
{
heuristic: true,
type: UrlbarUtils.RESULT_TYPE.SEARCH,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
searchParams: {
query,
engine: suggestionsEngine.name,
},
},
]);
await UrlbarTestUtils.exitSearchMode(window, { clickClose: true });
await UrlbarTestUtils.promisePopupClose(window);
});
});
async function checkResults(expectedResults) {
Assert.equal(
UrlbarTestUtils.getResultCount(window),
expectedResults.length,
"Check results count."
);
for (let i = 0; i < expectedResults.length; ++i) {
info(`Checking result at index ${i}`);
let expected = expectedResults[i];
let actual = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
// Check each property defined in the expected result against the property
// in the actual result.
for (let key of Object.keys(expected)) {
// For searchParams, remove undefined properties in the actual result so
// that the expected result doesn't need to include them.
if (key == "searchParams") {
let actualSearchParams = actual.searchParams;
for (let spKey of Object.keys(actualSearchParams)) {
if (actualSearchParams[spKey] === undefined) {
delete actualSearchParams[spKey];
}
}
}
Assert.deepEqual(
actual[key],
expected[key],
`${key} should match at result index ${i}.`
);
}
}
}