forked from mirrors/gecko-dev
338 lines
9.1 KiB
JavaScript
338 lines
9.1 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
const PAGECONTENT_SMALL = `
|
|
<!doctype html>
|
|
<html>
|
|
<body><select id='one'>
|
|
<option value='One'>One</option>
|
|
<option value='Two'>Two</option>
|
|
</select><select id='two'>
|
|
<option value='Three'>Three</option>
|
|
<option value='Four'>Four</option>
|
|
</select><select id='three'>
|
|
<option value='Five'>Five</option>
|
|
<option value='Six'>Six</option>
|
|
</select></body></html>
|
|
`;
|
|
|
|
async function performLargePopupTests(win) {
|
|
let browser = win.gBrowser.selectedBrowser;
|
|
|
|
await SpecialPowers.spawn(browser, [], async function () {
|
|
let doc = content.document;
|
|
let select = doc.getElementById("one");
|
|
for (var i = 0; i < 180; i++) {
|
|
select.add(new content.Option("Test" + i));
|
|
}
|
|
|
|
select.options[60].selected = true;
|
|
select.focus();
|
|
});
|
|
|
|
// Check if a drag-select works and scrolls the list.
|
|
const selectPopup = await openSelectPopup("mousedown", "select", win);
|
|
const browserRect = browser.getBoundingClientRect();
|
|
|
|
let getScrollPos = () => selectPopup.scrollBox.scrollbox.scrollTop;
|
|
let scrollPos = getScrollPos();
|
|
let popupRect = selectPopup.getBoundingClientRect();
|
|
|
|
// First, check that scrolling does not occur when the mouse is moved over the
|
|
// anchor button but not the popup yet.
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 5,
|
|
popupRect.top - 10,
|
|
{
|
|
type: "mousemove",
|
|
buttons: 1,
|
|
},
|
|
win
|
|
);
|
|
is(
|
|
getScrollPos(),
|
|
scrollPos,
|
|
"scroll position after mousemove over button should not change"
|
|
);
|
|
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.top + 10,
|
|
{
|
|
type: "mousemove",
|
|
buttons: 1,
|
|
},
|
|
win
|
|
);
|
|
|
|
// Dragging above the popup scrolls it up.
|
|
let scrolledPromise = BrowserTestUtils.waitForEvent(
|
|
selectPopup,
|
|
"scroll",
|
|
false,
|
|
() => getScrollPos() < scrollPos - 5
|
|
);
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.top - 20,
|
|
{
|
|
type: "mousemove",
|
|
buttons: 1,
|
|
},
|
|
win
|
|
);
|
|
await scrolledPromise;
|
|
ok(true, "scroll position at drag up");
|
|
|
|
// Dragging below the popup scrolls it down.
|
|
scrollPos = getScrollPos();
|
|
scrolledPromise = BrowserTestUtils.waitForEvent(
|
|
selectPopup,
|
|
"scroll",
|
|
false,
|
|
() => getScrollPos() > scrollPos + 5
|
|
);
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.bottom + 20,
|
|
{
|
|
type: "mousemove",
|
|
buttons: 1,
|
|
},
|
|
win
|
|
);
|
|
await scrolledPromise;
|
|
ok(true, "scroll position at drag down");
|
|
|
|
// Releasing the mouse button and moving the mouse does not change the scroll position.
|
|
scrollPos = getScrollPos();
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.bottom + 25,
|
|
{ type: "mouseup" },
|
|
win
|
|
);
|
|
is(getScrollPos(), scrollPos, "scroll position at mouseup should not change");
|
|
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.bottom + 20,
|
|
{ type: "mousemove" },
|
|
win
|
|
);
|
|
is(
|
|
getScrollPos(),
|
|
scrollPos,
|
|
"scroll position at mousemove after mouseup should not change"
|
|
);
|
|
|
|
// Now check dragging with a mousedown on an item
|
|
let menuRect = selectPopup.children[51].getBoundingClientRect();
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
menuRect.left + 5,
|
|
menuRect.top + 5,
|
|
{ type: "mousedown" },
|
|
win
|
|
);
|
|
|
|
// Dragging below the popup scrolls it down.
|
|
scrolledPromise = BrowserTestUtils.waitForEvent(
|
|
selectPopup,
|
|
"scroll",
|
|
false,
|
|
() => getScrollPos() > scrollPos + 5
|
|
);
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.bottom + 20,
|
|
{
|
|
type: "mousemove",
|
|
buttons: 1,
|
|
},
|
|
win
|
|
);
|
|
await scrolledPromise;
|
|
ok(true, "scroll position at drag down from option");
|
|
|
|
// Dragging above the popup scrolls it up.
|
|
scrolledPromise = BrowserTestUtils.waitForEvent(
|
|
selectPopup,
|
|
"scroll",
|
|
false,
|
|
() => getScrollPos() < scrollPos - 5
|
|
);
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.top - 20,
|
|
{
|
|
type: "mousemove",
|
|
buttons: 1,
|
|
},
|
|
win
|
|
);
|
|
await scrolledPromise;
|
|
ok(true, "scroll position at drag up from option");
|
|
|
|
scrollPos = getScrollPos();
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.bottom + 25,
|
|
{ type: "mouseup" },
|
|
win
|
|
);
|
|
is(
|
|
getScrollPos(),
|
|
scrollPos,
|
|
"scroll position at mouseup from option should not change"
|
|
);
|
|
|
|
EventUtils.synthesizeMouseAtPoint(
|
|
popupRect.left + 20,
|
|
popupRect.bottom + 20,
|
|
{ type: "mousemove" },
|
|
win
|
|
);
|
|
is(
|
|
getScrollPos(),
|
|
scrollPos,
|
|
"scroll position at mousemove after mouseup should not change"
|
|
);
|
|
|
|
await hideSelectPopup("escape", win);
|
|
|
|
let positions = [
|
|
"margin-top: 300px;",
|
|
"position: fixed; bottom: 200px;",
|
|
"width: 100%; height: 9999px;",
|
|
];
|
|
|
|
let position;
|
|
while (positions.length) {
|
|
await openSelectPopup("key", "select", win);
|
|
|
|
let rect = selectPopup.getBoundingClientRect();
|
|
let marginBottom = parseFloat(getComputedStyle(selectPopup).marginBottom);
|
|
let marginTop = parseFloat(getComputedStyle(selectPopup).marginTop);
|
|
ok(
|
|
rect.top - marginTop >= browserRect.top,
|
|
"Popup top position in within browser area"
|
|
);
|
|
ok(
|
|
rect.bottom + marginBottom <= browserRect.bottom,
|
|
"Popup bottom position in within browser area"
|
|
);
|
|
|
|
let cs = win.getComputedStyle(selectPopup);
|
|
let csArrow = win.getComputedStyle(selectPopup.scrollBox);
|
|
let bpBottom =
|
|
parseFloat(cs.paddingBottom) +
|
|
parseFloat(cs.borderBottomWidth) +
|
|
parseFloat(csArrow.paddingBottom) +
|
|
parseFloat(csArrow.borderBottomWidth);
|
|
let selectedOption = 60;
|
|
|
|
if (Services.prefs.getBoolPref("dom.forms.selectSearch")) {
|
|
// Use option 61 instead of 60, as the 60th option element is actually the
|
|
// 61st child, since the first child is now the search input field.
|
|
selectedOption = 61;
|
|
}
|
|
// Some of the styles applied to the menuitems are percentages, meaning
|
|
// that the final layout calculations returned by getBoundingClientRect()
|
|
// might return floating point values. We don't care about sub-pixel
|
|
// accuracy, and only care about the final pixel value, so we add a
|
|
// fuzz-factor of 1.
|
|
//
|
|
// FIXME(emilio): In win7 scroll position is off by 20px more, but that's
|
|
// not reproducible in win10 even with the win7 "native" menus enabled.
|
|
const fuzzFactor = matchMedia("(-moz-platform: windows-win7)").matches
|
|
? 21
|
|
: 1;
|
|
SimpleTest.isfuzzy(
|
|
selectPopup.children[selectedOption].getBoundingClientRect().bottom,
|
|
selectPopup.getBoundingClientRect().bottom - bpBottom + marginBottom,
|
|
fuzzFactor,
|
|
"Popup scroll at correct position " + bpBottom
|
|
);
|
|
|
|
await hideSelectPopup("enter", win);
|
|
|
|
position = positions.shift();
|
|
|
|
let contentPainted = BrowserTestUtils.waitForContentEvent(
|
|
browser,
|
|
"MozAfterPaint"
|
|
);
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[position],
|
|
async function (contentPosition) {
|
|
let select = content.document.getElementById("one");
|
|
select.setAttribute("style", contentPosition || "");
|
|
select.getBoundingClientRect();
|
|
}
|
|
);
|
|
await contentPainted;
|
|
}
|
|
|
|
if (navigator.platform.indexOf("Mac") == 0) {
|
|
await SpecialPowers.spawn(browser, [], async function () {
|
|
let doc = content.document;
|
|
doc.body.style = "padding-top: 400px;";
|
|
|
|
let select = doc.getElementById("one");
|
|
select.options[41].selected = true;
|
|
select.focus();
|
|
});
|
|
|
|
await openSelectPopup("key", "select", win);
|
|
|
|
ok(
|
|
selectPopup.getBoundingClientRect().top >
|
|
browser.getBoundingClientRect().top,
|
|
"select popup appears over selected item"
|
|
);
|
|
|
|
await hideSelectPopup("escape", win);
|
|
}
|
|
}
|
|
|
|
// This test checks select elements with a large number of options to ensure that
|
|
// the popup appears within the browser area.
|
|
add_task(async function test_large_popup() {
|
|
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
|
|
|
|
await performLargePopupTests(window);
|
|
|
|
BrowserTestUtils.removeTab(tab);
|
|
});
|
|
|
|
// This test checks the same as the previous test but in a new, vertically smaller window.
|
|
add_task(async function test_large_popup_in_small_window() {
|
|
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
|
|
|
let resizePromise = BrowserTestUtils.waitForEvent(
|
|
newWin,
|
|
"resize",
|
|
false,
|
|
e => {
|
|
info(`Got resize event (innerHeight: ${newWin.innerHeight})`);
|
|
return newWin.innerHeight <= 450;
|
|
}
|
|
);
|
|
newWin.resizeTo(600, 450);
|
|
await resizePromise;
|
|
|
|
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
|
|
let browserLoadedPromise = BrowserTestUtils.browserLoaded(
|
|
newWin.gBrowser.selectedBrowser
|
|
);
|
|
BrowserTestUtils.loadURIString(newWin.gBrowser.selectedBrowser, pageUrl);
|
|
await browserLoadedPromise;
|
|
|
|
newWin.gBrowser.selectedBrowser.focus();
|
|
|
|
await performLargePopupTests(newWin);
|
|
|
|
await BrowserTestUtils.closeWindow(newWin);
|
|
});
|