зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1626897 - Part 4 - Add tail suggestion tests. r=mak
Differential Revision: https://phabricator.services.mozilla.com/D74120
This commit is contained in:
Родитель
10d99a6ca5
Коммит
6abd224a1a
|
@ -275,8 +275,8 @@ add_task(async function test_onProviderResultsRequested() {
|
|||
|
||||
// Check the results.
|
||||
let expectedResults = [
|
||||
// The first result should be a search result returned by the
|
||||
// UnifiedComplete provider.
|
||||
// The first result should be a search result returned by
|
||||
// UrlbarProviderSearchSuggestions.
|
||||
{
|
||||
type: UrlbarUtils.RESULT_TYPE.SEARCH,
|
||||
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
|
||||
|
@ -286,6 +286,7 @@ add_task(async function test_onProviderResultsRequested() {
|
|||
query: "test",
|
||||
engine: "Test engine",
|
||||
suggestion: undefined,
|
||||
tail: undefined,
|
||||
keyword: undefined,
|
||||
isSearchHistory: false,
|
||||
icon: "",
|
||||
|
|
|
@ -208,6 +208,8 @@ function makeUrlbarResult(tokens, info) {
|
|||
action.params.searchSuggestion,
|
||||
UrlbarUtils.HIGHLIGHT.SUGGESTED,
|
||||
],
|
||||
// For test interoperabilty with UrlbarProviderSearchSuggestions.
|
||||
tail: undefined,
|
||||
keyword: [action.params.alias, UrlbarUtils.HIGHLIGHT.TYPED],
|
||||
query: [
|
||||
action.params.searchQuery.trim(),
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>engine-tail-suggestions.xml</ShortName>
|
||||
<Url type="application/x-suggestions+json"
|
||||
method="GET"
|
||||
template="http://localhost:9001/suggest?{searchTerms}"/>
|
||||
<Url type="text/html"
|
||||
method="GET"
|
||||
template="http://localhost:9001/search"
|
||||
rel="searchform"/>
|
||||
</SearchPlugin>
|
|
@ -130,6 +130,10 @@ class TestProvider extends UrlbarTestUtils.TestProvider {
|
|||
}
|
||||
}
|
||||
|
||||
function convertToUtf8(str) {
|
||||
return String.fromCharCode(...new TextEncoder().encode(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to clear the existing providers and register a basic provider
|
||||
* that returns only the results given.
|
||||
|
@ -221,6 +225,56 @@ async function addTestSuggestionsEngine(suggestionsFn = null) {
|
|||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a search engine that provides some tail suggestions by creating an
|
||||
* array that mimics Google's tail suggestion responses.
|
||||
*
|
||||
* @param {function} suggestionsFn
|
||||
* A function that returns an array that mimics Google's tail suggestion
|
||||
* responses. See bug 1626897.
|
||||
* NOTE: Consumers specifying suggestionsFn must include searchStr as a
|
||||
* part of the array returned by suggestionsFn.
|
||||
* @returns {nsISearchEngine} The new engine.
|
||||
*/
|
||||
async function addTestTailSuggestionsEngine(suggestionsFn = null) {
|
||||
// This port number should match the number in engine-tail-suggestions.xml.
|
||||
let server = makeTestServer(9001);
|
||||
server.registerPathHandler("/suggest", (req, resp) => {
|
||||
// URL query params are x-www-form-urlencoded, which converts spaces into
|
||||
// plus signs, so un-convert any plus signs back to spaces.
|
||||
let searchStr = decodeURIComponent(req.queryString.replace(/\+/g, " "));
|
||||
let suggestions = suggestionsFn
|
||||
? suggestionsFn(searchStr)
|
||||
: [
|
||||
"what time is it in t",
|
||||
["what is the time today texas"].concat(
|
||||
["toronto", "tunisia"].map(s => searchStr + s.slice(1))
|
||||
),
|
||||
[],
|
||||
{
|
||||
"google:irrelevantparameter": [],
|
||||
"google:suggestdetail": [{}].concat(
|
||||
["toronto", "tunisia"].map(s => ({
|
||||
mp: "… ",
|
||||
t: s,
|
||||
}))
|
||||
),
|
||||
},
|
||||
];
|
||||
let data = suggestions;
|
||||
let jsonString = JSON.stringify(data);
|
||||
// This script must be evaluated as UTF-8 for this to write out the bytes of
|
||||
// the string in UTF-8. If it's evaluated as Latin-1, the written bytes
|
||||
// will be the result of UTF-8-encoding the result-string *twice*, which
|
||||
// will break the "… " match prefixes.
|
||||
let stringOfUtf8Bytes = convertToUtf8(jsonString);
|
||||
resp.setHeader("Content-Type", "application/json", false);
|
||||
resp.write(stringOfUtf8Bytes);
|
||||
});
|
||||
let engine = await addTestEngine("engine-tail-suggestions.xml", server);
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a UrlbarResult for a search result.
|
||||
* @param {UrlbarQueryContext} queryContext
|
||||
|
@ -249,6 +303,7 @@ function makeSearchResult(
|
|||
queryContext,
|
||||
{
|
||||
suggestion,
|
||||
tail,
|
||||
engineName,
|
||||
alias,
|
||||
query,
|
||||
|
@ -274,6 +329,7 @@ function makeSearchResult(
|
|||
...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
|
||||
engine: [engineName, UrlbarUtils.HIGHLIGHT.TYPED],
|
||||
suggestion: [suggestion, UrlbarUtils.HIGHLIGHT.SUGGESTED],
|
||||
tail: [tail, UrlbarUtils.HIGHLIGHT.SUGGESTED],
|
||||
keyword: [alias, UrlbarUtils.HIGHLIGHT.TYPED],
|
||||
// Check against undefined so consumers can pass in the empty string.
|
||||
query: [
|
||||
|
|
|
@ -27,8 +27,8 @@ var previousSuggestionsFn;
|
|||
* @param {function} fn
|
||||
* A function that that a search string and returns an array of strings that
|
||||
* will be used as search suggestions.
|
||||
* Note: `fn` should return > 1 suggestion in most cases. Otherwise, you may
|
||||
* encounter unexceptede behaviour with UrlbarProviderSuggestion's
|
||||
* Note: `fn` should return > 0 suggestions in most cases. Otherwise, you may
|
||||
* encounter unexpected behaviour with UrlbarProviderSuggestion's
|
||||
* _lastLowResultsSearchSuggestion safeguard.
|
||||
*/
|
||||
function setSuggestionsFn(fn) {
|
||||
|
@ -1247,9 +1247,13 @@ add_task(async function avoid_url_suggestions() {
|
|||
await cleanUpSuggestions();
|
||||
});
|
||||
|
||||
add_task(async function restrict_suggestions_after_low_results() {
|
||||
add_task(async function restrict_suggestions_after_no_results() {
|
||||
// We don't fetch suggestions if a query with a length over
|
||||
// maxCharsForSearchSuggestions returns 0 results. We set it to 4 here to
|
||||
// avoid constructing a 100+ character string.
|
||||
Services.prefs.setIntPref("browser.urlbar.maxCharsForSearchSuggestions", 4);
|
||||
setSuggestionsFn(searchStr => {
|
||||
return [searchStr + "s"];
|
||||
return [];
|
||||
});
|
||||
|
||||
const query = "hello";
|
||||
|
@ -1258,10 +1262,6 @@ add_task(async function restrict_suggestions_after_low_results() {
|
|||
context,
|
||||
matches: [
|
||||
makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: `${query}s`,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -1270,12 +1270,13 @@ add_task(async function restrict_suggestions_after_low_results() {
|
|||
context,
|
||||
matches: [
|
||||
makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }),
|
||||
// Because the previous search only returned one suggestion, we will not
|
||||
// fetch suggestions for this query that is just a longer version of the
|
||||
// Because the previous search returned no suggestions, we will not fetch
|
||||
// suggestions for this query that is just a longer version of the
|
||||
// previous query.
|
||||
],
|
||||
});
|
||||
|
||||
Services.prefs.clearUserPref("browser.urlbar.maxCharsForSearchSuggestions");
|
||||
await cleanUpSuggestions();
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that tailed search engine suggestions are returned by
|
||||
* UrlbarProviderSearchSuggestions when available.
|
||||
*/
|
||||
|
||||
const { FormHistory } = ChromeUtils.import(
|
||||
"resource://gre/modules/FormHistory.jsm"
|
||||
);
|
||||
|
||||
const ENGINE_NAME = "engine-tail-suggestions.xml";
|
||||
const SUGGEST_PREF = "browser.urlbar.suggest.searches";
|
||||
const SUGGEST_ENABLED_PREF = "browser.search.suggest.enabled";
|
||||
const PRIVATE_SEARCH_PREF = "browser.search.separatePrivateDefault.ui.enabled";
|
||||
const TAIL_SUGGESTIONS_PREF = "browser.urlbar.richSuggestions.tail";
|
||||
|
||||
var suggestionsFn;
|
||||
var previousSuggestionsFn;
|
||||
|
||||
/**
|
||||
* Set the current suggestion funciton.
|
||||
* @param {function} fn
|
||||
* A function that that a search string and returns an array of strings that
|
||||
* will be used as search suggestions.
|
||||
* Note: `fn` should return > 1 suggestion in most cases. Otherwise, you may
|
||||
* encounter unexceptede behaviour with UrlbarProviderSuggestion's
|
||||
* _lastLowResultsSearchSuggestion safeguard.
|
||||
*/
|
||||
function setSuggestionsFn(fn) {
|
||||
previousSuggestionsFn = suggestionsFn;
|
||||
suggestionsFn = fn;
|
||||
}
|
||||
|
||||
async function cleanup() {
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
await PlacesUtils.history.clear();
|
||||
}
|
||||
|
||||
async function cleanUpSuggestions() {
|
||||
await cleanup();
|
||||
if (previousSuggestionsFn) {
|
||||
suggestionsFn = previousSuggestionsFn;
|
||||
previousSuggestionsFn = null;
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
Services.prefs.setCharPref(
|
||||
"browser.urlbar.matchBuckets",
|
||||
"general:5,suggestion:Infinity"
|
||||
);
|
||||
|
||||
let engine = await addTestTailSuggestionsEngine(searchStr => {
|
||||
return suggestionsFn(searchStr);
|
||||
});
|
||||
setSuggestionsFn(searchStr => {
|
||||
let suffixes = ["toronto", "tunisia"];
|
||||
return [
|
||||
"what time is it in t",
|
||||
suffixes.map(s => searchStr + s.slice(1)),
|
||||
[],
|
||||
{
|
||||
"google:irrelevantparameter": [],
|
||||
"google:suggestdetail": suffixes.map(s => ({
|
||||
mp: "… ",
|
||||
t: s,
|
||||
})),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
// Install the test engine.
|
||||
let oldDefaultEngine = await Services.search.getDefault();
|
||||
registerCleanupFunction(async () => {
|
||||
Services.search.setDefault(oldDefaultEngine);
|
||||
Services.prefs.clearUserPref(PRIVATE_SEARCH_PREF);
|
||||
Services.prefs.clearUserPref(TAIL_SUGGESTIONS_PREF);
|
||||
Services.prefs.clearUserPref(SUGGEST_ENABLED_PREF);
|
||||
});
|
||||
Services.search.setDefault(engine);
|
||||
Services.prefs.setBoolPref(PRIVATE_SEARCH_PREF, false);
|
||||
Services.prefs.setBoolPref(TAIL_SUGGESTIONS_PREF, true);
|
||||
Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true);
|
||||
|
||||
// We must make sure the FormHistoryStartup component is initialized.
|
||||
Cc["@mozilla.org/satchel/form-history-startup;1"]
|
||||
.getService(Ci.nsIObserver)
|
||||
.observe(null, "profile-after-change", null);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that non-tail suggestion providers still return results correctly when
|
||||
* the tailSuggestions pref is enabled.
|
||||
*/
|
||||
add_task(async function normal_suggestions_provider() {
|
||||
let engine = await addTestSuggestionsEngine();
|
||||
let tailEngine = await Services.search.getDefault();
|
||||
Services.search.setDefault(engine);
|
||||
|
||||
const query = "hello world";
|
||||
let context = createContext(query, { isPrivate: false });
|
||||
await check_results({
|
||||
context,
|
||||
matches: [
|
||||
makeSearchResult(context, {
|
||||
engineName: "engine-suggestions.xml",
|
||||
heuristic: true,
|
||||
}),
|
||||
makeSearchResult(context, {
|
||||
engineName: "engine-suggestions.xml",
|
||||
suggestion: query + " foo",
|
||||
}),
|
||||
makeSearchResult(context, {
|
||||
engineName: "engine-suggestions.xml",
|
||||
suggestion: query + " bar",
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
Services.search.setDefault(tailEngine);
|
||||
await cleanUpSuggestions();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests a suggestions provider that returns only tail suggestions.
|
||||
*/
|
||||
add_task(async function basic_tail() {
|
||||
const query = "what time is it in t";
|
||||
let context = createContext(query, { isPrivate: false });
|
||||
await check_results({
|
||||
context,
|
||||
matches: [
|
||||
makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: query + "oronto",
|
||||
tail: "… toronto",
|
||||
}),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: query + "unisia",
|
||||
tail: "… tunisia",
|
||||
}),
|
||||
],
|
||||
});
|
||||
await cleanUpSuggestions();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests a suggestions provider that returns both normal and tail suggestions.
|
||||
*/
|
||||
add_task(async function mixed_results() {
|
||||
// When normal suggestions are mixed with tail suggestions, they appear at the
|
||||
// correct position in the google:suggestdetail array as empty objects.
|
||||
setSuggestionsFn(searchStr => {
|
||||
let suffixes = ["toronto", "tunisia"];
|
||||
return [
|
||||
"what time is it in t",
|
||||
["what is the time today texas"].concat(
|
||||
suffixes.map(s => searchStr + s.slice(1))
|
||||
),
|
||||
[],
|
||||
{
|
||||
"google:irrelevantparameter": [],
|
||||
"google:suggestdetail": [{}].concat(
|
||||
suffixes.map(s => ({
|
||||
mp: "… ",
|
||||
t: s,
|
||||
}))
|
||||
),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const query = "what time is it in t";
|
||||
let context = createContext(query, { isPrivate: false });
|
||||
await check_results({
|
||||
context,
|
||||
matches: [
|
||||
makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: "what is the time today texas",
|
||||
tail: undefined,
|
||||
}),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: query + "oronto",
|
||||
tail: "… toronto",
|
||||
}),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: query + "unisia",
|
||||
tail: "… tunisia",
|
||||
}),
|
||||
],
|
||||
});
|
||||
await cleanUpSuggestions();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that tail suggestions are deduped if their full-text form is a dupe of
|
||||
* a local search suggestion.
|
||||
*/
|
||||
add_task(async function dedupe_local() {
|
||||
Services.prefs.setIntPref("browser.urlbar.maxHistoricalSearchSuggestions", 1);
|
||||
await updateSearchHistory("bump", "what time is it in toronto");
|
||||
|
||||
const query = "what time is it in t";
|
||||
let context = createContext(query, { isPrivate: false });
|
||||
await check_results({
|
||||
context,
|
||||
matches: [
|
||||
makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: query + "oronto",
|
||||
tail: undefined,
|
||||
}),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: query + "unisia",
|
||||
tail: "… tunisia",
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
Services.prefs.clearUserPref("browser.urlbar.maxHistoricalSearchSuggestions");
|
||||
await cleanUpSuggestions();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the correct number of suggestion results are displayed if
|
||||
* maxResults is limited, even when tail suggestions are returned.
|
||||
*/
|
||||
add_task(async function limit_results() {
|
||||
const query = "what time is it in t";
|
||||
let context = createContext(query, { isPrivate: false });
|
||||
context.maxResults = 2;
|
||||
await check_results({
|
||||
context,
|
||||
matches: [
|
||||
makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }),
|
||||
makeSearchResult(context, {
|
||||
engineName: ENGINE_NAME,
|
||||
suggestion: query + "oronto",
|
||||
tail: "… toronto",
|
||||
}),
|
||||
],
|
||||
});
|
||||
await cleanUpSuggestions();
|
||||
});
|
||||
|
||||
function updateSearchHistory(op, value) {
|
||||
return new Promise((resolve, reject) => {
|
||||
FormHistory.update(
|
||||
{ op, fieldname: "searchbar-history", value },
|
||||
{
|
||||
handleError(error) {
|
||||
do_throw("Error occurred updating form history: " + error);
|
||||
reject(error);
|
||||
},
|
||||
handleCompletion(reason) {
|
||||
if (reason) {
|
||||
reject(reason);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
|
@ -3,6 +3,7 @@ head = head.js
|
|||
firefox-appdir = browser
|
||||
support-files =
|
||||
data/engine-suggestions.xml
|
||||
data/engine-tail-suggestions.xml
|
||||
|
||||
[test_muxer.js]
|
||||
[test_providerOpenTabs.js]
|
||||
|
@ -14,6 +15,7 @@ support-files =
|
|||
[test_queryScorer.js]
|
||||
[test_search_suggestions.js]
|
||||
[test_search_suggestions_aliases.js]
|
||||
[test_search_suggestions_tail.js]
|
||||
[test_tokenizer.js]
|
||||
[test_UrlbarController_integration.js]
|
||||
[test_UrlbarController_telemetry.js]
|
||||
|
|
|
@ -19,7 +19,6 @@ function handleRequest(request, response) {
|
|||
}
|
||||
|
||||
function writeSuggestions(query, completions = []) {
|
||||
let result = [query, completions];
|
||||
let jsonString = JSON.stringify([query, completions]);
|
||||
|
||||
// This script must be evaluated as UTF-8 for this to write out the bytes of
|
||||
|
@ -31,6 +30,20 @@ function handleRequest(request, response) {
|
|||
response.write(stringOfUtf8Bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends `data` as suggestions directly. This is useful when testing rich
|
||||
* suggestions, which do not conform to the object shape sent by
|
||||
* writeSuggestions.
|
||||
*
|
||||
* @param {array} data
|
||||
*/
|
||||
function writeSuggestionsDirectly(data) {
|
||||
let jsonString = JSON.stringify(data);
|
||||
let stringOfUtf8Bytes = convertToUtf8(jsonString);
|
||||
response.setHeader("Content-Type", "application/json", false);
|
||||
response.write(stringOfUtf8Bytes);
|
||||
}
|
||||
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
|
||||
let q = request.method == "GET" ? query.q : undefined;
|
||||
|
@ -49,6 +62,70 @@ function handleRequest(request, response) {
|
|||
writeSuggestions(q, ["Mozilla", "modern", "mom"]);
|
||||
} else if (q && q.startsWith("I ❤️")) {
|
||||
writeSuggestions(q, ["I ❤️ Mozilla"]);
|
||||
} else if (q && q.startsWith("tailjunk ")) {
|
||||
writeSuggestionsDirectly([
|
||||
q,
|
||||
[q + " normal", q + " tail 1", q + " tail 2"],
|
||||
[],
|
||||
{
|
||||
"google:irrelevantparameter": [],
|
||||
"google:badformat": {
|
||||
"google:suggestdetail": [
|
||||
{},
|
||||
{ mp: "… ", t: "tail 1" },
|
||||
{ mp: "… ", t: "tail 2" },
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
} else if (q && q.startsWith("tailjunk few ")) {
|
||||
writeSuggestionsDirectly([
|
||||
q,
|
||||
[q + " normal", q + " tail 1", q + " tail 2"],
|
||||
[],
|
||||
{
|
||||
"google:irrelevantparameter": [],
|
||||
"google:badformat": {
|
||||
"google:suggestdetail": [{ mp: "… ", t: "tail 1" }],
|
||||
},
|
||||
},
|
||||
]);
|
||||
} else if (q && q.startsWith("tailalt ")) {
|
||||
writeSuggestionsDirectly([
|
||||
q,
|
||||
[q + " normal", q + " tail 1", q + " tail 2"],
|
||||
{
|
||||
"google:suggestdetail": [
|
||||
{},
|
||||
{ mp: "… ", t: "tail 1" },
|
||||
{ mp: "… ", t: "tail 2" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
} else if (q && q.startsWith("tail ")) {
|
||||
writeSuggestionsDirectly([
|
||||
q,
|
||||
[q + " normal", q + " tail 1", q + " tail 2"],
|
||||
[],
|
||||
{
|
||||
"google:irrelevantparameter": [],
|
||||
"google:suggestdetail": [
|
||||
{},
|
||||
{ mp: "… ", t: "tail 1" },
|
||||
{ mp: "… ", t: "tail 2" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
} else if (q && q.startsWith("richempty ")) {
|
||||
writeSuggestionsDirectly([
|
||||
q,
|
||||
[q + " normal", q + " tail 1", q + " tail 2"],
|
||||
[],
|
||||
{
|
||||
"google:irrelevantparameter": [],
|
||||
"google:suggestdetail": [],
|
||||
},
|
||||
]);
|
||||
} else if (q && q.startsWith("letter ")) {
|
||||
let letters = [];
|
||||
for (let charCode = "A".charCodeAt(); charCode <= "Z".charCodeAt(); charCode++) {
|
||||
|
|
|
@ -142,9 +142,9 @@ add_task(async function simple_remote_no_local_result() {
|
|||
Assert.equal(result.term, "mo");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 3);
|
||||
Assert.equal(result.remote[0], "Mozilla");
|
||||
Assert.equal(result.remote[1], "modern");
|
||||
Assert.equal(result.remote[2], "mom");
|
||||
Assert.equal(result.remote[0].value, "Mozilla");
|
||||
Assert.equal(result.remote[1].value, "modern");
|
||||
Assert.equal(result.remote[2].value, "mom");
|
||||
});
|
||||
|
||||
add_task(async function simple_remote_no_local_result_telemetry() {
|
||||
|
@ -173,9 +173,9 @@ add_task(async function simple_remote_no_local_result_alternative_type() {
|
|||
Assert.equal(result.term, "mo");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 3);
|
||||
Assert.equal(result.remote[0], "Mozilla");
|
||||
Assert.equal(result.remote[1], "modern");
|
||||
Assert.equal(result.remote[2], "mom");
|
||||
Assert.equal(result.remote[0].value, "Mozilla");
|
||||
Assert.equal(result.remote[1].value, "modern");
|
||||
Assert.equal(result.remote[2].value, "mom");
|
||||
});
|
||||
|
||||
add_task(async function remote_term_case_mismatch() {
|
||||
|
@ -183,7 +183,7 @@ add_task(async function remote_term_case_mismatch() {
|
|||
let result = await controller.fetch("Query Case Mismatch", false, getEngine);
|
||||
Assert.equal(result.term, "Query Case Mismatch");
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "Query Case Mismatch");
|
||||
Assert.equal(result.remote[0].value, "Query Case Mismatch");
|
||||
});
|
||||
|
||||
add_task(async function simple_local_no_remote_result() {
|
||||
|
@ -193,7 +193,7 @@ add_task(async function simple_local_no_remote_result() {
|
|||
let result = await controller.fetch("no remote", false, getEngine);
|
||||
Assert.equal(result.term, "no remote");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "no remote entries");
|
||||
Assert.equal(result.local[0].value, "no remote entries");
|
||||
Assert.equal(result.remote.length, 0);
|
||||
|
||||
await updateSearchHistory("remove", "no remote entries");
|
||||
|
@ -206,9 +206,9 @@ add_task(async function simple_non_ascii() {
|
|||
let result = await controller.fetch("I ❤️", false, getEngine);
|
||||
Assert.equal(result.term, "I ❤️");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "I ❤️ XUL");
|
||||
Assert.equal(result.local[0].value, "I ❤️ XUL");
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "I ❤️ Mozilla");
|
||||
Assert.equal(result.remote[0].value, "I ❤️ Mozilla");
|
||||
});
|
||||
|
||||
add_task(async function both_local_remote_result_dedupe() {
|
||||
|
@ -218,10 +218,10 @@ add_task(async function both_local_remote_result_dedupe() {
|
|||
let result = await controller.fetch("mo", false, getEngine);
|
||||
Assert.equal(result.term, "mo");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "Mozilla");
|
||||
Assert.equal(result.local[0].value, "Mozilla");
|
||||
Assert.equal(result.remote.length, 2);
|
||||
Assert.equal(result.remote[0], "modern");
|
||||
Assert.equal(result.remote[1], "mom");
|
||||
Assert.equal(result.remote[0].value, "modern");
|
||||
Assert.equal(result.remote[1].value, "mom");
|
||||
});
|
||||
|
||||
add_task(async function POST_both_local_remote_result_dedupe() {
|
||||
|
@ -229,10 +229,10 @@ add_task(async function POST_both_local_remote_result_dedupe() {
|
|||
let result = await controller.fetch("mo", false, postEngine);
|
||||
Assert.equal(result.term, "mo");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "Mozilla");
|
||||
Assert.equal(result.local[0].value, "Mozilla");
|
||||
Assert.equal(result.remote.length, 2);
|
||||
Assert.equal(result.remote[0], "modern");
|
||||
Assert.equal(result.remote[1], "mom");
|
||||
Assert.equal(result.remote[0].value, "modern");
|
||||
Assert.equal(result.remote[1].value, "mom");
|
||||
});
|
||||
|
||||
add_task(async function both_local_remote_result_dedupe2() {
|
||||
|
@ -242,10 +242,10 @@ add_task(async function both_local_remote_result_dedupe2() {
|
|||
let result = await controller.fetch("mo", false, getEngine);
|
||||
Assert.equal(result.term, "mo");
|
||||
Assert.equal(result.local.length, 2);
|
||||
Assert.equal(result.local[0], "mom");
|
||||
Assert.equal(result.local[1], "Mozilla");
|
||||
Assert.equal(result.local[0].value, "mom");
|
||||
Assert.equal(result.local[1].value, "Mozilla");
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "modern");
|
||||
Assert.equal(result.remote[0].value, "modern");
|
||||
});
|
||||
|
||||
add_task(async function both_local_remote_result_dedupe3() {
|
||||
|
@ -256,12 +256,97 @@ add_task(async function both_local_remote_result_dedupe3() {
|
|||
let result = await controller.fetch("mo", false, getEngine);
|
||||
Assert.equal(result.term, "mo");
|
||||
Assert.equal(result.local.length, 3);
|
||||
Assert.equal(result.local[0], "modern");
|
||||
Assert.equal(result.local[1], "mom");
|
||||
Assert.equal(result.local[2], "Mozilla");
|
||||
Assert.equal(result.local[0].value, "modern");
|
||||
Assert.equal(result.local[1].value, "mom");
|
||||
Assert.equal(result.local[2].value, "Mozilla");
|
||||
Assert.equal(result.remote.length, 0);
|
||||
});
|
||||
|
||||
add_task(async function valid_tail_results() {
|
||||
let controller = new SearchSuggestionController();
|
||||
let result = await controller.fetch("tail query", false, getEngine);
|
||||
Assert.equal(result.term, "tail query");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 3);
|
||||
Assert.equal(result.remote[0].value, "tail query normal");
|
||||
Assert.ok(!result.remote[0].matchPrefix);
|
||||
Assert.ok(!result.remote[0].tail);
|
||||
Assert.equal(result.remote[1].value, "tail query tail 1");
|
||||
Assert.equal(result.remote[1].matchPrefix, "… ");
|
||||
Assert.equal(result.remote[1].tail, "tail 1");
|
||||
Assert.equal(result.remote[2].value, "tail query tail 2");
|
||||
Assert.equal(result.remote[2].matchPrefix, "… ");
|
||||
Assert.equal(result.remote[2].tail, "tail 2");
|
||||
});
|
||||
|
||||
add_task(async function alt_tail_results() {
|
||||
let controller = new SearchSuggestionController();
|
||||
let result = await controller.fetch("tailalt query", false, getEngine);
|
||||
Assert.equal(result.term, "tailalt query");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 3);
|
||||
Assert.equal(result.remote[0].value, "tailalt query normal");
|
||||
Assert.ok(!result.remote[0].matchPrefix);
|
||||
Assert.ok(!result.remote[0].tail);
|
||||
Assert.equal(result.remote[1].value, "tailalt query tail 1");
|
||||
Assert.equal(result.remote[1].matchPrefix, "… ");
|
||||
Assert.equal(result.remote[1].tail, "tail 1");
|
||||
Assert.equal(result.remote[2].value, "tailalt query tail 2");
|
||||
Assert.equal(result.remote[2].matchPrefix, "… ");
|
||||
Assert.equal(result.remote[2].tail, "tail 2");
|
||||
});
|
||||
|
||||
add_task(async function invalid_tail_results() {
|
||||
let controller = new SearchSuggestionController();
|
||||
let result = await controller.fetch("tailjunk query", false, getEngine);
|
||||
Assert.equal(result.term, "tailjunk query");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 3);
|
||||
Assert.equal(result.remote[0].value, "tailjunk query normal");
|
||||
Assert.ok(!result.remote[0].matchPrefix);
|
||||
Assert.ok(!result.remote[0].tail);
|
||||
Assert.equal(result.remote[1].value, "tailjunk query tail 1");
|
||||
Assert.ok(!result.remote[1].matchPrefix);
|
||||
Assert.ok(!result.remote[1].tail);
|
||||
Assert.equal(result.remote[2].value, "tailjunk query tail 2");
|
||||
Assert.ok(!result.remote[2].matchPrefix);
|
||||
Assert.ok(!result.remote[2].tail);
|
||||
});
|
||||
|
||||
add_task(async function too_few_tail_results() {
|
||||
let controller = new SearchSuggestionController();
|
||||
let result = await controller.fetch("tailjunk few query", false, getEngine);
|
||||
Assert.equal(result.term, "tailjunk few query");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 3);
|
||||
Assert.equal(result.remote[0].value, "tailjunk few query normal");
|
||||
Assert.ok(!result.remote[0].matchPrefix);
|
||||
Assert.ok(!result.remote[0].tail);
|
||||
Assert.equal(result.remote[1].value, "tailjunk few query tail 1");
|
||||
Assert.ok(!result.remote[1].matchPrefix);
|
||||
Assert.ok(!result.remote[1].tail);
|
||||
Assert.equal(result.remote[2].value, "tailjunk few query tail 2");
|
||||
Assert.ok(!result.remote[2].matchPrefix);
|
||||
Assert.ok(!result.remote[2].tail);
|
||||
});
|
||||
|
||||
add_task(async function empty_rich_results() {
|
||||
let controller = new SearchSuggestionController();
|
||||
let result = await controller.fetch("richempty query", false, getEngine);
|
||||
Assert.equal(result.term, "richempty query");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 3);
|
||||
Assert.equal(result.remote[0].value, "richempty query normal");
|
||||
Assert.ok(!result.remote[0].matchPrefix);
|
||||
Assert.ok(!result.remote[0].tail);
|
||||
Assert.equal(result.remote[1].value, "richempty query tail 1");
|
||||
Assert.ok(!result.remote[1].matchPrefix);
|
||||
Assert.ok(!result.remote[1].tail);
|
||||
Assert.equal(result.remote[2].value, "richempty query tail 2");
|
||||
Assert.ok(!result.remote[2].matchPrefix);
|
||||
Assert.ok(!result.remote[2].tail);
|
||||
});
|
||||
|
||||
add_task(async function fetch_twice_in_a_row() {
|
||||
// Two entries since the first will match the first fetch but not the second.
|
||||
await updateSearchHistory("bump", "delay local");
|
||||
|
@ -277,9 +362,9 @@ add_task(async function fetch_twice_in_a_row() {
|
|||
let result = await resultPromise2;
|
||||
Assert.equal(result.term, "delayed ");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "delayed local");
|
||||
Assert.equal(result.local[0].value, "delayed local");
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "delayed ");
|
||||
Assert.equal(result.remote[0].value, "delayed ");
|
||||
});
|
||||
|
||||
add_task(async function fetch_twice_subset_reuse_formHistoryResult() {
|
||||
|
@ -292,10 +377,10 @@ add_task(async function fetch_twice_subset_reuse_formHistoryResult() {
|
|||
let result = await controller.fetch("delay", false, getEngine);
|
||||
Assert.equal(result.term, "delay");
|
||||
Assert.equal(result.local.length, 2);
|
||||
Assert.equal(result.local[0], "delay local");
|
||||
Assert.equal(result.local[1], "delayed local");
|
||||
Assert.equal(result.local[0].value, "delay local");
|
||||
Assert.equal(result.local[1].value, "delayed local");
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "delay");
|
||||
Assert.equal(result.remote[0].value, "delay");
|
||||
|
||||
// Remove the entry from the DB but it should remain in the cached formHistoryResult.
|
||||
await updateSearchHistory("remove", "delayed local");
|
||||
|
@ -303,9 +388,9 @@ add_task(async function fetch_twice_subset_reuse_formHistoryResult() {
|
|||
let result2 = await controller.fetch("delayed ", false, getEngine);
|
||||
Assert.equal(result2.term, "delayed ");
|
||||
Assert.equal(result2.local.length, 1);
|
||||
Assert.equal(result2.local[0], "delayed local");
|
||||
Assert.equal(result2.local[0].value, "delayed local");
|
||||
Assert.equal(result2.remote.length, 1);
|
||||
Assert.equal(result2.remote[0], "delayed ");
|
||||
Assert.equal(result2.remote[0].value, "delayed ");
|
||||
});
|
||||
|
||||
add_task(async function both_identical_with_more_than_max_results() {
|
||||
|
@ -329,14 +414,14 @@ add_task(async function both_identical_with_more_than_max_results() {
|
|||
Assert.equal(result.local.length, 7);
|
||||
for (let i = 0; i < controller.maxLocalResults; i++) {
|
||||
Assert.equal(
|
||||
result.local[i],
|
||||
result.local[i].value,
|
||||
"letter " + String.fromCharCode("A".charCodeAt() + i)
|
||||
);
|
||||
}
|
||||
Assert.equal(result.local.length + result.remote.length, 10);
|
||||
for (let i = 0; i < result.remote.length; i++) {
|
||||
Assert.equal(
|
||||
result.remote[i],
|
||||
result.remote[i].value,
|
||||
"letter " +
|
||||
String.fromCharCode("A".charCodeAt() + controller.maxLocalResults + i)
|
||||
);
|
||||
|
@ -352,7 +437,7 @@ add_task(async function noremote_maxLocal() {
|
|||
Assert.equal(result.local.length, 26);
|
||||
for (let i = 0; i < result.local.length; i++) {
|
||||
Assert.equal(
|
||||
result.local[i],
|
||||
result.local[i].value,
|
||||
"letter " + String.fromCharCode("A".charCodeAt() + i)
|
||||
);
|
||||
}
|
||||
|
@ -368,7 +453,7 @@ add_task(async function someremote_maxLocal() {
|
|||
Assert.equal(result.local.length, 2);
|
||||
for (let i = 0; i < result.local.length; i++) {
|
||||
Assert.equal(
|
||||
result.local[i],
|
||||
result.local[i].value,
|
||||
"letter " + String.fromCharCode("A".charCodeAt() + i)
|
||||
);
|
||||
}
|
||||
|
@ -376,7 +461,7 @@ add_task(async function someremote_maxLocal() {
|
|||
// "A" and "B" will have been de-duped, start at C for remote results
|
||||
for (let i = 0; i < result.remote.length; i++) {
|
||||
Assert.equal(
|
||||
result.remote[i],
|
||||
result.remote[i].value,
|
||||
"letter " + String.fromCharCode("C".charCodeAt() + i)
|
||||
);
|
||||
}
|
||||
|
@ -389,9 +474,9 @@ add_task(async function one_of_each() {
|
|||
let result = await controller.fetch("letter ", false, getEngine);
|
||||
Assert.equal(result.term, "letter ");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "letter A");
|
||||
Assert.equal(result.local[0].value, "letter A");
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "letter B");
|
||||
Assert.equal(result.remote[0].value, "letter B");
|
||||
});
|
||||
|
||||
add_task(async function local_result_returned_remote_result_disabled() {
|
||||
|
@ -404,7 +489,7 @@ add_task(async function local_result_returned_remote_result_disabled() {
|
|||
Assert.equal(result.local.length, 26);
|
||||
for (let i = 0; i < 26; i++) {
|
||||
Assert.equal(
|
||||
result.local[i],
|
||||
result.local[i].value,
|
||||
"letter " + String.fromCharCode("A".charCodeAt() + i)
|
||||
);
|
||||
}
|
||||
|
@ -423,7 +508,7 @@ add_task(
|
|||
Assert.equal(result.local.length, 26);
|
||||
for (let i = 0; i < 26; i++) {
|
||||
Assert.equal(
|
||||
result.local[i],
|
||||
result.local[i].value,
|
||||
"letter " + String.fromCharCode("A".charCodeAt() + i)
|
||||
);
|
||||
}
|
||||
|
@ -442,9 +527,9 @@ add_task(
|
|||
let result = await controller.fetch("letter ", false, getEngine);
|
||||
Assert.equal(result.term, "letter ");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "letter A");
|
||||
Assert.equal(result.local[0].value, "letter A");
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "letter B");
|
||||
Assert.equal(result.remote[0].value, "letter B");
|
||||
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
|
||||
}
|
||||
|
@ -459,7 +544,7 @@ add_task(async function one_local_zero_remote() {
|
|||
Assert.equal(result.local.length, 26);
|
||||
for (let i = 0; i < 26; i++) {
|
||||
Assert.equal(
|
||||
result.local[i],
|
||||
result.local[i].value,
|
||||
"letter " + String.fromCharCode("A".charCodeAt() + i)
|
||||
);
|
||||
}
|
||||
|
@ -474,7 +559,7 @@ add_task(async function zero_local_one_remote() {
|
|||
Assert.equal(result.term, "letter ");
|
||||
Assert.equal(result.local.length, 0);
|
||||
Assert.equal(result.remote.length, 1);
|
||||
Assert.equal(result.remote[0], "letter A");
|
||||
Assert.equal(result.remote[0].value, "letter A");
|
||||
});
|
||||
|
||||
add_task(async function stop_search() {
|
||||
|
@ -502,7 +587,7 @@ add_task(async function slow_timeout() {
|
|||
function check_result(result) {
|
||||
Assert.equal(result.term, "slow ");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "slow local result");
|
||||
Assert.equal(result.local[0].value, "slow local result");
|
||||
Assert.equal(result.remote.length, 0);
|
||||
}
|
||||
await updateSearchHistory("bump", "slow local result");
|
||||
|
@ -543,7 +628,7 @@ add_task(async function remote_term_mismatch() {
|
|||
let result = await controller.fetch("Query Mismatch", false, getEngine);
|
||||
Assert.equal(result.term, "Query Mismatch");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "Query Mismatch Entry");
|
||||
Assert.equal(result.local[0].value, "Query Mismatch Entry");
|
||||
Assert.equal(result.remote.length, 0);
|
||||
});
|
||||
|
||||
|
@ -554,7 +639,7 @@ add_task(async function http_404() {
|
|||
let result = await controller.fetch("HTTP 404", false, getEngine);
|
||||
Assert.equal(result.term, "HTTP 404");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "HTTP 404 Entry");
|
||||
Assert.equal(result.local[0].value, "HTTP 404 Entry");
|
||||
Assert.equal(result.remote.length, 0);
|
||||
});
|
||||
|
||||
|
@ -565,7 +650,7 @@ add_task(async function http_500() {
|
|||
let result = await controller.fetch("HTTP 500", false, getEngine);
|
||||
Assert.equal(result.term, "HTTP 500");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "HTTP 500 Entry");
|
||||
Assert.equal(result.local[0].value, "HTTP 500 Entry");
|
||||
Assert.equal(result.remote.length, 0);
|
||||
});
|
||||
|
||||
|
@ -580,7 +665,7 @@ add_task(async function unresolvable_server() {
|
|||
);
|
||||
Assert.equal(result.term, "Unresolvable Server");
|
||||
Assert.equal(result.local.length, 1);
|
||||
Assert.equal(result.local[0], "Unresolvable Server Entry");
|
||||
Assert.equal(result.local[0].value, "Unresolvable Server Entry");
|
||||
Assert.equal(result.remote.length, 0);
|
||||
});
|
||||
|
||||
|
|
|
@ -117,7 +117,11 @@ async function test_engine(engines, privateMode) {
|
|||
await new Promise(resolve => {
|
||||
controller = new SearchSuggestionController(result => {
|
||||
Assert.equal(result.local.length, 0, "Should have no local suggestions");
|
||||
Assert.equal(result.remote.length, 0, "Should have no remte suggestions");
|
||||
Assert.equal(
|
||||
result.remote.length,
|
||||
0,
|
||||
"Should have no remote suggestions"
|
||||
);
|
||||
if (result.term == "cookie") {
|
||||
resolve();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче