Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
/* import-globals-from ../../mochitest/states.js */
/* import-globals-from ../../mochitest/role.js */
loadScripts(
{ name: "states.js", dir: MOCHITESTS_DIR },
{ name: "role.js", dir: MOCHITESTS_DIR }
);
ChromeUtils.defineESModuleGetters(this, {
});
function isEventForAutocompleteItem(event) {
return event.accessible.role == ROLE_COMBOBOX_OPTION;
}
function isEventForButton(event) {
return event.accessible.role == ROLE_PUSHBUTTON;
}
function isEventForOneOffEngine(event) {
let parent = event.accessible.parent;
return (
event.accessible.role == ROLE_PUSHBUTTON &&
parent &&
parent.role == ROLE_GROUPING &&
parent.name
);
}
function isEventForMenuPopup(event) {
return event.accessible.role == ROLE_MENUPOPUP;
}
function isEventForMenuItem(event) {
return event.accessible.role == ROLE_MENUITEM;
}
function isEventForResultButton(event) {
let parent = event.accessible.parent;
return (
event.accessible.role == ROLE_PUSHBUTTON &&
parent?.role == ROLE_COMBOBOX_LIST
);
}
/**
* A test provider.
*/
class TipTestProvider extends UrlbarProvider {
constructor(matches) {
super();
this._matches = matches;
}
get name() {
return "TipTestProvider";
}
get type() {
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
}
isActive() {
return true;
}
isRestricting() {
return true;
}
async startQuery(context, addCallback) {
this._context = context;
for (const match of this._matches) {
addCallback(this, match);
}
}
}
// Check that the URL bar manages accessibility focus appropriately.
async function runTests() {
registerCleanupFunction(async function () {
await UrlbarTestUtils.promisePopupClose(window);
await PlacesUtils.history.clear();
});
await PlacesTestUtils.addVisits([
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
]);
// Ensure initial state.
await UrlbarTestUtils.promisePopupClose(window);
let focused = waitForEvent(
EVENT_FOCUS,
event => event.accessible.role == ROLE_ENTRY
);
gURLBar.focus();
let event = await focused;
let textBox = event.accessible;
// Ensure the URL bar is ready for a new URL to be typed.
// Sometimes, when this test runs, the existing text isn't selected when the
// URL bar is focused. Pressing escape twice ensures that the popup is
// closed and that the existing text is selected.
EventUtils.synthesizeKey("KEY_Escape");
EventUtils.synthesizeKey("KEY_Escape");
info("Ensuring no focus change when first text is typed");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
waitForFocus,
value: "example",
fireInputEvent: true,
});
// Wait a tick for a11y events to fire.
await TestUtils.waitForTick();
testStates(textBox, STATE_FOCUSED);
info("Ensuring no focus change on backspace");
EventUtils.synthesizeKey("KEY_Backspace");
await UrlbarTestUtils.promiseSearchComplete(window);
// Wait a tick for a11y events to fire.
await TestUtils.waitForTick();
testStates(textBox, STATE_FOCUSED);
info("Ensuring no focus change on text selection and delete");
EventUtils.synthesizeKey("KEY_ArrowLeft", { shiftKey: true });
EventUtils.synthesizeKey("KEY_Delete");
await UrlbarTestUtils.promiseSearchComplete(window);
// Wait a tick for a11y events to fire.
await TestUtils.waitForTick();
testStates(textBox, STATE_FOCUSED);
info("Ensuring autocomplete focus on down arrow (1)");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring focus of another autocomplete item on down arrow");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring previous arrow selection state doesn't get stale on input");
focused = waitForEvent(EVENT_FOCUS, textBox);
EventUtils.sendString("z");
await focused;
EventUtils.synthesizeKey("KEY_Backspace");
await UrlbarTestUtils.promiseSearchComplete(window);
testStates(textBox, STATE_FOCUSED);
info("Ensuring focus of another autocomplete item on down arrow");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
if (AppConstants.platform == "macosx") {
info("Ensuring focus of another autocomplete item on ctrl-n");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("n", { ctrlKey: true });
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring focus of another autocomplete item on ctrl-p");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("p", { ctrlKey: true });
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
}
info("Ensuring focus of another autocomplete item on up arrow");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowUp");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring text box focus on left arrow");
focused = waitForEvent(EVENT_FOCUS, textBox);
EventUtils.synthesizeKey("KEY_ArrowLeft");
await focused;
testStates(textBox, STATE_FOCUSED);
gURLBar.view.close();
// On Mac, down arrow when not at the end of the field moves to the end.
// Move back to the end so the next press of down arrow opens the popup.
EventUtils.synthesizeKey("KEY_ArrowRight");
info("Ensuring autocomplete focus on down arrow (2)");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring autocomplete focus on arrow up for search settings button");
focused = waitForEvent(EVENT_FOCUS, isEventForButton);
EventUtils.synthesizeKey("KEY_ArrowUp");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring text box focus when text is typed");
focused = waitForEvent(EVENT_FOCUS, textBox);
EventUtils.sendString("z");
await focused;
testStates(textBox, STATE_FOCUSED);
EventUtils.synthesizeKey("KEY_Backspace");
await UrlbarTestUtils.promiseSearchComplete(window);
info("Ensuring autocomplete focus on down arrow (3)");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring text box focus on backspace");
focused = waitForEvent(EVENT_FOCUS, textBox);
EventUtils.synthesizeKey("KEY_Backspace");
await focused;
testStates(textBox, STATE_FOCUSED);
await UrlbarTestUtils.promiseSearchComplete(window);
info("Ensuring autocomplete focus on arrow down (4)");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
// Arrow down to the last result.
const resultCount = UrlbarTestUtils.getResultCount(window);
while (UrlbarTestUtils.getSelectedRowIndex(window) != resultCount - 1) {
EventUtils.synthesizeKey("KEY_ArrowDown");
}
info("Ensuring one-off search button focus on arrow down");
focused = waitForEvent(EVENT_FOCUS, isEventForOneOffEngine);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring autocomplete focus on arrow up");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowUp");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring text box focus on text selection");
focused = waitForEvent(EVENT_FOCUS, textBox);
EventUtils.synthesizeKey("KEY_ArrowLeft", { shiftKey: true });
await focused;
testStates(textBox, STATE_FOCUSED);
if (AppConstants.platform == "macosx") {
// On Mac, ctrl-n after arrow left/right does not re-open the popup.
// Type some text so the next press of ctrl-n opens the popup.
EventUtils.sendString("ple");
info("Ensuring autocomplete focus on ctrl-n");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("n", { ctrlKey: true });
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
}
if (
AppConstants.platform == "macosx" &&
Services.prefs.getBoolPref("widget.macos.native-context-menus", false)
) {
// With native context menus, we do not observe accessibility events and we
// cannot send synthetic key events to the menu.
info("Opening and closing context native context menu");
let contextMenu = gURLBar.querySelector("menupopup");
let popupshown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
EventUtils.synthesizeMouseAtCenter(gURLBar.querySelector("moz-input-box"), {
type: "contextmenu",
});
await popupshown;
let popuphidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
contextMenu.hidePopup();
await popuphidden;
} else {
info(
"Ensuring context menu gets menu event on launch, and item focus on down"
);
let menuEvent = waitForEvent(
nsIAccessibleEvent.EVENT_MENUPOPUP_START,
isEventForMenuPopup
);
EventUtils.synthesizeMouseAtCenter(gURLBar.querySelector("moz-input-box"), {
type: "contextmenu",
});
await menuEvent;
focused = waitForEvent(EVENT_FOCUS, isEventForMenuItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
focused = waitForEvent(EVENT_FOCUS, textBox);
let closed = waitForEvent(
nsIAccessibleEvent.EVENT_MENUPOPUP_END,
isEventForMenuPopup
);
EventUtils.synthesizeKey("KEY_Escape");
await closed;
await focused;
}
info("Ensuring address bar is focused after context menu is dismissed.");
testStates(textBox, STATE_FOCUSED);
}
// We test TIP results in their own test so the spoofed results don't interfere
// with the main test.
async function runTipTests() {
let matches = [
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.TIP,
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
{
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
helpUrl: "http://example.com/",
type: "test",
titleL10n: { id: "urlbar-search-tips-confirm" },
buttons: [
{
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
l10n: { id: "urlbar-search-tips-confirm" },
},
],
}
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
),
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
),
];
// Ensure the tip appears in the expected position.
matches[1].suggestedIndex = 2;
let provider = new TipTestProvider(matches);
UrlbarProvidersManager.registerProvider(provider);
registerCleanupFunction(async function () {
UrlbarProvidersManager.unregisterProvider(provider);
});
let focused = waitForEvent(
EVENT_FOCUS,
event => event.accessible.role == ROLE_ENTRY
);
gURLBar.focus();
let event = await focused;
let textBox = event.accessible;
EventUtils.synthesizeKey("KEY_Escape");
EventUtils.synthesizeKey("KEY_Escape");
info("Ensuring no focus change when first text is typed");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
waitForFocus,
value: "example",
fireInputEvent: true,
});
// Wait a tick for a11y events to fire.
await TestUtils.waitForTick();
testStates(textBox, STATE_FOCUSED);
info("Ensuring autocomplete focus on down arrow (1)");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring the tip button is focused on down arrow");
info("Also ensuring that the tip button is a part of a labelled group");
focused = waitForEvent(EVENT_FOCUS, isEventForResultButton);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring the help button is focused on tab");
info("Also ensuring that the help button is a part of a labelled group");
focused = waitForEvent(EVENT_FOCUS, isEventForResultButton);
EventUtils.synthesizeKey("KEY_Tab");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring autocomplete focus on down arrow (2)");
focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
EventUtils.synthesizeKey("KEY_ArrowDown");
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring the help button is focused on shift+tab");
focused = waitForEvent(EVENT_FOCUS, isEventForResultButton);
EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
event = await focused;
testStates(event.accessible, STATE_FOCUSED);
info("Ensuring text box focus on left arrow, and not back to the tip button");
focused = waitForEvent(EVENT_FOCUS, textBox);
EventUtils.synthesizeKey("KEY_ArrowLeft");
await focused;
testStates(textBox, STATE_FOCUSED);
}
addAccessibleTask(``, runTests);
addAccessibleTask(``, runTipTests);