forked from mirrors/gecko-dev
Note that this patch also replaces legacy VK_* with KEY_*, and replaces synthesizeKey() for inputting some characters with sendString() because it's better and clearer what it does and it sets shiftKey state properly. MozReview-Commit-ID: De4enbjux3T --HG-- extra : rebase_source : 2296b84bff8e22f01eeb48cd8614fac5db11136a
240 lines
8.7 KiB
JavaScript
240 lines
8.7 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
// See browser/components/search/test/browser_*_behavior.js for tests of actual
|
|
// searches.
|
|
|
|
|
|
const ENGINE_NO_LOGO = {
|
|
name: "searchEngineNoLogo.xml",
|
|
numLogos: 0,
|
|
};
|
|
|
|
const ENGINE_FAVICON = {
|
|
name: "searchEngineFavicon.xml",
|
|
logoPrefix1x: "data:image/png;base64,AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAATCwAAEwsA",
|
|
numLogos: 1,
|
|
};
|
|
ENGINE_FAVICON.logoPrefix2x = ENGINE_FAVICON.logoPrefix1x;
|
|
|
|
const ENGINE_1X_LOGO = {
|
|
name: "searchEngine1xLogo.xml",
|
|
logoPrefix1x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAIAAABn3KYmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADEw",
|
|
numLogos: 1,
|
|
};
|
|
ENGINE_1X_LOGO.logoPrefix2x = ENGINE_1X_LOGO.logoPrefix1x;
|
|
|
|
const ENGINE_2X_LOGO = {
|
|
name: "searchEngine2xLogo.xml",
|
|
logoPrefix2x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAIAAADJ8nfCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADMU",
|
|
numLogos: 1,
|
|
};
|
|
ENGINE_2X_LOGO.logoPrefix1x = ENGINE_2X_LOGO.logoPrefix2x;
|
|
|
|
const ENGINE_1X_2X_LOGO = {
|
|
name: "searchEngine1x2xLogo.xml",
|
|
logoPrefix1x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAIAAABn3KYmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADIG",
|
|
logoPrefix2x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAIAAADJ8nfCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADMo",
|
|
numLogos: 2,
|
|
};
|
|
|
|
const ENGINE_SUGGESTIONS = {
|
|
name: "searchSuggestionEngine.xml",
|
|
numLogos: 0,
|
|
};
|
|
|
|
// The test has an expected search event queue and a search event listener.
|
|
// Search events that are expected to happen are added to the queue, and the
|
|
// listener consumes the queue and ensures that each event it receives is at
|
|
// the head of the queue.
|
|
let gExpectedSearchEventQueue = [];
|
|
let gExpectedSearchEventResolver = null;
|
|
|
|
let gNewEngines = [];
|
|
|
|
add_task(async function() {
|
|
let oldCurrentEngine = Services.search.currentEngine;
|
|
|
|
await addNewTabPageTab();
|
|
|
|
// The tab is removed at the end of the test, so there's no need to remove
|
|
// this listener at the end of the test.
|
|
info("Adding search event listener");
|
|
await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
|
|
const SERVICE_EVENT_NAME = "ContentSearchService";
|
|
content.addEventListener(SERVICE_EVENT_NAME, function(event) {
|
|
sendAsyncMessage("test:search-event", { eventType: event.detail.type });
|
|
});
|
|
});
|
|
|
|
let mm = gBrowser.selectedBrowser.messageManager;
|
|
mm.addMessageListener("test:search-event", function(message) {
|
|
let eventType = message.data.eventType;
|
|
if (!gExpectedSearchEventResolver) {
|
|
ok(false, "Got search event " + eventType + " with no promise assigned");
|
|
}
|
|
|
|
let expectedEventType = gExpectedSearchEventQueue.shift();
|
|
is(eventType, expectedEventType, "Got expected search event " + expectedEventType);
|
|
if (!gExpectedSearchEventQueue.length) {
|
|
gExpectedSearchEventResolver();
|
|
gExpectedSearchEventResolver = null;
|
|
}
|
|
});
|
|
|
|
// Add the engine without any logos and switch to it.
|
|
let noLogoEngine = await promiseNewSearchEngine(ENGINE_NO_LOGO);
|
|
let searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
|
|
Services.search.currentEngine = noLogoEngine;
|
|
await searchEventsPromise;
|
|
await checkCurrentEngine(ENGINE_NO_LOGO);
|
|
|
|
// Add the engine with favicon and switch to it.
|
|
let faviconEngine = await promiseNewSearchEngine(ENGINE_FAVICON);
|
|
searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
|
|
Services.search.currentEngine = faviconEngine;
|
|
await searchEventsPromise;
|
|
await checkCurrentEngine(ENGINE_FAVICON);
|
|
|
|
// Add the engine with a 1x-DPI logo and switch to it.
|
|
let logo1xEngine = await promiseNewSearchEngine(ENGINE_1X_LOGO);
|
|
searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
|
|
Services.search.currentEngine = logo1xEngine;
|
|
await searchEventsPromise;
|
|
await checkCurrentEngine(ENGINE_1X_LOGO);
|
|
|
|
// Add the engine with a 2x-DPI logo and switch to it.
|
|
let logo2xEngine = await promiseNewSearchEngine(ENGINE_2X_LOGO);
|
|
searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
|
|
Services.search.currentEngine = logo2xEngine;
|
|
await searchEventsPromise;
|
|
await checkCurrentEngine(ENGINE_2X_LOGO);
|
|
|
|
// Add the engine with 1x- and 2x-DPI logos and switch to it.
|
|
let logo1x2xEngine = await promiseNewSearchEngine(ENGINE_1X_2X_LOGO);
|
|
searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
|
|
Services.search.currentEngine = logo1x2xEngine;
|
|
await searchEventsPromise;
|
|
await checkCurrentEngine(ENGINE_1X_2X_LOGO);
|
|
|
|
// Add the engine that provides search suggestions and switch to it.
|
|
let suggestionEngine = await promiseNewSearchEngine(ENGINE_SUGGESTIONS);
|
|
searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
|
|
Services.search.currentEngine = suggestionEngine;
|
|
await searchEventsPromise;
|
|
await checkCurrentEngine(ENGINE_SUGGESTIONS);
|
|
|
|
// Type an X in the search input. This is only a smoke test. See
|
|
// browser_searchSuggestionUI.js for comprehensive content search suggestion
|
|
// UI tests.
|
|
let suggestionsOpenPromise = new Promise(resolve => {
|
|
mm.addMessageListener("test:newtab-suggestions-open", function onResponse(message) {
|
|
mm.removeMessageListener("test:newtab-suggestions-open", onResponse);
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
|
|
let table = content.document.getElementById("searchSuggestionTable");
|
|
|
|
let input = content.document.getElementById("newtab-search-text");
|
|
input.focus();
|
|
|
|
info("Waiting for suggestions table to open");
|
|
let observer = new content.MutationObserver(() => {
|
|
if (input.getAttribute("aria-expanded") == "true") {
|
|
observer.disconnect();
|
|
Assert.ok(!table.hidden, "Search suggestion table unhidden");
|
|
sendAsyncMessage("test:newtab-suggestions-open", {});
|
|
}
|
|
});
|
|
observer.observe(input, {
|
|
attributes: true,
|
|
attributeFilter: ["aria-expanded"],
|
|
});
|
|
});
|
|
|
|
let suggestionsPromise = promiseSearchEvents(["Suggestions"]);
|
|
|
|
EventUtils.sendString("x");
|
|
|
|
// Wait for the search suggestions to become visible and for the Suggestions
|
|
// message.
|
|
await suggestionsOpenPromise;
|
|
await suggestionsPromise;
|
|
|
|
// Empty the search input, causing the suggestions to be hidden.
|
|
EventUtils.synthesizeKey("a", {accelKey: true});
|
|
EventUtils.synthesizeKey("KEY_Delete");
|
|
|
|
await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
|
|
Assert.ok(content.document.getElementById("searchSuggestionTable").hidden,
|
|
"Search suggestion table hidden");
|
|
});
|
|
|
|
// Done. Revert the current engine and remove the new engines.
|
|
searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
|
|
Services.search.currentEngine = oldCurrentEngine;
|
|
await searchEventsPromise;
|
|
|
|
let events = Array(gNewEngines.length).fill("CurrentState", 0, gNewEngines.length);
|
|
searchEventsPromise = promiseSearchEvents(events);
|
|
|
|
for (let engine of gNewEngines) {
|
|
Services.search.removeEngine(engine);
|
|
}
|
|
await searchEventsPromise;
|
|
});
|
|
|
|
function promiseSearchEvents(events) {
|
|
info("Expecting search events: " + events);
|
|
return new Promise(resolve => {
|
|
gExpectedSearchEventQueue.push(...events);
|
|
gExpectedSearchEventResolver = resolve;
|
|
});
|
|
}
|
|
|
|
function promiseNewSearchEngine({name: basename, numLogos}) {
|
|
info("Waiting for engine to be added: " + basename);
|
|
|
|
// Wait for the search events triggered by adding the new engine.
|
|
// engine-added engine-loaded
|
|
let expectedSearchEvents = ["CurrentState", "CurrentState"];
|
|
// engine-changed for each of the logos
|
|
for (let i = 0; i < numLogos; i++) {
|
|
expectedSearchEvents.push("CurrentState");
|
|
}
|
|
let eventPromise = promiseSearchEvents(expectedSearchEvents);
|
|
|
|
// Wait for addEngine().
|
|
let addEnginePromise = new Promise((resolve, reject) => {
|
|
let url = getRootDirectory(gTestPath) + basename;
|
|
Services.search.addEngine(url, null, "", false, {
|
|
onSuccess(engine) {
|
|
info("Search engine added: " + basename);
|
|
gNewEngines.push(engine);
|
|
resolve(engine);
|
|
},
|
|
onError(errCode) {
|
|
ok(false, "addEngine failed with error code " + errCode);
|
|
reject();
|
|
},
|
|
});
|
|
});
|
|
|
|
return Promise.all([addEnginePromise, eventPromise]).then(([newEngine, _]) => {
|
|
return newEngine;
|
|
});
|
|
}
|
|
|
|
async function checkCurrentEngine(engineInfo) {
|
|
let engine = Services.search.currentEngine;
|
|
ok(engine.name.includes(engineInfo.name),
|
|
"Sanity check: current engine: engine.name=" + engine.name +
|
|
" basename=" + engineInfo.name);
|
|
|
|
await ContentTask.spawn(gBrowser.selectedBrowser, { name: engine.name }, async function(args) {
|
|
Assert.equal(content.gSearch._contentSearchController.defaultEngine.name,
|
|
args.name, "currentEngineName: " + args.name);
|
|
});
|
|
}
|