Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!doctype html>
<!-- Any copyright is dedicated to the Public Domain.
<html>
<head>
<meta charset="utf-8" />
<title>Test Panel List Context Menu</title>
<link
rel="stylesheet"
/>
</head>
<body>
<p id="display"></p>
<div id="content">
<button id="anchor-button">Anchor</button>
<panel-list id="panel-list">
<panel-item>one</panel-item>
<panel-item>two</panel-item>
</panel-list>
</div>
<script class="testbody" type="application/javascript">
const { BrowserTestUtils } = ChromeUtils.importESModule(
);
let anchorButton, panelList;
add_setup(async function setup() {
await customElements.whenDefined("panel-list");
await customElements.whenDefined("panel-item");
panelList = document.getElementById("panel-list");
anchorButton = document.getElementById("anchor-button");
anchorButton.addEventListener("contextmenu", e => panelList.show(e));
});
// A contextmenu event is dispatched during the button press on most
// platforms, so the panel opens between the pointerdown and the pointerup.
// An auto popover would be light dismissed by that pointerup, since the
// pointer is still outside the panel.
add_task(async function testContextMenuSurvivesTriggeringMouseUp() {
let shown = BrowserTestUtils.waitForEvent(panelList, "shown");
// Press near the anchor's top left, which the panel opening below it
// won't cover, so the release lands outside the panel.
synthesizeMouse(anchorButton, 2, 2, { type: "mousedown", button: 2 });
synthesizeMouse(anchorButton, 2, 2, { type: "contextmenu" });
await shown;
is(
panelList.getAttribute("popover"),
"manual",
"A contextmenu-triggered panel should not be light dismissable"
);
ok(panelList.matches(":popover-open"), "Panel should be open");
synthesizeMouse(anchorButton, 2, 2, { type: "mouseup", button: 2 });
// Let light dismiss run for the mouseup before asserting.
await new Promise(resolve =>
requestAnimationFrame(() => setTimeout(resolve, 0))
);
ok(
panelList.matches(":popover-open"),
"Panel should still be open after the triggering mouseup"
);
ok(panelList.open, "Panel open attribute should still be true");
});
async function reopen() {
if (panelList.open) {
let hidden = BrowserTestUtils.waitForEvent(panelList, "hidden");
panelList.hide(undefined, { force: true });
await hidden;
}
let shown = BrowserTestUtils.waitForEvent(panelList, "shown");
panelList.show(
new PointerEvent("contextmenu", { bubbles: true }),
anchorButton
);
await shown;
}
function dispatchContextMenuInPanel() {
let event = new PointerEvent("contextmenu", {
bubbles: true,
cancelable: true,
composed: true,
});
panelList.querySelector("panel-item").dispatchEvent(event);
return event;
}
add_task(async function testContextMenuSuppressedWithTheAttribute() {
panelList.setAttribute("suppress-contextmenu", "");
// The listener is registered as the panel opens.
await reopen();
let event = dispatchContextMenuInPanel();
ok(
event.defaultPrevented,
"A contextmenu event in the panel should be prevented"
);
ok(panelList.open, "Panel should stay open");
panelList.removeAttribute("suppress-contextmenu");
});
add_task(async function testContextMenuPassesWithoutTheAttribute() {
await reopen();
let event = dispatchContextMenuInPanel();
ok(
!event.defaultPrevented,
"A contextmenu event in the panel should be left alone"
);
ok(panelList.open, "Panel should stay open");
});
</script>
</body>
</html>