Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

  • This test gets skipped with pattern: os == 'linux' && os_version == '18.04' && processor == 'x86_64' && asan OR os == 'linux' && os_version == '18.04' && processor == 'x86_64' && tsan OR win11_2009 && asan
  • Manifest: browser/components/urlbar/tests/browser/browser.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
/**
* Tests less common mouse/keyboard manipulations of the address bar input
* field selection, for example:
* - Home/Del
* - Shift+Right/Left
* - Drag selection
* - Double-click on word
*
* All the tests set up some initial conditions, and check it. Then optionally
* they can manipulate the selection further, and check the results again.
* We want to ensure the final selection is the expected one, even if in the
* future we change our trimming strategy for the input field value.
*
* Note: there's a few +-1 adjustments to text lengths that are apparently
* necessary in --headless mode.
*/
const tests = [
{
description: "Test HOME starting from full selection",
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
EventUtils.synthesizeKey("KEY_Home");
},
get modifiedSelection() {
// Cursor must move to zero, regardless of any untrimming.
return [0, 0];
},
},
{
description: "Test CTRL/META LEFT starting from full selection",
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
if (AppConstants.platform == "macosx") {
// Synthesized key events work differently from native ones, here
// we simulate the native behavior.
EventUtils.synthesizeKey("KEY_ArrowLeft", {
type: "keydown",
metaKey: true,
});
EventUtils.synthesizeKey("KEY_ArrowLeft", { type: "keyup" });
EventUtils.synthesizeKey("KEY_Meta", { type: "keyup" });
} else {
EventUtils.synthesizeKey("KEY_ArrowLeft", { ctrlKey: true });
}
},
get modifiedSelection() {
return [0, 0];
},
},
{
description: "Test CTRL/ALT SHIFT LEFT starting from full selection",
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
if (AppConstants.platform == "macosx") {
// Synthesized key events work differently from native ones, here
// we simulate the native behavior.
EventUtils.synthesizeKey("KEY_ArrowLeft", {
type: "keydown",
altKey: true,
shiftKey: true,
});
EventUtils.synthesizeKey("KEY_ArrowLeft", { type: "keyup" });
EventUtils.synthesizeKey("KEY_Meta", { type: "keyup" });
} else {
EventUtils.synthesizeKey("KEY_ArrowLeft", {
ctrlKey: true,
shiftKey: true,
});
}
},
get modifiedSelection() {
return [0, gURLBar.value.lastIndexOf(".") + 1];
},
},
{
description: "Test CTRL A starting from full selection",
skipIf() {
return AppConstants.platform != "macosx";
},
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
EventUtils.synthesizeKey("A", { ctrlKey: true });
},
get modifiedSelection() {
return [0, 0];
},
},
{
description: "Test END starting from full selection",
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
if (AppConstants.platform == "macosx") {
EventUtils.synthesizeKey("KEY_ArrowRight", { metaKey: true });
} else {
EventUtils.synthesizeKey("KEY_End", {});
}
},
get modifiedSelection() {
return [gURLBar.value.length, gURLBar.value.length];
},
},
{
description: "Test SHIFT+LEFT starting from full selection",
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
EventUtils.synthesizeKey("KEY_ArrowLeft", { shiftKey: true });
},
get modifiedSelection() {
return [0, gURLBar.value.length - 1];
},
},
{
description: "Test SHIFT+RIGHT starting from full selection",
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
EventUtils.synthesizeKey("KEY_ArrowRight", { shiftKey: true });
},
get modifiedSelection() {
return [0, gURLBar.value.length];
},
},
{
description: "Test Drag Selection from the first character - Partial host",
async openPanel() {
// Select partial string that doesn't complete to a URL.
this._expectedSelectedText = gURLBar.value.substring(0, 5);
await selectWithMouseDrag(
getTextWidth(gURLBar.value[0]) / 2 - 1,
getTextWidth(gURLBar.value.substring(0, 5)) + 1
);
},
get selection() {
// When untrimming is enabled, the behavior differs depending on whether
// the selected text can generate a valid URL, so there may be an offset.
let startOffset = UrlbarPrefs.getScotchBonnetPref(
"untrimOnUserInteraction.featureGate"
)
? gURLBar.value.indexOf(this._expectedSelectedText)
: 0;
return [startOffset, startOffset + this._expectedSelectedText.length];
},
},
{
description: "Test Drag Selection from the first character - Full host",
async openPanel() {
// Select partial string that completes to a URL.
let uri = Services.io.newURI(gURLBar._untrimmedValue);
let endOfHost =
gURLBar.value.indexOf(uri.displayHost) + uri.displayHost.length;
this._expectedSelectedText = gURLBar.value.substring(0, endOfHost);
await selectWithMouseDrag(
getTextWidth(gURLBar.value[0]) / 2 - 1,
getTextWidth(this._expectedSelectedText)
);
},
get selection() {
return [
0,
gURLBar.value.indexOf(this._expectedSelectedText) +
this._expectedSelectedText.length,
];
},
},
{
description: "Test Drag Selection from the last character",
async openPanel() {
this._expectedSelectedText = gURLBar.value.substring(-5);
await selectWithMouseDrag(
getTextWidth(gURLBar.value) + 1,
getTextWidth(this._expectedSelectedText)
);
},
get selection() {
return [
gURLBar.value.indexOf(this._expectedSelectedText),
gURLBar.value.length,
];
},
},
{
description: "Test Drag Selection in the middle of the string",
async openPanel() {
this._expectedSelectedText = gURLBar.value.substring(5, 10);
await selectWithMouseDrag(
getTextWidth(gURLBar.value.substring(0, 5)) + 1,
getTextWidth(gURLBar.value.substring(0, 10)) + 1
);
},
get selection() {
let start = gURLBar.value.indexOf(this._expectedSelectedText);
return [start, start + this._expectedSelectedText.length];
},
},
{
description: "Test Double-click on word",
async openPanel() {
let wordBoundaryIndex = gURLBar.value.search(/\btest/);
this._expectedSelectedText = "test";
await selectWithDoubleClick(
getTextWidth(gURLBar.value.substring(0, wordBoundaryIndex))
);
},
get selection() {
let start = gURLBar.value.indexOf(this._expectedSelectedText);
return [start, start + this._expectedSelectedText.length];
},
},
{
description: "Click at the right of the text",
openPanel() {
EventUtils.synthesizeKey("l", { accelKey: true });
},
get selection() {
return [0, gURLBar.value.length];
},
manipulate() {
let rect = gURLBar.inputField.getBoundingClientRect();
EventUtils.synthesizeMouse(
gURLBar.inputField,
getTextWidth(gURLBar.value) + 10,
rect.height / 2,
{}
);
},
get modifiedSelection() {
return [gURLBar.value.length, gURLBar.value.length];
},
},
];
add_setup(async function () {
gURLBar.inputField.style.font = "14px monospace";
registerCleanupFunction(() => {
gURLBar.inputField.style.font = null;
});
});
add_task(async function https() {
});
add_task(async function http() {
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
});
async function doTest(url) {
await BrowserTestUtils.withNewTab(url, async () => {
for (let test of tests) {
if (test.skipIf?.()) {
continue;
}
gURLBar.blur();
info(test.description);
await UrlbarTestUtils.promisePopupOpen(window, async () => {
await test.openPanel();
});
info(
`Selected text is <${gURLBar.value.substring(
gURLBar.selectionStart,
gURLBar.selectionEnd
)}>`
);
Assert.deepEqual(
test.selection,
[gURLBar.selectionStart, gURLBar.selectionEnd],
"Check initial selection"
);
if (test.manipulate) {
await test.manipulate();
info(
`Selected text after manipulation is <${gURLBar.value.substring(
gURLBar.selectionStart,
gURLBar.selectionEnd
)}>`
);
Assert.deepEqual(
test.modifiedSelection,
[gURLBar.selectionStart, gURLBar.selectionEnd],
"Check selection after manipulation"
);
}
}
});
}
function getTextWidth(inputText) {
let span = document.createElement("span");
document.documentElement.appendChild(span);
span.style.all = "initial";
span.style.font = window
.getComputedStyle(gURLBar.inputField)
.getPropertyValue("font");
span.textContent = inputText;
let result = span.offsetWidth;
span.remove();
return result;
}