Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
});
let sandbox;
add_setup(async function () {
sandbox = lazy.sinon.createSandbox();
registerCleanupFunction(() => {
sandbox.restore();
});
});
add_task(async function test_muxer() {
Assert.throws(
() => UrlbarProvidersManager.registerMuxer(),
/invalid muxer/,
"Should throw with no arguments"
);
Assert.throws(
() => UrlbarProvidersManager.registerMuxer({}),
/invalid muxer/,
"Should throw with empty object"
);
Assert.throws(
() =>
UrlbarProvidersManager.registerMuxer({
name: "",
}),
/invalid muxer/,
"Should throw with empty name"
);
Assert.throws(
() =>
UrlbarProvidersManager.registerMuxer({
name: "test",
sort: "no",
}),
/invalid muxer/,
"Should throw with invalid sort"
);
let matches = [
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
UrlbarUtils.RESULT_SOURCE.TABS,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
];
let provider = registerBasicTestProvider(matches);
let context = createContext(undefined, { providers: [provider.name] });
let controller = UrlbarTestUtils.newMockController();
/**
* A test muxer.
*/
class TestMuxer extends UrlbarMuxer {
get name() {
return "TestMuxer";
}
sort(queryContext, unsortedResults) {
queryContext.results = [...unsortedResults].sort((a, b) => {
if (b.source == UrlbarUtils.RESULT_SOURCE.TABS) {
return -1;
}
if (b.source == UrlbarUtils.RESULT_SOURCE.BOOKMARKS) {
return 1;
}
return a.source == UrlbarUtils.RESULT_SOURCE.BOOKMARKS ? -1 : 1;
});
}
}
let muxer = new TestMuxer();
UrlbarProvidersManager.registerMuxer(muxer);
context.muxer = "TestMuxer";
info("Check results, the order should be: bookmark, history, tab");
await UrlbarProvidersManager.startQuery(context, controller);
Assert.deepEqual(context.results, [matches[1], matches[2], matches[0]]);
// Sanity check, should not throw.
UrlbarProvidersManager.unregisterMuxer(muxer);
UrlbarProvidersManager.unregisterMuxer("TestMuxer"); // no-op.
});
add_task(async function test_preselectedHeuristic_singleProvider() {
let matches = [
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
];
matches[1].heuristic = true;
let provider = registerBasicTestProvider(matches);
let context = createContext(undefined, {
providers: [provider.name],
});
let controller = UrlbarTestUtils.newMockController();
info("Check results, the order should be: b (heuristic), a, c");
await UrlbarProvidersManager.startQuery(context, controller);
Assert.deepEqual(context.results, [matches[1], matches[0], matches[2]]);
});
add_task(async function test_preselectedHeuristic_multiProviders() {
let matches1 = [
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
];
let matches2 = [
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
];
matches2[1].heuristic = true;
let provider1 = registerBasicTestProvider(matches1);
let provider2 = registerBasicTestProvider(matches2);
let context = createContext(undefined, {
providers: [provider1.name, provider2.name],
});
let controller = UrlbarTestUtils.newMockController();
info("Check results, the order should be: e (heuristic), a, b, c, d, f");
await UrlbarProvidersManager.startQuery(context, controller);
Assert.deepEqual(context.results, [
matches2[1],
...matches1,
matches2[0],
matches2[2],
]);
});
add_task(async function test_suggestions() {
Services.prefs.setIntPref("browser.urlbar.maxHistoricalSearchSuggestions", 1);
let matches = [
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.HISTORY,
{
engine: "mozSearch",
query: "moz",
suggestion: "mozzarella",
lowerCaseSuggestion: "mozzarella",
}
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{
engine: "mozSearch",
query: "moz",
suggestion: "mozilla",
lowerCaseSuggestion: "mozilla",
}
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{
engine: "mozSearch",
query: "moz",
providesSearchMode: true,
keyword: "@moz",
}
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
];
let provider = registerBasicTestProvider(matches);
let context = createContext(undefined, {
providers: [provider.name],
});
let controller = UrlbarTestUtils.newMockController();
info("Check results, the order should be: mozzarella, moz, a, b, @moz, c");
await UrlbarProvidersManager.startQuery(context, controller);
Assert.deepEqual(context.results, [
matches[2],
matches[3],
matches[0],
matches[1],
matches[4],
matches[5],
]);
Services.prefs.clearUserPref("browser.urlbar.maxHistoricalSearchSuggestions");
});
add_task(async function test_deduplicate_for_unitConversion() {
const searchSuggestion = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{
engine: "Google",
query: "10cm to m",
suggestion: "= 0.1 meters",
}
);
const searchProvider = registerBasicTestProvider(
[searchSuggestion],
null,
UrlbarUtils.PROVIDER_TYPE.PROFILE
);
const unitConversionSuggestion = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.DYNAMIC,
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
{
dynamicType: "unitConversion",
output: "0.1 m",
input: "10cm to m",
}
);
unitConversionSuggestion.suggestedIndex = 1;
const unitConversion = registerBasicTestProvider(
[unitConversionSuggestion],
null,
UrlbarUtils.PROVIDER_TYPE.PROFILE,
"UnitConversion"
);
const context = createContext(undefined, {
providers: [searchProvider.name, unitConversion.name],
});
const controller = UrlbarTestUtils.newMockController();
await UrlbarProvidersManager.startQuery(context, controller);
Assert.deepEqual(context.results, [unitConversionSuggestion]);
});
// These results are used in the badHeuristicGroups tests below. The order of
// the results in the array isn't important because they all get added at the
// same time. It's the resultGroups in each test that is important.
const BAD_HEURISTIC_RESULTS = [
// heuristic
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ heuristic: true }
),
// heuristic
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ heuristic: true }
),
// non-heuristic
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
// non-heuristic
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
];
const BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC = BAD_HEURISTIC_RESULTS[0];
const BAD_HEURISTIC_RESULTS_GENERAL = [
BAD_HEURISTIC_RESULTS[2],
BAD_HEURISTIC_RESULTS[3],
];
add_task(async function test_badHeuristicGroups_multiple_0() {
await doBadHeuristicGroupsTest(
[
// 2 heuristics with child groups
{
maxResultCount: 2,
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicGroups_multiple_1() {
await doBadHeuristicGroupsTest(
[
// infinite heuristics with child groups
{
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicGroups_multiple_2() {
await doBadHeuristicGroupsTest(
[
// 2 heuristics
{
maxResultCount: 2,
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicGroups_multiple_3() {
await doBadHeuristicGroupsTest(
[
// infinite heuristics
{
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicGroups_multiple_4() {
await doBadHeuristicGroupsTest(
[
// 1 heuristic with child groups
{
maxResultCount: 1,
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// 1 heuristic with child groups
{
maxResultCount: 1,
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicGroups_multiple_5() {
await doBadHeuristicGroupsTest(
[
// infinite heuristics with child groups
{
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// infinite heuristics with child groups
{
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicGroups_multiple_6() {
await doBadHeuristicGroupsTest(
[
// 1 heuristic
{
maxResultCount: 1,
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// 1 heuristic
{
maxResultCount: 1,
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicGroups_multiple_7() {
await doBadHeuristicGroupsTest(
[
// infinite heuristics
{
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
// infinite general
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// infinite heuristics
{
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
],
[BAD_HEURISTIC_RESULTS_FIRST_HEURISTIC, ...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicsGroups_notFirst_0() {
await doBadHeuristicGroupsTest(
[
// infinite general first
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// 1 heuristic with child groups second
{
maxResultCount: 1,
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
],
[...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicsGroups_notFirst_1() {
await doBadHeuristicGroupsTest(
[
// infinite general first
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// infinite heuristics with child groups second
{
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
],
[...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicsGroups_notFirst_2() {
await doBadHeuristicGroupsTest(
[
// infinite general first
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// 1 heuristic second
{
maxResultCount: 1,
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
],
[...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicsGroups_notFirst_3() {
await doBadHeuristicGroupsTest(
[
// infinite general first
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// infinite heuristics second
{
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
],
[...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
add_task(async function test_badHeuristicsGroups_notFirst_4() {
await doBadHeuristicGroupsTest(
[
// 1 general first
{
maxResultCount: 1,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
// infinite heuristics second
{
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
},
// infinite general third
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
[...BAD_HEURISTIC_RESULTS_GENERAL]
);
});
/**
* Sets the resultGroups pref, performs a search, and then checks the results.
* Regardless of the groups, the muxer should include at most one heuristic in
* its results and it should always be the first result.
*
* @param {Array} resultGroups
* The result groups.
* @param {Array} expectedResults
* The expected results.
*/
async function doBadHeuristicGroupsTest(resultGroups, expectedResults) {
sandbox.stub(UrlbarPrefs, "resultGroups").get(() => {
return { children: resultGroups };
});
let provider = registerBasicTestProvider(BAD_HEURISTIC_RESULTS);
let context = createContext("foo", { providers: [provider.name] });
let controller = UrlbarTestUtils.newMockController();
await UrlbarProvidersManager.startQuery(context, controller);
Assert.deepEqual(context.results, expectedResults);
sandbox.restore();
}
// When `maxRichResults` is positive and taken up by suggested-index result(s),
// both the heuristic and suggested-index results should be included because we
// (a) make room for the heuristic and (b) assume all suggested-index results
// should be included even if it means exceeding `maxRichResults`. The specified
// `maxRichResults` span will be exceeded in this case.
add_task(async function roomForHeuristic_suggestedIndex() {
let results = [
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ heuristic: true }
),
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ suggestedIndex: 1 }
),
];
UrlbarPrefs.set("maxRichResults", 1);
let provider = registerBasicTestProvider(results);
let context = createContext(undefined, { providers: [provider.name] });
await check_results({
context,
matches: results,
});
UrlbarPrefs.clear("maxRichResults");
});
// When `maxRichResults` is positive but less than the heuristic's result span,
// the heuristic should be included because we make room for it even if it means
// exceeding `maxRichResults`. The specified `maxRichResults` span will be
// exceeded in this case.
add_task(async function roomForHeuristic_largeResultSpan() {
let results = [
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ heuristic: true, resultSpan: 2 }
),
];
UrlbarPrefs.set("maxRichResults", 1);
let provider = registerBasicTestProvider(results);
let context = createContext(undefined, { providers: [provider.name] });
await check_results({
context,
matches: results,
});
UrlbarPrefs.clear("maxRichResults");
});
// When `maxRichResults` is zero and there are no suggested-index results, the
// heuristic should not be included.
add_task(async function roomForHeuristic_maxRichResultsZero() {
let results = [
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ heuristic: true }
),
];
UrlbarPrefs.set("maxRichResults", 0);
let provider = registerBasicTestProvider(results);
let context = createContext(undefined, { providers: [provider.name] });
await check_results({
context,
matches: [],
});
UrlbarPrefs.clear("maxRichResults");
});
// When `maxRichResults` is zero and suggested-index results are present,
// neither the heuristic nor the suggested-index results should be included.
add_task(async function roomForHeuristic_maxRichResultsZero_suggestedIndex() {
let results = [
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ heuristic: true }
),
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
),
{ suggestedIndex: 1 }
),
];
UrlbarPrefs.set("maxRichResults", 0);
let provider = registerBasicTestProvider(results);
let context = createContext(undefined, { providers: [provider.name] });
await check_results({
context,
matches: [],
});
UrlbarPrefs.clear("maxRichResults");
});