Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
/**
* Tests the one-off search buttons in the urlbar.
*/
"use strict";
const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
let gMaxResults;
let engine;
ChromeUtils.defineLazyGetter(this, "oneOffSearchButtons", () => {
return UrlbarTestUtils.getOneOffSearchButtons(window);
});
add_setup(async function () {
gMaxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
// Add a search suggestion engine and move it to the front so that it appears
// as the first one-off.
engine = await SearchTestUtils.promiseNewSearchEngine({
url: getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME,
});
await Services.search.moveEngine(engine, 0);
await SpecialPowers.pushPrefEnv({
set: [
["browser.search.separatePrivateDefault.ui.enabled", false],
["browser.urlbar.suggest.quickactions", false],
],
});
registerCleanupFunction(async function () {
await PlacesUtils.history.clear();
await UrlbarTestUtils.formHistory.clear();
});
// Initialize history with enough visits to fill up the view.
await PlacesUtils.history.clear();
await UrlbarTestUtils.formHistory.clear();
for (let i = 0; i < gMaxResults; i++) {
await PlacesTestUtils.addVisits(
);
}
// Add some more visits to the last URL added above so that the top-sites view
// will be non-empty.
for (let i = 0; i < 5; i++) {
await PlacesTestUtils.addVisits(
);
}
await updateTopSites(sites => {
return sites && sites[0] && sites[0].url.startsWith("http://example.com/");
});
// Move the mouse away from the view so that a result or one-off isn't
// inadvertently highlighted. See bug 1659011.
EventUtils.synthesizeMouse(
gURLBar.inputField,
0,
0,
{ type: "mousemove" },
window
);
});
// Opens the view without showing the one-offs. They should be hidden and arrow
// key selection should work properly.
add_task(async function noOneOffs() {
// Do a search for "@" since we hide the one-offs in that case.
let value = "@";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value,
fireInputEvent: true,
});
await TestUtils.waitForCondition(
() => !oneOffSearchButtons._rebuilding,
"Waiting for one-offs to finish rebuilding"
);
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
false,
"One-offs should be hidden"
);
assertState(-1, -1, value);
// Get the result count. We don't particularly care what the results are,
// just what the count is so that we can key through them all.
let resultCount = UrlbarTestUtils.getResultCount(window);
// Key down through all results.
for (let i = 0; i < resultCount; i++) {
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(i, -1);
}
// Key down again. Nothing should be selected.
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(-1, -1, value);
// Key down again. The first result should be selected.
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(0, -1);
// Key up. Nothing should be selected.
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(-1, -1, value);
// Key up through all the results.
for (let i = resultCount - 1; i >= 0; i--) {
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(i, -1);
}
// Key up again. Nothing should be selected.
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(-1, -1, value);
await hidePopup();
});
// Opens the top-sites view. The one-offs should be shown.
add_task(async function topSites() {
// Do a search that shows top sites.
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
fireInputEvent: true,
});
await TestUtils.waitForCondition(
() => !oneOffSearchButtons._rebuilding,
"Waiting for one-offs to finish rebuilding"
);
// There's one top sites result, the page with a lot of visits from init.
let resultURL = UrlbarTestUtils.trimURL(
);
Assert.equal(UrlbarTestUtils.getResultCount(window), 1, "Result count");
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
true,
"One-offs are visible"
);
assertState(-1, -1, "");
// Key down into the result.
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(0, -1, resultURL);
// Key down through each one-off.
let numButtons = oneOffSearchButtons.getSelectableButtons(true).length;
for (let i = 0; i < numButtons; i++) {
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(-1, i, "");
}
// Key down again. The selection should go away.
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(-1, -1, "");
// Key down again. The result should be selected.
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(0, -1, resultURL);
// Key back up. The selection should go away.
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(-1, -1, "");
// Key up again. The selection should wrap back around to the one-offs. Key
// up through all the one-offs.
for (let i = numButtons - 1; i >= 0; i--) {
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(-1, i, "");
}
// Key up. The result should be selected.
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(0, -1, resultURL);
// Key up again. The selection should go away.
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(-1, -1, "");
await hidePopup();
});
// Keys up and down through the non-top-sites view, i.e., the view that's shown
// when the input has been edited.
add_task(async function editedView() {
// Use a typed value that returns the visits added above but that doesn't
// trigger autofill since that would complicate the test.
let typedValue = "browser_urlbarOneOffs";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
fireInputEvent: true,
});
await UrlbarTestUtils.waitForAutocompleteResultAt(window, gMaxResults - 1);
let heuristicResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
assertState(0, -1, typedValue);
// Key down through each result. The first result is already selected, which
// is why gMaxResults - 1 is the correct number of times to do this.
for (let i = 0; i < gMaxResults - 1; i++) {
EventUtils.synthesizeKey("KEY_ArrowDown");
// i starts at zero so that the textValue passed to assertState is correct.
// But that means that i + 1 is the expected selected index, since initially
// (when this loop starts) the first result is selected.
assertState(
i + 1,
-1,
UrlbarTestUtils.trimURL(
)
);
Assert.ok(
!BrowserTestUtils.isVisible(heuristicResult.element.action),
"The heuristic action should not be visible"
);
}
// Key down through each one-off.
let numButtons = oneOffSearchButtons.getSelectableButtons(true).length;
for (let i = 0; i < numButtons; i++) {
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(-1, i, typedValue);
Assert.equal(
BrowserTestUtils.isVisible(heuristicResult.element.action),
!oneOffSearchButtons.selectedButton.classList.contains(
"search-setting-button"
),
"The heuristic action should be visible when a one-off button is selected"
);
}
// Key down once more. The selection should wrap around to the first result.
EventUtils.synthesizeKey("KEY_ArrowDown");
assertState(0, -1, typedValue);
Assert.ok(
BrowserTestUtils.isVisible(heuristicResult.element.action),
"The heuristic action should be visible"
);
// Now key up. The selection should wrap back around to the one-offs. Key
// up through all the one-offs.
for (let i = numButtons - 1; i >= 0; i--) {
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(-1, i, typedValue);
Assert.equal(
BrowserTestUtils.isVisible(heuristicResult.element.action),
!oneOffSearchButtons.selectedButton.classList.contains(
"search-setting-button"
),
"The heuristic action should be visible when a one-off button is selected"
);
}
// Key up through each non-heuristic result.
for (let i = gMaxResults - 2; i >= 0; i--) {
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(
i + 1,
-1,
UrlbarTestUtils.trimURL(
)
);
Assert.ok(
!BrowserTestUtils.isVisible(heuristicResult.element.action),
"The heuristic action should not be visible"
);
}
// Key up once more. The heuristic result should be selected.
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(0, -1, typedValue);
Assert.ok(
BrowserTestUtils.isVisible(heuristicResult.element.action),
"The heuristic action should be visible"
);
await hidePopup();
});
// Checks that "Search with Current Search Engine" items are updated to "Search
// with One-Off Engine" when a one-off is selected.
add_task(async function searchWith() {
// Enable suggestions for this subtest so we can check non-heuristic results.
let oldDefaultEngine = await Services.search.getDefault();
await Services.search.setDefault(
engine,
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
);
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.suggest.searches", true]],
});
let typedValue = "foo";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
});
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
assertState(0, -1, typedValue);
Assert.equal(
result.displayed.action,
"Search with " + (await Services.search.getDefault()).name,
"Sanity check: first result's action text"
);
// Alt+Down to the second one-off. Now the first result and the second
// one-off should both be selected.
EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true, repeat: 2 });
assertState(0, 1, typedValue);
let engineName = oneOffSearchButtons.selectedButton.engine.name;
Assert.notEqual(
engineName,
(await Services.search.getDefault()).name,
"Sanity check: Second one-off engine should not be the current engine"
);
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.equal(
result.displayed.action,
"Search with " + engineName,
"First result's action text should be updated"
);
// Check non-heuristic results.
await hidePopup();
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
});
EventUtils.synthesizeKey("KEY_ArrowDown");
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
assertState(1, -1, typedValue + "foo");
Assert.equal(
result.displayed.action,
"Search with " + engine.name,
"Sanity check: second result's action text"
);
Assert.ok(!result.heuristic, "The second result is not heuristic.");
EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true, repeat: 2 });
assertState(1, 1, typedValue + "foo");
engineName = oneOffSearchButtons.selectedButton.engine.name;
Assert.notEqual(
engineName,
(await Services.search.getDefault()).name,
"Sanity check: Second one-off engine should not be the current engine"
);
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
Assert.equal(
result.displayed.action,
"Search with " + engineName,
"Second result's action text should be updated"
);
await SpecialPowers.popPrefEnv();
await Services.search.setDefault(
oldDefaultEngine,
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
);
await hidePopup();
});
// Clicks a one-off with an engine.
add_task(async function oneOffClick() {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
// We are explicitly using something that looks like a url, to make the test
// stricter. Even if it looks like a url, we should search.
let typedValue = "foo.bar";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
});
await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
assertState(0, -1, typedValue);
let oneOffs = oneOffSearchButtons.getSelectableButtons(true);
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeMouseAtCenter(oneOffs[0], {});
await searchPromise;
Assert.ok(UrlbarTestUtils.isPopupOpen(window), "Urlbar view is still open.");
await UrlbarTestUtils.assertSearchMode(window, {
engineName: oneOffs[0].engine.name,
entry: "oneoff",
});
await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
gBrowser.removeTab(gBrowser.selectedTab);
await UrlbarTestUtils.formHistory.clear();
});
// Presses the Return key when a one-off with an engine is selected.
add_task(async function oneOffReturn() {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
// We are explicitly using something that looks like a url, to make the test
// stricter. Even if it looks like a url, we should search.
let typedValue = "foo.bar";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
fireInputEvent: true,
});
await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
assertState(0, -1, typedValue);
let oneOffs = oneOffSearchButtons.getSelectableButtons(true);
// Alt+Down to select the first one-off.
EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true });
assertState(0, 0, typedValue);
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("KEY_Enter");
await searchPromise;
Assert.ok(UrlbarTestUtils.isPopupOpen(window), "Urlbar view is still open.");
await UrlbarTestUtils.assertSearchMode(window, {
engineName: oneOffs[0].engine.name,
entry: "oneoff",
});
await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
gBrowser.removeTab(gBrowser.selectedTab);
await UrlbarTestUtils.formHistory.clear();
await hidePopup();
});
// When all engines and local shortcuts are hidden except for the current
// engine, the one-offs container should be hidden.
add_task(async function allOneOffsHiddenExceptCurrentEngine() {
// Disable all the engines but the current one, check the oneoffs are
// hidden and that moving up selects the last match.
let defaultEngine = await Services.search.getDefault();
let engines = (await Services.search.getVisibleEngines()).filter(
e => e.name != defaultEngine.name
);
await SpecialPowers.pushPrefEnv({
set: [
...UrlbarUtils.LOCAL_SEARCH_MODES.map(m => [
`browser.urlbar.${m.pref}`,
false,
]),
],
});
engines.forEach(e => {
e.hideOneOffButton = e.name !== defaultEngine.name;
});
let typedValue = "foo";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
fireInputEvent: true,
});
await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
assertState(0, -1);
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
false,
"The one-off buttons should be hidden"
);
EventUtils.synthesizeKey("KEY_ArrowUp");
assertState(0, -1);
await hidePopup();
await SpecialPowers.popPrefEnv();
engines.forEach(e => {
e.hideOneOffButton = false;
});
});
// The one-offs should be hidden when searching with an "@engine" search engine
// alias.
add_task(async function hiddenWhenUsingSearchAlias() {
let typedValue = "@example";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
fireInputEvent: true,
});
await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
false,
"Should not be showing the one-off buttons"
);
await hidePopup();
typedValue = "not an engine alias";
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
fireInputEvent: true,
});
await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
true,
"Should be showing the one-off buttons"
);
await hidePopup();
});
// Makes sure the local shortcuts exist.
add_task(async function localShortcuts() {
oneOffSearchButtons.invalidateCache();
await doLocalShortcutsShownTest();
});
// Clicks a local shortcut button.
add_task(async function localShortcutClick() {
// We are explicitly using something that looks like a url, to make the test
// stricter. Even if it looks like a url, we should search.
let typedValue = "foo.bar";
oneOffSearchButtons.invalidateCache();
let rebuildPromise = BrowserTestUtils.waitForEvent(
oneOffSearchButtons,
"rebuild"
);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
});
await rebuildPromise;
let buttons = oneOffSearchButtons.localButtons;
Assert.ok(buttons.length, "Sanity check: Local shortcuts exist");
for (let button of buttons) {
Assert.ok(button.source, "Sanity check: Button has a source");
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeMouseAtCenter(button, {});
await searchPromise;
Assert.ok(
UrlbarTestUtils.isPopupOpen(window),
"Urlbar view is still open."
);
await UrlbarTestUtils.assertSearchMode(window, {
source: button.source,
entry: "oneoff",
});
}
await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
await hidePopup();
});
// Presses the Return key when a local shortcut is selected.
add_task(async function localShortcutReturn() {
// We are explicitly using something that looks like a url, to make the test
// stricter. Even if it looks like a url, we should search.
let typedValue = "foo.bar";
oneOffSearchButtons.invalidateCache();
let rebuildPromise = BrowserTestUtils.waitForEvent(
oneOffSearchButtons,
"rebuild"
);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: typedValue,
});
await rebuildPromise;
let buttons = oneOffSearchButtons.localButtons;
Assert.ok(buttons.length, "Sanity check: Local shortcuts exist");
let allButtons = oneOffSearchButtons.getSelectableButtons(false);
let firstLocalIndex = allButtons.length - buttons.length;
for (let i = 0; i < buttons.length; i++) {
let button = buttons[i];
// Alt+Down enough times to select the button.
let index = firstLocalIndex + i;
EventUtils.synthesizeKey("KEY_ArrowDown", {
altKey: true,
repeat: index + 1,
});
await TestUtils.waitForCondition(
() => oneOffSearchButtons.selectedButtonIndex == index,
"Waiting for local shortcut to become selected"
);
let expectedSelectedResultIndex = -1;
let count = UrlbarTestUtils.getResultCount(window);
if (count > 0) {
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
if (result.heuristic) {
expectedSelectedResultIndex = 0;
}
}
assertState(expectedSelectedResultIndex, index, typedValue);
Assert.ok(button.source, "Sanity check: Button has a source");
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("KEY_Enter");
await searchPromise;
Assert.ok(
UrlbarTestUtils.isPopupOpen(window),
"Urlbar view is still open."
);
await UrlbarTestUtils.assertSearchMode(window, {
source: button.source,
entry: "oneoff",
});
}
await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
await hidePopup();
});
// With an empty search string, clicking a local shortcut should result in no
// heuristic result.
add_task(async function localShortcutEmptySearchString() {
oneOffSearchButtons.invalidateCache();
let rebuildPromise = BrowserTestUtils.waitForEvent(
oneOffSearchButtons,
"rebuild"
);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await rebuildPromise;
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
true,
"One-offs are visible"
);
let buttons = oneOffSearchButtons.localButtons;
Assert.ok(buttons.length, "Sanity check: Local shortcuts exist");
for (let button of buttons) {
Assert.ok(button.source, "Sanity check: Button has a source");
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeMouseAtCenter(button, {});
await searchPromise;
Assert.ok(
UrlbarTestUtils.isPopupOpen(window),
"Urlbar view is still open."
);
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
true,
"One-offs are visible"
);
await UrlbarTestUtils.assertSearchMode(window, {
source: button.source,
entry: "oneoff",
});
let resultCount = UrlbarTestUtils.getResultCount(window);
if (!resultCount) {
Assert.equal(
gURLBar.panel.getAttribute("noresults"),
"true",
"Panel has no results, therefore should have noresults attribute"
);
continue;
}
Assert.ok(
!gURLBar.panel.hasAttribute("noresults"),
"Panel has results, therefore should not have noresults attribute"
);
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
Assert.ok(!result.heuristic, "The first result should not be heuristic");
}
await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
await hidePopup();
});
// Trigger SearchOneOffs.willHide() outside of SearchOneOffs.__rebuild(). Ensure
// that we always show the correct engines in the one-offs. This effectively
// tests SearchOneOffs._engineInfo.domWasUpdated.
add_task(async function avoidWillHideRace() {
// We set maxHistoricalSearchSuggestions to 0 since this test depends on
// UrlbarView calling SearchOneOffs.willHide(). That only happens when the
// Urlbar is in search mode after a query that returned no results.
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.maxHistoricalSearchSuggestions", 0]],
});
oneOffSearchButtons.invalidateCache();
// Accel+K triggers SearchOneOffs.willHide() from UrlbarView instead of from
// SearchOneOffs.__rebuild.
let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("k", { accelKey: true });
await searchPromise;
Assert.ok(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
"One-offs should be visible"
);
await UrlbarTestUtils.promisePopupClose(window);
info("Hide all engines but the test engine.");
let oldDefaultEngine = await Services.search.getDefault();
await Services.search.setDefault(
engine,
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
);
let engines = (await Services.search.getVisibleEngines()).filter(
e => e.name != engine.name
);
await SpecialPowers.pushPrefEnv({
set: [
...UrlbarUtils.LOCAL_SEARCH_MODES.map(m => [
`browser.urlbar.${m.pref}`,
false,
]),
],
});
engines.forEach(e => {
e.hideOneOffButton = true;
});
Assert.ok(
!oneOffSearchButtons._engineInfo,
"_engineInfo should be nulled out."
);
// This call to SearchOneOffs.willHide() should repopulate _engineInfo but not
// rebuild the one-offs. _engineInfo.willHide will be true and thus UrlbarView
// will not open.
EventUtils.synthesizeKey("k", { accelKey: true });
// We can't wait for UrlbarTestUtils.promiseSearchComplete here since we
// expect the popup will not open. We wait for _engineInfo to be populated
// instead.
await BrowserTestUtils.waitForCondition(
() => !!oneOffSearchButtons._engineInfo,
"_engineInfo is set."
);
Assert.ok(!UrlbarTestUtils.isPopupOpen(window), "The UrlbarView is closed.");
Assert.equal(
oneOffSearchButtons._engineInfo.willHide,
true,
"_engineInfo should be repopulated and willHide should be true."
);
Assert.equal(
oneOffSearchButtons._engineInfo.domWasUpdated,
undefined,
"domWasUpdated should not be populated since we haven't yet tried to rebuild the one-offs."
);
// Now search. The view will open and the one-offs will rebuild, although
// the one-offs will not be shown since there is only one engine.
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "test",
});
Assert.equal(
oneOffSearchButtons._engineInfo.domWasUpdated,
true,
"domWasUpdated should be true"
);
Assert.ok(
!UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
"One-offs should be hidden since there is only one engine."
);
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
await Services.search.setDefault(
oldDefaultEngine,
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
);
await SpecialPowers.popPrefEnv();
engines.forEach(e => {
e.hideOneOffButton = false;
});
});
// Hides each of the local shortcuts one at a time. The search buttons should
// automatically rebuild themselves.
add_task(async function individualLocalShortcutsHidden() {
for (let { pref, source } of UrlbarUtils.LOCAL_SEARCH_MODES) {
await SpecialPowers.pushPrefEnv({
set: [[`browser.urlbar.${pref}`, false]],
});
let rebuildPromise = BrowserTestUtils.waitForEvent(
oneOffSearchButtons,
"rebuild"
);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await rebuildPromise;
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
true,
"One-offs are visible"
);
let buttons = oneOffSearchButtons.localButtons;
Assert.ok(buttons.length, "Sanity check: Local shortcuts exist");
let otherModes = UrlbarUtils.LOCAL_SEARCH_MODES.filter(
m => m.source != source
);
Assert.equal(
buttons.length,
otherModes.length,
"Expected number of enabled local shortcut buttons"
);
for (let i = 0; i < buttons.length; i++) {
Assert.equal(
buttons[i].source,
otherModes[i].source,
"Button has the expected source"
);
}
await hidePopup();
await SpecialPowers.popPrefEnv();
}
});
// Hides all the local shortcuts at once.
add_task(async function allLocalShortcutsHidden() {
await SpecialPowers.pushPrefEnv({
set: UrlbarUtils.LOCAL_SEARCH_MODES.map(m => [
`browser.urlbar.${m.pref}`,
false,
]),
});
let rebuildPromise = BrowserTestUtils.waitForEvent(
oneOffSearchButtons,
"rebuild"
);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await rebuildPromise;
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
true,
"One-offs are visible"
);
Assert.equal(
oneOffSearchButtons.localButtons.length,
0,
"All local shortcuts should be hidden"
);
Assert.greater(
oneOffSearchButtons.getSelectableButtons(false).filter(b => b.engine)
.length,
0,
"Engine one-offs should not be hidden"
);
await hidePopup();
await SpecialPowers.popPrefEnv();
});
// Hides all the engines but none of the local shortcuts.
add_task(async function localShortcutsShownWhenEnginesHidden() {
let engines = await Services.search.getVisibleEngines();
engines.forEach(e => {
e.hideOneOffButton = true;
});
let rebuildPromise = BrowserTestUtils.waitForEvent(
oneOffSearchButtons,
"rebuild"
);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "",
});
await rebuildPromise;
Assert.equal(
UrlbarTestUtils.getOneOffSearchButtonsVisible(window),
true,
"One-offs are visible"
);
Assert.equal(
oneOffSearchButtons.localButtons.length,
UrlbarUtils.LOCAL_SEARCH_MODES.length,
"All local shortcuts are visible"
);
Assert.equal(
oneOffSearchButtons.getSelectableButtons(false).filter(b => b.engine)
.length,
0,
"All engine one-offs are hidden"
);
await hidePopup();
engines.forEach(e => {
e.hideOneOffButton = false;
});
});
/**
* Checks that the local shortcuts are shown correctly.
*/
async function doLocalShortcutsShownTest() {
let rebuildPromise = BrowserTestUtils.waitForEvent(
oneOffSearchButtons,
"rebuild"
);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "doLocalShortcutsShownTest",
});
await rebuildPromise;
let buttons = oneOffSearchButtons.localButtons;
Assert.equal(buttons.length, 3, "Expected number of local shortcuts");
let expectedSource;
let seenIDs = new Set();
for (let button of buttons) {
Assert.ok(
!seenIDs.has(button.id),
"Should not have already seen button.id"
);
seenIDs.add(button.id);
switch (button.id) {
case "urlbar-engine-one-off-item-bookmarks":
expectedSource = UrlbarUtils.RESULT_SOURCE.BOOKMARKS;
break;
case "urlbar-engine-one-off-item-tabs":
expectedSource = UrlbarUtils.RESULT_SOURCE.TABS;
break;
case "urlbar-engine-one-off-item-history":
expectedSource = UrlbarUtils.RESULT_SOURCE.HISTORY;
break;
default:
Assert.ok(false, `Unexpected local shortcut ID: ${button.id}`);
break;
}
Assert.equal(button.source, expectedSource, "Expected button.source");
}
await hidePopup();
}
function assertState(result, oneOff, textValue = undefined) {
Assert.equal(
UrlbarTestUtils.getSelectedRowIndex(window),
result,
"Expected result should be selected"
);
Assert.equal(
oneOffSearchButtons.selectedButtonIndex,
oneOff,
"Expected one-off should be selected"
);
if (textValue !== undefined) {
Assert.equal(gURLBar.value, textValue, "Expected value");
}
}
function hidePopup() {
return UrlbarTestUtils.promisePopupClose(window, () => {
EventUtils.synthesizeKey("KEY_Escape");
});
}