Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
// Tests results with `suggestedIndex` and `isSuggestedIndexRelativeToGroup`.
"use strict";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
});
const MAX_RESULTS = 10;
// Default result groups used in the tests below.
const RESULT_GROUPS = {
children: [
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
flexChildren: true,
children: [
{
flex: 1,
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
},
{
flex: 1,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
{
flex: 1,
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
},
],
},
],
};
let sandbox;
add_setup(async () => {
sandbox = lazy.sinon.createSandbox();
registerCleanupFunction(() => {
sandbox.restore();
});
});
add_task(async function test() {
// Create the default non-suggestedIndex results we'll use for tests that
// don't specify `otherResults`.
let basicResults = [
...makeHistoryResults(),
...makeFormHistoryResults(),
...makeRemoteSuggestionResults(),
];
// Test cases follow. Each object in `tests` has the following properties:
//
// * {string} desc
// * {object} suggestedIndexResults
// Describes the suggestedIndex results the test provider should return.
// Properties:
// * {number} suggestedIndex
// * {UrlbarUtils.RESULT_GROUP} group
// This will force the result to have the given group.
// * {array} expected
// Describes the expected results the muxer should return, i.e., the search
// results. Each object in the array describes a slice of expected results.
// The size of the slice is defined by the `count` property.
// * {UrlbarUtils.RESULT_GROUP} group
// The expected group of the results in the slice.
// * {number} count
// The number of results in the slice.
// * {number} [offset]
// Can be used to offset the starting index of the slice in the results.
// * {array} [otherResults]
// An array of results besides the group-relative suggestedIndex results
// that the provider should return. If not specified `basicResults` is used.
// * {array} [resultGroups]
// The result groups to use. If not specified `RESULT_GROUPS` is used.
// * {number} [maxRichResults]
// The `maxRichResults` pref will be set to this value. If not specified
// `MAX_RESULTS` is used.
let tests = [
{
desc: "First result in GENERAL",
suggestedIndexResults: [
{
suggestedIndex: 0,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 4,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
suggestedIndex: 0,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 2,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
// The muxer will remove the first 4 remote suggestions because they
// dupe the earlier form history.
offset: 4,
count: 3,
},
],
},
{
desc: "Last result in GENERAL",
suggestedIndexResults: [
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 4,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 2,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
suggestedIndex: -1,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
// The muxer will remove the first 4 remote suggestions because they
// dupe the earlier form history.
offset: 4,
count: 3,
},
],
},
{
desc: "First result in GENERAL_PARENT",
suggestedIndexResults: [
{
suggestedIndex: 0,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
suggestedIndex: 0,
},
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
// The muxer will remove the first 3 remote suggestions because they
// dupe the earlier form history.
offset: 3,
count: 3,
},
],
},
{
desc: "Last result in GENERAL_PARENT",
suggestedIndexResults: [
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
// The muxer will remove the first 3 remote suggestions because they
// dupe the earlier form history.
offset: 3,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
suggestedIndex: -1,
},
],
},
{
desc: "First and last results in GENERAL",
suggestedIndexResults: [
{
suggestedIndex: 0,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 4,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
suggestedIndex: 0,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 1,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
suggestedIndex: -1,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
// The muxer will remove the first 4 remote suggestions because they
// dupe the earlier form history.
offset: 4,
count: 3,
},
],
},
{
desc: "First and last results in GENERAL_PARENT",
suggestedIndexResults: [
{
suggestedIndex: 0,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
},
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
suggestedIndex: 0,
},
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
// The muxer will remove the first 3 remote suggestions because they
// dupe the earlier form history.
offset: 3,
count: 2,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
suggestedIndex: -1,
},
],
},
{
desc: "First result in GENERAL_PARENT, first result in GENERAL",
suggestedIndexResults: [
{
suggestedIndex: 0,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
},
{
suggestedIndex: 0,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
suggestedIndex: 0,
},
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 3,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
suggestedIndex: 0,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 2,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
// The muxer will remove the first 3 remote suggestions because they
// dupe the earlier form history.
offset: 3,
count: 3,
},
],
},
{
desc: "Results in sibling group, no other results in same group",
otherResults: makeFormHistoryResults(),
suggestedIndexResults: [
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.GENERAL,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 9,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
suggestedIndex: -1,
},
],
},
{
desc: "Results in sibling group, no other results in same group, has child group",
resultGroups: {
flexChildren: true,
children: [
{
flex: 2,
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
},
{
flex: 1,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
children: [{ group: UrlbarUtils.RESULT_GROUP.GENERAL }],
},
],
},
otherResults: makeRemoteSuggestionResults(),
suggestedIndexResults: [
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
count: 9,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
suggestedIndex: -1,
},
],
},
{
desc: "Complex group nesting with global suggestedIndex with resultSpan",
resultGroups: {
children: [
{
maxResultCount: 1,
children: [{ group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST }],
},
{
flexChildren: true,
children: [
{
flex: 2,
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
},
{
flex: 1,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
children: [{ group: UrlbarUtils.RESULT_GROUP.GENERAL }],
},
],
},
],
},
otherResults: [
// heuristic
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{
engine: "test",
suggestion: "foo",
lowerCaseSuggestion: "foo",
}
),
{
heuristic: true,
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
}
),
// global suggestedIndex with resultSpan = 2
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{
engine: "test",
}
),
{
suggestedIndex: 1,
resultSpan: 2,
}
),
// remote suggestions
...makeRemoteSuggestionResults(),
],
suggestedIndexResults: [
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.HEURISTIC_TEST,
count: 1,
},
{
group: UrlbarUtils.RESULT_GROUP.SUGGESTED_INDEX,
suggestedIndex: 1,
resultSpan: 2,
count: 1,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
count: 6,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL_PARENT,
suggestedIndex: -1,
},
],
},
{
desc: "Last result in REMOTE_SUGGESTION, maxRichResults too small to add any REMOTE_SUGGESTION",
maxRichResults: 2,
suggestedIndexResults: [
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 1,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 1,
},
// The suggestedIndex result should not be added.
],
},
{
desc: "Last result in REMOTE_SUGGESTION, maxRichResults just big enough to show one REMOTE_SUGGESTION",
maxRichResults: 3,
suggestedIndexResults: [
{
suggestedIndex: -1,
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
},
],
expected: [
{
group: UrlbarUtils.RESULT_GROUP.FORM_HISTORY,
count: 1,
},
{
group: UrlbarUtils.RESULT_GROUP.GENERAL,
count: 1,
},
{
group: UrlbarUtils.RESULT_GROUP.REMOTE_SUGGESTION,
suggestedIndex: -1,
},
],
},
];
let controller = UrlbarTestUtils.newMockController();
for (let {
desc,
suggestedIndexResults,
expected,
resultGroups,
otherResults,
maxRichResults = MAX_RESULTS,
} of tests) {
info(`Running test: ${desc}`);
setResultGroups(resultGroups || RESULT_GROUPS);
UrlbarPrefs.set("maxRichResults", maxRichResults);
// Make the array of all results and do a search.
let results = (otherResults || basicResults).concat(
makeSuggestedIndexResults(suggestedIndexResults)
);
let provider = registerBasicTestProvider(results);
let context = createContext(undefined, { providers: [provider.name] });
await UrlbarProvidersManager.startQuery(context, controller);
// Make the list of expected results.
let expectedResults = [];
for (let { group, offset, count, suggestedIndex } of expected) {
// Find the index in `results` of the expected result.
let index = results.findIndex(
r =>
UrlbarUtils.getResultGroup(r) == group &&
r.suggestedIndex === suggestedIndex
);
Assert.notEqual(
index,
-1,
"Sanity check: Expected result is in `results`"
);
if (offset) {
index += offset;
}
// Extract the expected number of results from `results` and append them
// to the expected results array.
count = count || 1;
expectedResults.push(...results.slice(index, index + count));
}
Assert.deepEqual(context.results, expectedResults);
UrlbarProvidersManager.unregisterProvider(provider);
}
});
function makeHistoryResults(count = MAX_RESULTS) {
let results = [];
for (let i = 0; i < count; i++) {
results.push(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
{ url: "http://example.com/" + i }
)
);
}
return results;
}
function makeRemoteSuggestionResults(count = MAX_RESULTS) {
let results = [];
for (let i = 0; i < count; i++) {
results.push(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{
engine: "test",
query: "test",
suggestion: "test " + i,
lowerCaseSuggestion: "test " + i,
}
)
);
}
return results;
}
function makeFormHistoryResults(count = MAX_RESULTS) {
let results = [];
for (let i = 0; i < count; i++) {
results.push(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.HISTORY,
{
engine: "test",
suggestion: "test " + i,
lowerCaseSuggestion: "test " + i,
}
)
);
}
return results;
}
function makeSuggestedIndexResults(objects) {
return objects.map(({ suggestedIndex, group }) =>
Object.assign(
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
{
url: "http://example.com/si " + suggestedIndex,
}
),
{
group,
suggestedIndex,
isSuggestedIndexRelativeToGroup: true,
}
)
);
}
function setResultGroups(resultGroups) {
sandbox.restore();
if (resultGroups) {
sandbox.stub(UrlbarPrefs, "resultGroups").get(() => resultGroups);
}
}