Update web-platform-tests to revision b'b728032f59a396243864b0f8584e7211e3632005'

This commit is contained in:
WPT Sync Bot 2022-11-10 01:22:36 +00:00
parent ace9b32b1c
commit df68c4e5d1
15632 changed files with 514865 additions and 155000 deletions

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<link rel=author href="mailto:vmpstr@chromium.org">
<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1334983">
<canvas>
<details>
<card card>
<script>
async function trigger() {
document.querySelector("canvas").style.setProperty("container-type", "size");
document.querySelector("canvas").style.setProperty("column-span", "all");
document.querySelector("card").setAttribute("contenteditable", "true");
}
onload = requestAnimationFrame(() => requestAnimationFrame(trigger));
</script>

View file

@ -0,0 +1,52 @@
<!doctype html>
<meta charset="utf-8">
<title>Details activation with space bar</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1726454">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<style>
:root {
scroll-behavior: instant;
}
.spacer {
height: 200vh;
}
</style>
<details>
<summary>Activate me with the <kbd>Space</kbd> key</summary>
<p>Summary</p>
</details>
<div class="spacer"></div>
<script>
function tick() {
return new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
}
promise_test(async t => {
const details = document.querySelector("details");
const summary = details.querySelector("summary");
summary.focus();
assert_equals(document.activeElement, summary, "Summary should be focusable");
assert_false(details.open, "Details should be closed");
const oldScrollY = window.scrollY;
assert_equals(oldScrollY, 0, "Should be at top");
window.addEventListener("scroll", t.unreached_func("Unexpected scroll event"));
await test_driver.send_keys(summary, " ");
assert_true(details.open, "Space bar on summary should open details");
assert_equals(window.scrollY, oldScrollY, "Scroll position shouldn't change");
await tick();
assert_equals(window.scrollY, oldScrollY, "Scroll position shouldn't change");
});
</script>

View file

@ -32,7 +32,12 @@
<summary>Lorem ipsum</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</details>
<details id=details9 open>
<script>
window.details9TogglePromise = new Promise(resolve => {
window.details9TogglePromiseResolver = resolve;
});
</script>
<details id=details9 ontoggle="window.details9TogglePromiseResolver()" open>
<summary>Lorem ipsum</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</details>
@ -128,22 +133,20 @@
});
details8.removeAttribute('open'); // closes details8
var toggleFiredOnDetails9 = false;
details9.ontoggle = t9.step_func_done(function(evt) {
if (toggleFiredOnDetails9) {
window.details9TogglePromise.then(t9.step_func(() => {
// The toggle event should be fired once when declaring details9 with open
// attribute.
details9.ontoggle = t9.step_func(() => {
assert_unreached("toggle event fired twice on opened details element");
} else {
toggleFiredOnDetails9 = true;
}
});
// The toggle event should be fired once when declaring details9 with open
// attribute.
details9.open = true; // opens details9
t9.step_timeout(function() {
assert_true(details9.open);
assert_true(toggleFiredOnDetails9);
t9.done();
}, 0);
});
// setting open=true on details9 should not fire another event since it is
// already open.
details9.open = true;
t9.step_timeout(() => {
assert_true(details9.open);
t9.done();
});
}));
details10.ontoggle = t10.step_func_done(function(evt) {
assert_unreached("toggle event fired on closed details element");

View file

@ -0,0 +1,35 @@
<!doctype html>
<meta charset=utf-8>
<title>Test for dialog element colors</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
:root { background-color: Canvas; color: CanvasText; }
#light { color-scheme: light }
#dark { color-scheme: dark }
</style>
<dialog id="dialog" open>
This is a dialog
</dialog>
<dialog id="light" open>
This is a dialog
</dialog>
<dialog id="dark" open>
This is a dialog
</dialog>
<script>
test(function() {
let dialog = document.getElementById("dialog");
let cs = getComputedStyle(dialog);
let rootCs = getComputedStyle(document.documentElement);
assert_equals(cs.color, rootCs.color, "Dialog color should match CanvasText");
assert_equals(cs.backgroundColor, rootCs.backgroundColor, "Dialog background should match Canvas");
}, "<dialog> color and background match default")
test(function() {
let lightCs = getComputedStyle(document.getElementById("light"));
let darkCs = getComputedStyle(document.getElementById("dark"));
assert_not_equals(lightCs.color, darkCs.color, "Dialog color should react to color-scheme");
assert_not_equals(lightCs.backgroundColor, darkCs.backgroundColor, "Dialog background should react to color-scheme");
}, "<dialog> colors react to dark mode")
</script>

View file

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<title>Test cancel event is fired when the dialog is closed by user interaction</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=227534">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322947">
</head>
<body>
<p>Test cancel event is fired when the dialog is closed by user interaction</p>
<dialog>
<p>Hello World</p>
<button>user activation button</button>
</dialog>
<script>
setup({ single_test: true });
var hasCancelEventFired = false;
var hasCloseEventFired = false;
const dialog = document.querySelector("dialog");
dialog.addEventListener("cancel", function(event) {
assert_true(true, "cancel event is fired");
assert_true(event.cancelable, "cancel event should be cancelable");
assert_false(hasCancelEventFired, "cancel event should only be fired once");
assert_false(hasCloseEventFired, "close event should be fired after cancel event");
hasCancelEventFired = true;
});
dialog.addEventListener("close", function() {
assert_true(true, "close event is fired");
assert_false(hasCloseEventFired, "close event should only be fired once");
assert_true(hasCancelEventFired, "cancel event should be fired before close event");
hasCloseEventFired = true;
done();
});
dialog.showModal();
(async () => {
// Pressing escape on the dialog needs user activation or else the cancel event won't be fired.
const button = dialog.querySelector('button');
const buttonClickPromise = new Promise(resolve => button.onclick = resolve);
await test_driver.click(button);
await buttonClickPromise;
test_driver.send_keys(document.documentElement, "\uE00C"); // ESC key
})();
</script>
</body>
</html>

View file

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<title>Test cancel event with preventDefault on cancel event for dialog element</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=227534">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322947">
</head>
<body>
<p>Test cancel event with preventDefault on cancel event for dialog element</p>
<dialog>
<p>Hello World</p>
<button>user activation button</button>
</dialog>
<script>
setup({ single_test: true });
var hasCancelEventFired = false;
const dialog = document.querySelector("dialog");
const verify = () => {
assert_true(hasCancelEventFired, "cancel is fired");
done();
};
dialog.addEventListener("cancel", function(event) {
hasCancelEventFired = true;
event.preventDefault();
step_timeout(function() {
verify();
}, 0)
});
dialog.addEventListener("close", function() {
assert_true(false, "close event should not be fired");
});
dialog.showModal();
(async () => {
// Pressing escape on the dialog needs user activation or else the cancel event won't be fired.
const button = dialog.querySelector('button');
const buttonClickPromise = new Promise(resolve => button.onclick = resolve);
await test_driver.click(button);
await buttonClickPromise;
test_driver.send_keys(document.documentElement, "\uE00C"); // ESC key
})();
</script>
</body>
</html>

View file

@ -1,12 +1,12 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>dialog focusing delegation with autofocus plus delegatesFocus inside the dialog</title>
<title>dialog focusing delegation: with two nested shadow trees</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<dialog>
<template class="turn-into-shadow-tree">
<template class="turn-into-shadow-tree delegates-focus">
<button disabled>Non-focusable</button>
<template class="turn-into-shadow-tree delegates-focus">
<button tabindex="-1">Focusable</button>

View file

@ -1,62 +1,256 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>dialog focus delegation</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<dialog data-description="When autofocus is not present, the first focusable shadow-including descendant must be focused">
<template class="turn-into-shadow-tree">
<button disabled>Non-focusable</button>
<button tabindex="-1" class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<!--
We focus this one between each test, to ensure that for non-modal dialogs,
if there is no focus delegate, it stays focused (instead of causing focus to reset to the body).
-->
<button tabindex="-1" id="focus-between-tests">Focus between tests</button>
<dialog data-description="autofocus outside a shadow tree must take precedence over earlier in-shadow-tree focusable elements">
<button disabled>Non-focusable</button>
<dialog data-description="No autofocus, no delegatesFocus, no siblings">
<template class="turn-into-shadow-tree">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1" autofocus>Focusable</button>
</dialog>
<dialog data-description="autofocus inside a shadow tree must be ignored: no focusable elements outside the shadow tree">
<dialog data-description="No autofocus, no delegatesFocus, sibling before">
<button tabindex="-1" class="focus-me">Focusable</button>
<template class="turn-into-shadow-tree">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="No autofocus, no delegatesFocus, sibling after">
<template class="turn-into-shadow-tree">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1" class="focus-me">Focusable</button>
</dialog>
<dialog data-description="No autofocus, yes delegatesFocus, no siblings">
<template class="turn-into-shadow-tree delegates-focus">
<button disabled>Non-focusable</button>
<button tabindex="-1" class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="No autofocus, yes delegatesFocus, sibling before">
<button tabindex="-1" class="focus-me">Focusable</button>
<template class="turn-into-shadow-tree delegates-focus">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="No autofocus, yes delegatesFocus, sibling after">
<template class="turn-into-shadow-tree delegates-focus">
<button disabled>Non-focusable</button>
<button tabindex="-1" class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1">Focusable</button>
</dialog>
<dialog data-description="Autofocus before, no delegatesFocus">
<button tabindex="-1" autofocus class="focus-me">Focusable</button>
<template class="turn-into-shadow-tree">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus before, yes delegatesFocus">
<button tabindex="-1" autofocus class="focus-me">Focusable</button>
<template class="turn-into-shadow-tree delegates-focus">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus after, no delegatesFocus">
<template class="turn-into-shadow-tree">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1" autofocus class="focus-me">Focusable</button>
</dialog>
<dialog data-description="Autofocus after, yes delegatesFocus">
<template class="turn-into-shadow-tree delegates-focus">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1" autofocus class="focus-me">Focusable</button>
</dialog>
<dialog data-description="Autofocus on shadow host, yes delegatesFocus, no siblings">
<template class="turn-into-shadow-tree delegates-focus autofocus">
<button disabled>Non-focusable</button>
<button tabindex="-1" class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus on shadow host, yes delegatesFocus, sibling before">
<button tabindex="-1">Focusable</button>
<template class="turn-into-shadow-tree delegates-focus autofocus">
<button disabled>Non-focusable</button>
<button tabindex="-1" class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus on shadow host, yes delegatesFocus, sibling after">
<template class="turn-into-shadow-tree delegates-focus autofocus">
<button disabled>Non-focusable</button>
<button tabindex="-1" class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1">Focusable</button>
</dialog>
<dialog data-description="Autofocus on shadow host, no delegatesFocus, no siblings">
<template class="turn-into-shadow-tree autofocus">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus on shadow host, no delegatesFocus, sibling before">
<button tabindex="-1" class="focus-me">Focusable</button>
<template class="turn-into-shadow-tree autofocus">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus on shadow host, no delegatesFocus, sibling after">
<template class="turn-into-shadow-tree autofocus">
<button disabled>Non-focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1" class="focus-me">Focusable</button>
</dialog>
<dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, no siblings">
<template class="turn-into-shadow-tree delegates-focus">
<button tabindex="-1">Focusable</button>
<button tabindex="-1" autofocus class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, sibling before">
<button tabindex="-1" class="focus-me">Focusable</button>
<template class="turn-into-shadow-tree delegates-focus">
<button tabindex="-1">Focusable</button>
<button tabindex="-1" autofocus>Focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="autofocus inside a shadow tree must be ignored: focusable element before the shadow tree">
<dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, sibling after">
<template class="turn-into-shadow-tree delegates-focus">
<button tabindex="-1">Focusable</button>
<button tabindex="-1" autofocus class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1">Focusable</button>
</dialog>
<dialog data-description="Autofocus inside shadow tree, no delegatesFocus, no siblings">
<template class="turn-into-shadow-tree">
<button tabindex="-1">Focusable</button>
<button tabindex="-1" autofocus>Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="Autofocus inside shadow tree, no delegatesFocus, sibling before">
<button tabindex="-1" class="focus-me">Focusable</button>
<template class="turn-into-shadow-tree">
<button tabindex="-1">Focusable</button>
<button tabindex="-1" autofocus>Focusable</button>
<button tabindex="-1">Focusable</button>
<button disabled>Non-focusable</button>
</template>
</dialog>
<dialog data-description="autofocus inside a shadow tree must be ignored: focusable element after the shadow tree">
<dialog data-description="Autofocus inside shadow tree, no delegatesFocus, sibling after">
<template class="turn-into-shadow-tree">
<button tabindex="-1">Focusable</button>
<button tabindex="-1" autofocus>Focusable</button>
<button disabled>Non-focusable</button>
</template>
<button tabindex="-1" class="focus-me">Focusable</button>
</dialog>
<dialog data-description="Two shadow trees, both delegatesFocus, first tree doesn't have autofocus element, second does">
<template class="turn-into-shadow-tree delegates-focus">
<button disabled>Non-focusable</button>
<button tabindex="-1" class="focus-me">Focusable</button>
<button disabled>Non-focusable</button>
</template>
<template class="turn-into-shadow-tree delegates-focus">
<button tabindex="-1" autofocus>Focusable</button>
</template>
</dialog>
<dialog data-description="No autofocus, no delegatesFocus, slotted target">
<template class="turn-into-shadow-tree">
<button tabindex="-1">Focusable</button>
<slot></slot>
<button tabindex="-1">Focusable</button>
</template>
<button tabindex="-1" class="focus-me">Focusable</button>
</dialog>
<dialog data-description="Shadowroot on child, no autofocus, no delegatesFocus">
<div>
<template class="turn-into-shadow-tree">
<button tabindex="-1">Focusable</button>
</template>
</div>
<button tabindex="-1" class="focus-me">Focusable</button>
</dialog>
<script>
for (const template of document.querySelectorAll(".turn-into-shadow-tree")) {
const div = document.createElement("div");
div.attachShadow({ mode: "open" });
div.attachShadow({ mode: "open", delegatesFocus: template.classList.contains("delegates-focus") });
if (template.classList.contains("autofocus")) {
div.setAttribute("autofocus", true);
}
div.shadowRoot.append(template.content);
template.replaceWith(div);
}
const focusBetweenTests = document.querySelector("#focus-between-tests");
for (const dialog of document.querySelectorAll("dialog")) {
for (const method of ["show", "showModal"]) {
test(t => {
focusBetweenTests.focus();
dialog[method]();
t.add_cleanup(() => dialog.close());
@ -66,10 +260,17 @@ for (const dialog of document.querySelectorAll("dialog")) {
} else {
const shadowHost = dialog.querySelector("div");
const expectedFocusInsideShadowTree = shadowHost.shadowRoot.querySelector(".focus-me");
assert_not_equals(expectedFocusInsideShadowTree, "Precondition check: the test was set up to expect a focused element, either outside the shadow tree or inside");
assert_equals(document.activeElement, shadowHost);
assert_equals(shadowHost.shadowRoot.activeElement, expectedFocusInsideShadowTree);
if (expectedFocusInsideShadowTree) {
assert_equals(document.activeElement, shadowHost);
assert_equals(shadowHost.shadowRoot.activeElement, expectedFocusInsideShadowTree);
} else {
// There is no focus delegate. Expected result depends on show() vs. showModal().
if (method === "show") {
assert_equals(document.activeElement, focusBetweenTests);
} else {
assert_equals(document.activeElement, document.body);
}
}
}
}, `${method}: ${dialog.dataset.description}`);
}

View file

@ -16,6 +16,7 @@ test(function() {
const dialog = document.createElement("dialog");
assert_false(dialog.open, "Dialog should initially be closed");
assert_false(dialog.hasAttribute('open'), "Dialog should initially be closed");
const innerInput = document.createElement("input");
innerInput.autofocus = true;
@ -23,6 +24,8 @@ test(function() {
dialog.show();
this.add_cleanup(() => { dialog.close(); });
assert_true(dialog.open, "Disconnected dialog can still be open");
assert_equals(document.activeElement, outerInput, "Focusing steps should not change focus");
}, "dialog.show(): focusing steps should not change focus on disconnected <dialog>");

View file

@ -1,35 +0,0 @@
<!DOCTYPE html>
<link rel=author href="mailto:jarhar@chromium.org">
<link rel=author href="mailto:falken@chromium.org">
<link rel=help href="https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element">
<link rel=help href="https://bugs.webkit.org/show_bug.cgi?id=97425">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<dialog id="mydialog">It's my dialog.</dialog>
<script>
test(() => {
const dialog = document.getElementById('mydialog');
const computedStyle = window.getComputedStyle(dialog, null);
assert_equals(computedStyle.display, 'none');
dialog.showModal();
assert_equals(computedStyle.display, 'block');
// The quoted texts output below are from <http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#dom-dialog-showmodal>.
assert_throws_dom('InvalidStateError', () => dialog.showModal());
dialog.close();
assert_equals(computedStyle.display, 'none');
dialog.parentNode.removeChild(dialog);
assert_throws_dom('InvalidStateError', () => dialog.showModal());
const doc = document.implementation.createHTMLDocument();
doc.body.appendChild(dialog);
assert_false(dialog.open);
dialog.showModal();
assert_true(dialog.open, 'Although the document is not attached to any pages, showModal() should execute as normal.');
}, 'Tests that showModal() performs the steps specified in the HTML spec.');
</script>

View file

@ -62,10 +62,12 @@
test(function(){
assert_false(d1.open);
assert_false(d1.hasAttribute("open"));
assert_equals(getComputedStyle(d1).display, "none");
d1.showModal();
this.add_cleanup(function() { d1.close(); });
assert_true(d1.open);
assert_equals(d1.getAttribute("open"), "");
assert_equals(getComputedStyle(d1).display, "block");
assert_equals(document.activeElement, b1);
});
@ -169,4 +171,18 @@
d11.close();
assert_equals(topElement(), d10);
}, "when opening multiple dialogs, the most recently opened is rendered on top");
test(function() {
assert_false(d11.open);
d11.parentNode.removeChild(d11);
assert_throws_dom("INVALID_STATE_ERR", () => d11.showModal());
const doc = document.implementation.createHTMLDocument();
doc.body.appendChild(d11);
this.add_cleanup(() => document.body.append(d11));
assert_false(d11.open);
d11.showModal();
assert_true(d11.open);
this.add_cleanup(() => d11.close());
}, "Although the document is not attached to any pages, showModal() should execute as normal.");
</script>

View file

@ -160,13 +160,17 @@ function test_move_to_shadow_host(showModal) {
}
// Test moving the focus doesn't scroll the viewport
function test_move_focus_dont_scroll_viewport(showModal) {
async function test_move_focus_dont_scroll_viewport(showModal) {
const outViewPortButton = document.createElement("button");
outViewPortButton.style.top = (window.innerHeight + 10).toString() + "px";
outViewPortButton.style.position = "absolute";
document.body.appendChild(outViewPortButton);
outViewPortButton.focus();
await new Promise(resolve => {
document.addEventListener("scroll", () => step_timeout(resolve, 0));
outViewPortButton.focus();
});
// Since the outViewPortButton is focused, so the viewport should be
// scrolled to it
assert_true(document.documentElement.scrollTop > 0 );
@ -217,9 +221,9 @@ test(() => {
test_move_to_shadow_host(false);
}, "Focus should be moved to the shadow DOM host if the previouly focused element is a shadow DOM node");
test(() => {
test_move_focus_dont_scroll_viewport(true);
test_move_focus_dont_scroll_viewport(false);
promise_test(async () => {
await test_move_focus_dont_scroll_viewport(true);
await test_move_focus_dont_scroll_viewport(false);
}, "Focus should not scroll if the previously focused element is outside the viewport");
</script>
</body>

View file

@ -37,7 +37,11 @@ promise_test(async () => {
let focusedElement = null;
element.addEventListener('focus', function() { focusedElement = element; }, false);
element.focus();
assert_equals(focusedElement === element, expectFocus, element.id);
if (expectFocus) {
assert_equals(focusedElement, element, element.id);
} else {
assert_not_equals(focusedElement, element, element.id);
}
}
// Opening a modal dialog in frame1. It blocks other nodes in its document.
@ -46,7 +50,7 @@ promise_test(async () => {
testFocus(frame1.querySelector('.target'), false);
const iframe = frame1.querySelector('#iframe1').contentDocument;
testFocus(iframe.querySelector('.target'), false);
testFocus(iframe.querySelector('.target'), true);
// Even a modal dialog in the iframe is blocked by the modal dialog in the parent frame1.
iframe.querySelector('dialog').showModal();

View file

@ -0,0 +1,68 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Hit-testing with SVG made inert by modal dialog</title>
<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#inert">
<meta assert="assert" content="SVG made inert by modal dialog should be unreachable with hit-testing">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<div id="wrapper">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
<rect width="500" height="500" id="target" fill="red">
</svg>
</div>
<dialog id="dialog">Content behind the open modal dialog should not be clickable</dialog>
<style>
dialog::backdrop {
display: none;
}
</style>
<script>
const dialog = document.getElementById("dialog");
const wrapper = document.getElementById("wrapper");
const target = document.getElementById("target");
promise_test(async function() {
dialog.showModal();
this.add_cleanup(() => dialog.close());
let reachedTarget = false;
target.addEventListener("mousedown", () => {
reachedTarget = true;
}, { once: true });
let wrapperRect = wrapper.getBoundingClientRect();
await new test_driver.Actions()
.pointerMove(wrapperRect.x + 1, wrapperRect.y + 1, { origin: "viewport" })
.pointerDown()
.send();
assert_false(target.matches(":active"), "target is not active");
assert_false(target.matches(":hover"), "target is not hovered");
assert_false(reachedTarget, "target didn't get event");
}, "Hit-testing doesn't reach contents of an inert SVG");
promise_test(async function() {
assert_false(dialog.open, "dialog is closed");
let reachedTarget = false;
target.addEventListener("mousedown", () => {
reachedTarget = true;
}, { once: true });
await new test_driver.Actions()
.pointerMove(0, 0, { origin: wrapper })
.pointerDown()
.send();
assert_true(target.matches(":active"), "target is active");
assert_true(reachedTarget, "target got event");
}, "Hit-testing can reach contents of a no longer inert SVG");
</script>

View file

@ -4,9 +4,8 @@
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#inert">
<meta name="assert" content="Checks that a modal dialog marks outer nodes as inert,
but only in its document, not in the parent browsing context.
Also, when an iframe is marked as inert by a modal dialog,
all contents in the nested browsing context are marked as inert too.">
but only in its document, not in the parent browsing context,
nor in nested browsing contexts.">
<div id="log"></div>
<div id="wrapper">
(main document: outer text)
@ -103,30 +102,30 @@ promise_test(async function() {
checkSelection(window, "(main document: dialog)");
checkSelection(innerIframeWindow, "(inner iframe: outer text)(inner iframe: dialog)");
checkSelection(outerIframeWindow, "");
}, "Modal dialog in the main document marks outer nodes as inert. All contents of the outer iframe are also marked as inert.");
checkSelection(outerIframeWindow, "(outer iframe: outer text)(outer iframe: dialog)");
}, "Modal dialog in the main document marks outer nodes as inert. Contents of the outer iframe aren't marked as inert.");
promise_test(async function() {
showModals(this, [innerIframeWindow, window]);
checkSelection(window, "(main document: dialog)");
checkSelection(innerIframeWindow, "(inner iframe: dialog)");
checkSelection(outerIframeWindow, "");
}, "Modal dialogs in the main document and inner iframe mark outer nodes as inert. All contents of the outer iframe are also marked as inert.");
checkSelection(outerIframeWindow, "(outer iframe: outer text)(outer iframe: dialog)");
}, "Modal dialogs in the main document and inner iframe mark outer nodes as inert. Contents of the outer iframe aren't marked as inert.");
promise_test(async function() {
showModals(this, [outerIframeWindow, window]);
checkSelection(window, "(main document: dialog)");
checkSelection(innerIframeWindow, "(inner iframe: outer text)(inner iframe: dialog)");
checkSelection(outerIframeWindow, "");
}, "Modal dialogs in the main document and outer iframe mark outer nodes as inert. All contents of the outer iframe are also marked as inert.");
checkSelection(outerIframeWindow, "(outer iframe: dialog)");
}, "Modal dialogs in the main document and outer iframe mark outer nodes as inert. Contents of the outer iframe aren't marked as inert.");
promise_test(async function() {
showModals(this, [innerIframeWindow, outerIframeWindow, window]);
checkSelection(window, "(main document: dialog)");
checkSelection(innerIframeWindow, "(inner iframe: dialog)");
checkSelection(outerIframeWindow, "");
}, "Modal dialogs in the main document and both iframes mark outer nodes as inert. All contents of the outer iframe are also marked as inert.");
checkSelection(outerIframeWindow, "(outer iframe: dialog)");
}, "Modal dialogs in the main document and both iframes mark outer nodes as inert. Contents of the outer iframe aren't marked as inert.");
</script>

View file

@ -47,7 +47,9 @@ promise_test(async () => {
async function clickOn(element) {
const rect = element.getBoundingClientRect();
const actions = new test_driver.Actions()
.pointerMove(rect.left + rect.width / 2, rect.top + rect.height / 2)
.pointerMove(
Math.floor(rect.left + rect.width / 2),
Math.floor(rect.top + rect.height / 2))
.pointerDown()
.pointerUp()
.pointerMove(0, 0);

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<title>Modal dialog inside iframe should not generate box</title>
<link rel=match href="modal-dialog-in-iframe-ref.html">
<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939">
<link rel=help href="https://fullscreen.spec.whatwg.org/#new-stacking-layer">
<style>
dialog {
background: red;
border-color: red;
}
</style>
<iframe></iframe>
<script>
const iframe = document.querySelector('iframe');
const dialog = document.createElement('dialog');
iframe.appendChild(dialog);
dialog.showModal();
</script>

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
<object width="200" type="image/svg+xml" data="../../../../images/100px-green-rect.svg"></object>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<title>Modal dialog inside object should not generate box</title>
<link rel=match href="modal-dialog-in-object-ref.html">
<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939">
<link rel=help href="https://fullscreen.spec.whatwg.org/#new-stacking-layer">
<style>
dialog {
background: green;
border-color: green;
}
</style>
<object width="200" type="image/svg+xml" data="../../../../images/100px-green-rect.svg">
<dialog id="dialog"></dialog>
</object>
<script>
document.getElementById('dialog').showModal();
</script>

View file

@ -12,13 +12,7 @@ div {
</style>
</head>
<body>
<p>Bug <a href="http://webkit.org/b/103477">103477</a>: Make
NodeRenderingContext::parentRenderer and nextRenderer top layer aware
<p>The test passes if you see a green square near the top and green rectangle in the center of the viewport.
<p>The test passes if you see a green square near the top of the viewport.
<div></div>
<dialog id="dialog"></dialog>
<script>
document.getElementById('dialog').showModal();
</script>
</body>
</html>

View file

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Modal dialog inside replaced renderer should not generate box</title>
<link rel="match" href="modal-dialog-in-replaced-renderer-ref.html">
<link rel="help" href="https://fullscreen.spec.whatwg.org/#new-stacking-layer">
<style>
@ -14,9 +15,7 @@ div {
</style>
</head>
<body>
<p>Bug <a href="http://webkit.org/b/103477">103477</a>: Make
NodeRenderingContext::parentRenderer and nextRenderer top layer aware
<p>The test passes if you see a green square near the top and green rectangle in the center of the viewport.
<p>The test passes if you see a green square near the top of the viewport.
<div>
<dialog id="dialog"></dialog>
</div>

View file

@ -9,12 +9,6 @@ dialog {
</style>
</head>
<body>
<p>Bug <a href="http://webkit.org/b/103477">103477</a>: Make
NodeRenderingContext::parentRenderer and nextRenderer top layer aware
<p>The test passes if you see a green rectangle in the center of the viewport.
<dialog id="dialog"></dialog>
<script>
document.getElementById('dialog').showModal();
</script>
<p>The test passes if you see no green rectangle.
</body>
</html>

View file

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Modal dialog inside display: table-column should not generate box</title>
<link rel="match" href="modal-dialog-in-table-column-ref.html">
<link rel="help" href="https://fullscreen.spec.whatwg.org/#new-stacking-layer">
<style>
@ -14,9 +15,7 @@ div {
</style>
</head>
<body>
<p>Bug <a href="http://webkit.org/b/103477">103477</a>: Make
NodeRenderingContext::parentRenderer and nextRenderer top layer aware
<p>The test passes if you see a green rectangle in the center of the viewport.
<p>The test passes if you see no green rectangle.
<div>
<dialog id="dialog"></dialog>
</div>

View file

@ -0,0 +1,68 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Content selection in modal dialog</title>
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-ui-4/#content-selection">
<meta name="assert" content="Checks that text can be selected in a modal dialog, except with 'user-select: none'.">
<link rel="stylesheet" href="/fonts/ahem.css">
<style>
dialog {
font: 10px/1 Ahem;
text-align: center;
}
</style>
<dialog>123456789A</dialog>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script>
const dialog = document.querySelector("dialog");
dialog.showModal();
function selectSomeText() {
// Clear existing selection.
getSelection().removeAllRanges();
// The dialog contains 10 characters. Select the 6 ones at the center.
return new test_driver.Actions()
.pointerMove(-3e1, 0, {origin: dialog})
.pointerDown()
.pointerMove(+3e1, 0, {origin: dialog})
.pointerUp()
.send();
}
function clickOnBackdrop() {
getSelection().removeAllRanges();
return new test_driver.Actions()
.pointerMove(10, 10)
.pointerDown()
.pointerUp()
.send();
}
promise_test(async function() {
await selectSomeText();
assert_equals(getSelection().toString(), "345678");
}, "By default, text inside a modal dialog can be selected");
promise_test(async function() {
await clickOnBackdrop();
assert_equals(getSelection().toString(), "");
}, "Clicking on backdrop doesn't select text");
promise_test(async function() {
dialog.style.userSelect = "none";
await selectSomeText();
assert_equals(getSelection().toString(), "");
dialog.style.userSelect = "";
}, "'user-select: none' prevents text from being selected");
</script>

View file

@ -28,14 +28,32 @@ dialog {
<script>
test(() => {
function documentHeight() {
// clientHeight is an integer, but we want the correct floating point
// value. Start a binary search at clientHeight-1 and clientHeight+1.
let min = document.documentElement.clientHeight;
let max = min + 1;
--min;
// binary search with media queries to find the correct height
for (let iter = 0; iter < 10; ++iter) {
let test = (min + max) / 2;
if (window.matchMedia(`(min-height: ${test}px)`).matches)
min = test;
else
max = test;
}
return min;
}
function expectedTop(dialog) {
return Math.floor((document.documentElement.clientHeight - dialog.offsetHeight) / 2);
let height = documentHeight();
return (height - dialog.getBoundingClientRect().height) / 2;
}
function showAndTest(id) {
dialog = document.getElementById(id);
dialog.showModal();
assert_equals(dialog.offsetTop, expectedTop(dialog), id);
assert_approx_equals(dialog.getBoundingClientRect().top, expectedTop(dialog), 0.05, id);
}
showAndTest('top-dialog');

View file

@ -1,16 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<button id=b1>This is an anchor button</button>
<popup id=p1 anchor=b1>This is a popup</popup>
<button id=b2 popup=p1>This button invokes the popup but isn't an anchor</button>
<script>
test(function() {
assert_equals(p1.anchor,b1);
}, "popup anchor IDL property returns the anchor element");
</script>

View file

@ -1,61 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup anchor nesting</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<body>
<!-- This example has the anchor (b1) for one popup (p1)
which contains a separate popup (p2) which is anchored
by a separate anchor (b2). -->
<button id=b1 onclick='p1.show()'>Popup 1
<popup id=p2 anchor=b2>
<span id=inside2>Inside popup 2</span>
</popup>
</button>
<popup id=p1 anchor=b1>This is popup 1</popup>
<button id=b2 onclick='p2.show()'>Popup 2</button>
<style>
#p1 { top:50px; }
#p2 { top:50px; left:250px; }
popup { border: 5px solid red; }
</style>
<script>
function clickOn(element) {
const actions = new test_driver.Actions();
return actions.pointerMove(0, 0, {origin: element})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
}
const popup1 = document.querySelector('#p1');
const button1 = document.querySelector('#b1');
const popup2 = document.querySelector('#p2');
(async function() {
setup({ explicit_done: true });
popup2.show();
assert_false(popup1.open);
assert_true(popup2.open);
await clickOn(button1);
test(t => {
// Button1 is the anchor for popup1, and an ancestor of popup2.
// Since popup2 is open, but not popup1, button1 should not be
// the anchor of any open popup. So popup2 should be closed.
assert_false(popup2.open);
},'Nested popups (inside anchor elements) do not affect light dismiss');
done();
})();
</script>

View file

@ -1,50 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<popup id=p1>This is a popup</popup>
<popup id=p2 open>This is another popup, with an unused "open" attribute</popup>
<script>
test(function() {
assert_true(document.createElement('popup') instanceof HTMLPopupElement);
}, "popup element exists")
const popup1 = document.getElementById('p1');
const popup2 = document.getElementById('p2');
function popupVisible(popup) {
return !!(popup.offsetWidth || popup.offsetHeight || popup.getClientRects().length);
}
test(function(){
assert_false(popup1.open);
assert_false(popup2.open);
}, 'The IDL "open" content attribute must have no effect, and must not be reflected to the WebIDL.');
test(function(){
assert_false(popup1.open);
assert_false(popup1.hasAttribute("open"));
assert_false(popupVisible(popup1));
popup1.open = true; // Should have no effect
assert_false(popup1.open);
assert_false(popupVisible(popup1));
popup1.show();
assert_true(popup1.open);
assert_false(popup1.hasAttribute("open"));
assert_true(popupVisible(popup1));
popup1.open = false; // Should have no effect
assert_true(popup1.open);
popup1.hide();
assert_false(popup1.open);
assert_false(popup1.hasAttribute("open"));
assert_false(popupVisible(popup1));
popup1.setAttribute("open","");
assert_false(popup1.open,'Setting open attribute should not reflect to the WebIDL');
assert_true(popup1.hasAttribute("open"));
assert_false(popupVisible(popup1));
}, "The only visibility control for <popup> is through .show() and .hide().");
</script>

View file

@ -1,44 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup keyboard focus behaviors</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<button id=firstfocus>Button 1</button>
<popup>
<p>This is a popup without a focusable element</p>
</popup>
<button id=secondfocus>Button 2</button>
<script>
promise_test(async () => {
const b1 = document.getElementById('firstfocus');
const b2 = document.getElementById('secondfocus');
const popup = document.querySelector('popup');
b1.focus();
assert_equals(document.activeElement,b1);
popup.show();
assert_true(popup.open);
assert_equals(document.activeElement,b1);
// Tab once
await new test_driver.send_keys(document.body,'\uE004'); // Tab
assert_equals(document.activeElement, b2, 'Keyboard focus should skip the open popup');
popup.hide();
// Add a focusable button to the popup and make sure we can focus that
const button = document.createElement('button');
popup.appendChild(button);
b1.focus();
popup.show();
assert_equals(document.activeElement,b1);
// Tab once
await new test_driver.send_keys(document.body,'\uE004'); // Tab
assert_equals(document.activeElement, button, 'Keyboard focus should go to the contained button');
popup.hide();
}, "Popup should not be keyboard focusable");
</script>

View file

@ -1,28 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup document removal behavior</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id=frame1 srcdoc="<popup id=popup>Popup</popup>"></iframe>
<iframe id=frame2></iframe>
<script>
window.onload = () => {
test(t => {
const frame1Doc = document.getElementById('frame1').contentDocument;
const frame2Doc = document.getElementById('frame2').contentDocument;
const popup = frame1Doc.querySelector('popup');
assert_true(!!popup);
assert_false(popup.open);
popup.show();
assert_true(popup.open);
frame2Doc.body.appendChild(popup);
assert_false(popup.open);
popup.show();
assert_true(popup.open);
}, 'Moving popup between documents shouldn\'t cause issues');
};
</script>

View file

@ -1,27 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup document removal behavior</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<popup id=popup>Popup</popup>
<script>
promise_test(async t => {
function loadCompleted() {
return new Promise(resolve => {
window.addEventListener('load', resolve);
});
}
const popup = document.querySelector('popup');
assert_false(popup.open);
popup.show();
assert_true(popup.open);
popup.remove(); // Shouldn't cause any issues
document.body.click(); // Shouldn't cause light dismiss problems
await loadCompleted(); // The document should finish loading
}, 'Removal from the document shouldn\'t cause issues');
</script>

View file

@ -1,145 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup focus behaviors</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<popup data-test='default behavior - popup is not focused' data-no-focus>
<p>This is a popup</p>
<button>first button</button>
</popup>
<popup data-test='autofocus popup' autofocus class=should-be-focused>
<p>This is a popup</p>
</popup>
<popup data-test='autofocus empty popup' autofocus class=should-be-focused></popup>
<popup data-test='autofocus popup with button' autofocus class=should-be-focused>
<p>This is a popup</p>
<button>button</button>
</popup>
<popup data-test='autofocus child'>
<p>This is a popup</p>
<button autofocus class=should-be-focused>autofocus button</button>
</popup>
<popup data-test='autofocus on tabindex=0 element'>
<p autofocus tabindex=0 class=should-be-focused>This is a popup with autofocus on a tabindex=0 element</p>
<button>button</button>
</popup>
<popup data-test='autofocus multiple children'>
<p>This is a popup</p>
<button autofocus class=should-be-focused>autofocus button</button>
<button autofocus>second autofocus button</button>
</popup>
<popup autofocus data-test='autofocus popup and multiple autofocus children' class=should-be-focused>
<p>This is a popup</p>
<button autofocus>autofocus button</button>
<button autofocus>second autofocus button</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus popup'>
<p>This is a popup</p>
<button class=should-be-focused>first button should be focused</button>
<button>second button</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus takes precedence over autofocus'>
<p>This is a popup</p>
<button class=should-be-focused>first button</button>
<button autofocus>autofocus button should NOT be focused</button>
</popup>
<popup delegatesfocus autofocus data-test='delegatesfocus takes precedence over autofocus 2'>
<p>This is a popup</p>
<button class=should-be-focused>first button</button>
<button>autofocus button should NOT be focused</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus on empty popup has no effect' data-no-focus></popup>
<popup data-test='delegatesfocus on child has no effect' data-no-focus>
<p>This is a popup</p>
<button delegatesfocus>first button</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus skips contained popups'>
<p>This is a popup</p>
<popup>
<button>Contained popup button</button>
</popup>
<button class=should-be-focused>first button</button>
<button>autofocus button should NOT be focused</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus skips contained dialogs'>
<p>This is a popup</p>
<dialog>
<button>Contained dialog button</button>
</dialog>
<button class=should-be-focused>first button</button>
<button>autofocus button should NOT be focused</button>
</popup>
<style>
popup {
border: 2px solid black;
top:150px;
left:150px;
}
:focus-within { border: 5px dashed red; }
:focus { border: 5px solid lime; }
</style>
<script>
function activateAndVerify(popup) {
const testName = popup.getAttribute('data-test');
const priorFocus = document.createElement('button');
priorFocus.id = 'prior-focus';
document.body.appendChild(priorFocus);
let expectedFocusedElement = popup.matches('.should-be-focused') ? popup : popup.querySelector('.should-be-focused');
if (popup.hasAttribute('data-no-focus')) {
expectedFocusedElement = priorFocus;
}
test(t => {
t.add_cleanup(() => priorFocus.remove());
assert_true(!!expectedFocusedElement);
assert_false(popup.open);
priorFocus.focus();
assert_equals(document.activeElement,priorFocus);
// Directly show the popup:
popup.show();
assert_equals(document.activeElement, expectedFocusedElement, `${testName} activated by popup.show()`);
popup.hide();
// Use an activating element:
const button = document.createElement('button');
const popupId = 'popup-id';
assert_equals(document.querySelectorAll('#' + popupId).length,0);
document.body.appendChild(button);
t.add_cleanup(function() {
popup.removeAttribute('id');
button.remove();
});
popup.id = popupId;
button.setAttribute('popup', popupId);
priorFocus.focus();
button.click();
assert_equals(document.activeElement, expectedFocusedElement, `${testName} activated by button.click()`);
// Make sure we can directly focus the (already open) popup:
popup.focus();
assert_equals(document.activeElement, popup.hasAttribute('delegatesfocus') ? expectedFocusedElement : popup, `${testName} directly focus with popup.focus()`);
popup.hide();
}, "Popup focus test: " + testName);
}
document.querySelectorAll('body > popup').forEach(popup => activateAndVerify(popup));
</script>

View file

@ -1,5 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
No popup should be displayed here.<p>

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<link rel=match href="popup-hidden-display-ref.tentative.html">
No popup should be displayed here.<p>
<popup>This content should be hidden</popup>
<style>
popup {
display: block; /* This should have no effect */
top: 0;
left: 0;
width: 300px;
height: 200px;
border: 1px solid;
background: white;
color: black;
}
</style>

View file

@ -1,24 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<popup id=p1 initiallyopen>
Outer popup
<popup id=p2 initiallyopen>
Inner popup
</popup>
</popup>
<script>
requestAnimationFrame(() => {
requestAnimationFrame(() => {
test(function(){
assert_true(p1.open,'The first (outermost) popup should be the one that opens in this case');
assert_false(p2.open,'The inner popup should not be open');
}, "The initiallyopen attribute should cause only the first popup to open");
});
});
</script>

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<div>This is a popup, which should be open upon load</div>
<style>
div {
/* Per spec: */
display: block;
position: fixed;
top: 0;
left: 0;
/* Per settings in test file: */
width: fit-content;
height: fit-content;
border: 1px solid;
padding: 1em;
background: -internal-light-dark(white, black);
color: -internal-light-dark(black, white);
}
</style>

View file

@ -1,26 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<link rel=match href="popup-initiallyopen-display-ref.tentative.html">
<popup id=p1 initiallyopen>This is a popup, which should be open upon load</popup>
<popup id=p2 initiallyopen>This is a second popup with initiallyopen, which should NOT be open upon load</popup>
<style>
popup {
width: fit-content;
height: fit-content;
border: 1px solid;
padding: 1em;
background: white;
color: black;
}
#p1 {
top:0;
}
#p2 {
top:100px;
}
</style>

View file

@ -1,38 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<popup id=p1 initiallyopen>This is a popup, which should be open upon load</popup>
<script></script> <!-- Possibly yield the parser, just to double-check -->
<popup id=p2 initiallyopen>This is a second popup with initiallyopen, which should NOT be open upon load</popup>
<popup id=p3>Also not visible</popup>
<script>
requestAnimationFrame(() => {
requestAnimationFrame(() => {
test(function(){
assert_true(p1.open,'initiallyopen should open the popup');
assert_true(p1.hasAttribute('initiallyopen'));
assert_true(p1.initiallyOpen,'initiallyopen should be reflected in the IDL attribute');
assert_false(p2.open, 'Only the first popup with initiallyopen should be open on load');
assert_true(p2.hasAttribute('initiallyopen'),'initiallyopen should be present/true, even if not opened');
assert_true(p2.initiallyOpen,'initiallyopen should be present/true, even if not opened');
assert_false(p3.open);
p3.setAttribute('initiallyopen','');
assert_false(p3.open, 'Changing initiallyopen should not affect open status');
assert_true(p3.hasAttribute('initiallyopen'));
assert_true(p3.initiallyOpen,'initiallyopen should still reflect to IDL');
p1.removeAttribute('initiallyopen');
assert_true(p1.open,'removing initiallyopen should not close the popup');
assert_false(p1.hasAttribute('initiallyopen'),'...but it should reflect to IDL');
p1.hide();
}, "The initiallyopen attribute should affect page load only");
});
});
</script>

View file

@ -1,18 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<link rel=match href="popup-hidden-display-ref.tentative.html">
No popup should be displayed here.<p>
<div style="display:none">
<popup>This content should be hidden</popup>
</div>
<script>
const popup = document.querySelector('popup');
popup.show();
if (!popup.open)
document.body.appendChild(document.createTextNode('FAIL'));
</script>

View file

@ -1,40 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup invoking attribute</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<button id=b1 popup=p1>Open Popup 1</button>
<popup id=p1 anchor=b1><p>This is popup #1</p></popup>
<style>
popup { border: 5px solid red; }
</style>
<script>
function clickOn(element) {
const actions = new test_driver.Actions();
return actions.pointerMove(0, 0, {origin: element})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
}
const popup1 = document.querySelector('#p1');
const button1 = document.querySelector('#b1');
promise_test(async () => {
assert_false(popup1.open);
await clickOn(button1);
assert_true(popup1.open);
popup1.hide();
assert_false(popup1.open);
button1.click();
assert_true(popup1.open);
}, "Basic test of the 'popup' attribute on a button");
</script>

View file

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8" />
<title>Popup light dismiss on scroll</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=scroller>
Scroll me<br><br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Enim ut sem viverra aliquet eget sit amet tellus. Massa
sed elementum tempus egestas sed sed risus pretium. Felis bibendum ut tristique et egestas
quis. Tortor dignissim convallis aenean et. Eu mi bibendum neque egestas congue quisque
</div>
<popup id=popup1>This is popup 1<div id=anchor></div></popup>
<popup id=popup2 anchor=anchor>This is popup 2</popup>
<button onclick='popup1.show();popup2.show();'>Open popups</button>
<style>
#popup1 { top:50px; left: 50px; }
#popup2 { top:150px; left: 50px; }
#scroller {
height: 150px;
width: 150px;
overflow-y: scroll;
border: 1px solid black;
}
</style>
<script>
async_test(t => {
popup1.addEventListener('hide',e => {
assert_false(popup2.open);
t.done();
})
assert_false(popup1.open);
assert_false(popup2.open);
popup1.show();
popup2.show();
assert_true(popup1.open);
assert_true(popup2.open);
scroller.scrollTo(0, 100);
},'Scrolling light-dismisses all popups');
</script>

View file

@ -1,189 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup light dismiss behavior</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<button id=b1 onclick='p1.show()'>Popup 1</button>
<span id=outside>Outside all popups</span>
<popup id=p1 anchor=b1>
<span id=inside1>Inside popup 1</span>
<button id=b2 onclick='p2.show()'>Popup 2</button>
</popup>
<popup id=p2 anchor=b2>
<span id=inside2>Inside popup 2</span>
</popup>
<button id=b3 popup=p3>Popup 3 - button 3
<popup id=p4>Inside popup 4</popup>
</button>
<popup id=p3>Inside popup 3</popup>
<button id=b4 popup=p3>Popup 3 - button 4
<popup id=p5>Inside popup 5</popup>
</button>
<popup id=p6>Inside popup 6
<div style="height:2000px;background:lightgreen"></div>
Bottom of popup6
</popup>
<button popup=p6>Popup 6</button>
<style>
#p1 { top:50px; }
#p2 { top:50px; left:250px; }
#p3 { top:150px;}
#p4 { top:150px; left:250px;}
#p5 { top:250px;}
#p6 {
top: 50px;
left:150px;
width: 300px;
height: 300px;
overflow-y: scroll;
}
popup { border: 5px solid red; }
</style>
<script>
function clickOn(element) {
const actions = new test_driver.Actions();
return actions.pointerMove(0, 0, {origin: element})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
}
const popup1 = document.querySelector('#p1');
const button1 = document.querySelector('#b1');
const popup2 = document.querySelector('#p2');
const outside = document.querySelector('#outside');
const inside1 = document.querySelector('#inside1');
const inside2 = document.querySelector('#inside2');
const button3 = document.querySelector('#b3');
const button4 = document.querySelector('#b4');
const popup3 = document.querySelector('#p3');
const popup4 = document.querySelector('#p4');
const popup5 = document.querySelector('#p5');
const popup6 = document.querySelector('#p6');
(async function() {
setup({ explicit_done: true });
let popup1HideCount = 0;
popup1.addEventListener('hide',(e) => {
++popup1HideCount;
e.preventDefault(); // 'hide' should not be cancellable.
});
let popup2HideCount = 0;
popup2.addEventListener('hide',(e) => {
++popup2HideCount;
e.preventDefault(); // 'hide' should not be cancellable.
});
assert_false(popup1.open);
popup1.show();
let p1HideCount = popup1HideCount;
assert_true(popup1.open);
await clickOn(outside);
test(t => {
assert_false(popup1.open);
assert_equals(popup1HideCount,p1HideCount+1);
},'Clicking outside a popup will dismiss the popup');
assert_false(popup1.open);
popup1.show();
p1HideCount = popup1HideCount;
await clickOn(inside1);
test(t => {
assert_true(popup1.open);
assert_equals(popup1HideCount,p1HideCount);
},'Clicking inside a popup does not close that popup');
popup2.show();
p1HideCount = popup1HideCount;
let p2HideCount = popup2HideCount;
await clickOn(inside2);
test(t => {
assert_true(popup1.open);
assert_true(popup2.open);
assert_equals(popup1HideCount,p1HideCount,'popup1');
assert_equals(popup2HideCount,p2HideCount,'popup2');
},'Clicking inside a child popup shouldn\'t close either popup');
popup2.show();
p1HideCount = popup1HideCount;
p2HideCount = popup2HideCount;
await clickOn(inside1);
test(t => {
assert_true(popup1.open);
assert_equals(popup1HideCount,p1HideCount);
assert_false(popup2.open);
assert_equals(popup2HideCount,p2HideCount+1);
},'Clicking inside a parent popup should close child popup');
assert_true(popup1.open);
p1HideCount = popup1HideCount;
await clickOn(button1);
test(t => {
assert_true(popup1.open,'popup1 not open');
assert_equals(popup1HideCount,p1HideCount);
popup1.hide(); // Cleanup
assert_false(popup1.open);
},'Clicking on anchor element shouldn\'t close its popup');
await clickOn(button3);
test(t => {
assert_true(popup3.open,'invoking element should open popup');
popup4.show();
assert_true(popup4.open);
assert_true(popup3.open);
},'An invoking element should be part of the ancestor chain');
await clickOn(button3);
assert_true(popup3.open);
assert_false(popup4.open);
assert_false(popup5.open);
popup5.show();
test(t => {
assert_true(popup5.open);
assert_false(popup3.open);
},'An invoking element that was not used to invoke the popup should NOT be part of the ancestor chain');
popup1.show();
popup2.show(); // Popup1 is an ancestral element for popup2.
assert_true(popup1.open);
assert_true(popup2.open);
const drag_actions = new test_driver.Actions();
// Drag *from* popup2 *to* popup1 (its ancestor).
await drag_actions.pointerMove(0,0,{origin: popup2})
.pointerDown({button: drag_actions.ButtonType.LEFT})
.pointerMove(0,0,{origin: popup1})
.pointerUp({button: drag_actions.ButtonType.LEFT})
.send();
test(t => {
assert_true(popup1.open,'popup1 should be open');
assert_true(popup2.open,'popup1 should be open');
popup1.hide();
assert_false(popup2.open);
},'Dragging from an open popup outside an open popup should leave the popup open');
popup6.show();
assert_equals(popup6.scrollTop,0,'popup6 should start non-scrolled');
await new test_driver.Actions()
.scroll(0, 0, 0, 50, {origin: popup6})
.send();
test(t => {
assert_true(popup6.open,'popup6 should stay open');
assert_equals(popup6.scrollTop,50,'popup6 should be scrolled');
popup6.hide();
},'Scrolling within a popup should not close the popup');
done();
})();
</script>

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<div>This is a popup</div>
<style>
div {
/* Per spec: */
display: block;
position: fixed;
top: 0;
left: 0;
/* Per settings in test file: */
width: fit-content;
height: fit-content;
border: 1px solid;
padding: 1em;
background: white;
color: black;
}
</style>

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<link rel=match href="popup-open-display-ref.tentative.html">
<popup>This is a popup</popup>
<style>
popup {
width: fit-content;
height: fit-content;
border: 1px solid;
padding: 1em;
background: white;
color: black;
}
</style>
<script>
document.querySelector('popup').show();
</script>

View file

@ -1,30 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<popup id=p1>This is popup 1<div id=anchor2></div></popup>
<popup id=p2 anchor=anchor2>This is popup 2<div id=anchor3></div></popup>
<popup id=p3 anchor=anchor3>This is popup 3</popup>
<style>
popup#p2 {
top: 100px;
}
popup#p3 {
top:200px;
}
popup {
width: fit-content;
height: fit-content;
border: 1px solid;
padding: 1em;
background: white;
color: black;
}
</style>
<script>
document.querySelector('#p1').show();
document.querySelector('#p2').show();
document.querySelector('#p3').show();
</script>

View file

@ -1,44 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel=author href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<link rel=match href="popup-open-overflow-display-ref.tentative.html">
<div id=container>
<popup id=p1>This is popup 1<div id=anchor2></div></popup>
<popup id=p2 anchor=anchor2>This is popup 2<div id=anchor3></div></popup>
<popup id=p3 anchor=anchor3>This is popup 3</popup>
</div>
<style>
#container {
overflow:hidden;
position: absolute;
top: 100px;
left: 50px;
width: 30px;
height: 30px;
}
popup#p2 {
position: absolute;
top: 100px;
}
popup#p3 {
position: relative;
top:200px;
}
popup {
width: fit-content;
height: fit-content;
border: 1px solid;
padding: 1em;
background: white;
color: black;
}
</style>
<script>
document.querySelector('#p1').show();
document.querySelector('#p2').show();
document.querySelector('#p3').show();
</script>

View file

@ -1,162 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function ensureShadowDom(host) {
host.querySelectorAll('my-element').forEach(host => {
if (host.shadowRoot)
return; // Declarative Shadow DOM is enabled
const template = host.firstElementChild;
assert_true(template instanceof HTMLTemplateElement);
const shadow = host.attachShadow({mode: 'open'});
shadow.appendChild(template.content);
template.remove();
})
}
function findPopups(root) {
let popups = [];
if (!root)
return popups;
if (root instanceof HTMLPopupElement)
popups.push(root);
popups.push(...findPopups(root.shadowRoot));
root.childNodes.forEach(child => {
popups.push(...findPopups(child));
})
return popups;
}
function getPopupReferences(testId) {
const testRoot = document.querySelector(`#${testId}`);
assert_true(!!testRoot);
ensureShadowDom(testRoot);
return findPopups(testRoot);
}
function popupVisible(popup) {
return !!(popup.offsetWidth || popup.offsetHeight || popup.getClientRects().length);
}
function showPopup(testId,popupNum) {
getPopupReferences(testId)[popupNum].show();
}
</script>
<div id=test1>
<button onclick='showPopup("test1",0)'>Test1 Popup</button>
<my-element>
<template shadowroot=open>
<popup>
<p>This should show, even though it is inside shadow DOM.</p>
</popup>
</template>
</my-element>
</div>
<script>
test(function() {
const popup = getPopupReferences('test1')[0];
popup.show();
assert_true(popup.open);
assert_true(popupVisible(popup));
}, "Popups located inside shadow DOM can still be shown");
</script>
<div id=test2>
<button id=t2b1 onclick='showPopup("test2",0)'>Test 2 Popup 1</button>
<popup anchor=t2b1 style="top: 400px;">
<p>Popup 1</p>
<button id=t2b2 onclick='showPopup("test2",1)'>Test 2 Popup 2</button>
</popup>
<my-element>
<template shadowroot=open>
<popup anchor=t2b2 style="top: 400px;">
<p>Hiding this popup will hide *all* open popups,</p>
<p>because t2b2 doesn't exist in this context.</p>
</popup>
</template>
</my-element>
</div>
<script>
test(function() {
const [popup1,popup2] = getPopupReferences('test2');
popup1.show();
assert_true(popup1.open);
assert_true(popupVisible(popup1));
popup2.show();
assert_false(popup1.open, 'popup1 open'); // P1 was closed by P2
assert_false(popupVisible(popup1), 'popup1 visible');
assert_true(popup2.open, 'popup2 open'); // P2 is open
assert_true(popupVisible(popup2), 'popup2 visible');
}, "anchor references do not cross shadow boundaries");
</script>
<div id=test3>
<my-element>
<template shadowroot=open>
<button id=t3b1 onclick='showPopup("test3",0)'>Test 3 Popup 1</button>
<popup anchor=t3b1>
<p>This popup will stay open when popup2 shows.</p>
<slot></slot>
</popup>
</template>
<button id=t3b2 onclick='showPopup("test3",1)'>Test 3 Popup 2</button>
</my-element>
<popup anchor=t3b2>Popup 2</popup>
</div>
<script>
test(function() {
const [popup1,popup2] = getPopupReferences('test3');
popup1.show();
assert_true(popup1.open);
assert_true(popupVisible(popup1));
// Showing popup2 should not close popup1, since it is a flat
// tree ancestor of popup2's anchor button.
popup2.show();
assert_true(popup2.open);
assert_true(popupVisible(popup2));
assert_true(popup1.open);
assert_true(popupVisible(popup1));
popup1.hide();
assert_false(popup2.open);
assert_false(popup1.open);
}, "anchor references use the flat tree not the DOM tree");
</script>
<div id=test4>
<button id=t4b1 onclick='showPopup("test4",0)'>Test 4 Popup 1</button>
<popup anchor=t4b1>
<p>This should not get hidden when popup2 opens.</p>
<my-element>
<template shadowroot=open>
<button id=t4b2 onclick='showPopup("test4",1)'>Test 4 Popup 2</button>
<popup anchor=t4b2>
<p>This should not hide popup1.</p>
</popup>
</template>
</my-element>
</popup>
</div>
<script>
test(function() {
const [popup1,popup2] = getPopupReferences('test4');
popup1.show();
popup2.show();
// Both 1 and 2 should be open at this point.
assert_true(popup1.open, 'popup1 not open');
assert_true(popupVisible(popup1));
assert_true(popup2.open, 'popup2 not open');
assert_true(popupVisible(popup2));
// This should hide both of them.
popup1.hide();
assert_false(popup2.open);
assert_false(popupVisible(popup2));
}, "The popup stack is preserved across shadow-inclusive ancestors");
</script>

View file

@ -1,37 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" href="mailto:masonf@chromium.org">
<div id=popup>
Inside popup
<div class=z style="z-index: 2; background:lightgreen">z-index 2
<div class=z style="z-index: 3; background:lightblue; left: 20px;">z-index 3</div>
<div class=z style="z-index: 1; background:pink; top:-20px; left: 10px;">z-index 1</div>
</div>
<div class=z style="background:green; top:-100px; left: 250px; width: 100px;">Outside</div>
Bottom of popup
</div>
<style>
#popup {
/* Per spec: */
display: block;
position: fixed;
top: 0;
left: 0;
/* Per settings in test file: */
width: 200px;
height: 230px;
border: 1px solid red;
padding: 1em;
background: white;
color: black;
top:50px;
left:50px;
}
.z {
position: relative;
border: 1px solid black;
padding: 1em;
}
</style>

View file

@ -1,37 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<link rel=match href="popup-stacking-context-ref.tentative.html">
<popup>
Inside popup
<div class=z style="z-index: 2; background:lightgreen">z-index 2
<div class=z style="z-index: 3; background:lightblue; left: 20px;">z-index 3</div>
<div class=z style="z-index: 1; background:pink; top:-20px; left: 10px;">z-index 1</div>
</div>
<div class=z style="background:green; top:-100px; left: 250px; width: 100px;">Outside</div>
Bottom of popup
</popup>
<style>
popup {
width: 200px;
height: 230px;
border: 1px solid red;
padding: 1em;
background: white;
color: black;
top:50px;
left:50px;
}
.z {
position: relative;
border: 1px solid black;
padding: 1em;
}
</style>
<script>
document.querySelector('popup').show();
</script>

View file

@ -1,85 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<popup id=p1 anchor=b1><p>This is popup #1</p>
<button id=b2 onclick='p2.show()'>Popup 2</button>
<button id=b4 onclick='p4.show()'>Popup 4</button>
</popup>
<popup id=p2 anchor=b2><p>This is popup #2</p>
<button id=b3 onclick='p3.show()'>Popup 3</button>
</popup>
<popup id=p3 anchor=b3><p>This is popup #3</p></popup>
<popup id=p4 anchor=b4><p>This is popup #4</p></popup>
<button id=b1 onclick='p1.show()'>Popup 1</button>
<dialog id=d1>This is a dialog<button onclick='this.parentElement.close()'>Close</button></dialog>
<button id=b5 onclick='d1.show()'>Dialog</button>
<script>
const popups = [p1, p2, p3, p4];
function assertState(...states) {
assert_equals(popups.length,states.length);
for(let i=0;i<popups.length;++i) {
assert_equals(popups[i].open,states[i],`Popup #${i+1} incorrect state`);
}
}
test(function() {
assertState(false,false,false,false);
p1.show();
assertState(true,false,false,false);
p2.show();
assertState(true,true,false,false);
p3.show();
assertState(true,true,true,false);
// P4 is a sibling of P2, so showing it should
// close P2 and P3.
p4.show();
assertState(true,false,false,true);
// P2 should close P4 now.
p2.show();
assertState(true,true,false,false);
// Hiding P1 should hide all.
p1.hide();
assertState(false,false,false,false);
}, "popup stacking behavior")
test(function() {
function openManyPopups() {
p1.show();
p2.show();
p3.show();
assertState(true,true,true,false);
}
openManyPopups();
d1.show(); // Dialog.show() should hide all popups.
assertState(false,false,false,false);
d1.close();
openManyPopups();
d1.showModal(); // Dialog.showModal() should also hide all popups.
assertState(false,false,false,false);
d1.close();
}, "popups should be closed by dialogs")
test(function() {
d1.show();
assert_true(d1.open);
p1.show();
assertState(true,false,false,false);
assert_true(d1.open);
p1.hide();
assert_true(d1.open);
d1.close();
}, "dialogs should not be closed by popups")
</script>
<style>
#p1 { top:350px; }
#p2 { top:350px; left:200px; }
#p3 { top:500px; }
#p4 { top:500px;left:200px; }
</style>

View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>summary element: clicking on anchor without link</title>
<link rel="author" title="Di Zhang" href="mailto:dizhangg@chromium.org">
<link rel="help" href="https://html.spec.whatwg.org/C/#the-summary-element">
<link rel="help" href="https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<details id="details">
<summary><a id="no_inline">Details</a></summary>
<p>Text</p>
</details>
<details id="details_inline">
<summary><a><i id="has_inline">Details</i></a></summary>
<p>Text</p>
</details>
<script>
async function testClickingOnAnchorWithoutLink (detailsId, targetId) {
const details = document.getElementById(detailsId);
const target = document.getElementById(targetId);
const initialLoc = location.hash;
assert_false(details.open);
target.click();
assert_true(details.open);
assert_equals(location.hash, initialLoc);
}
promise_test(() => testClickingOnAnchorWithoutLink('details', 'no_inline'),
"clicking on anchor without link should open details and not navigate.");
promise_test(() => testClickingOnAnchorWithoutLink('details_inline', 'has_inline'),
"clicking on anchor without link, with embedded inline element should open details and not navigate.");
</script>

View file

@ -0,0 +1,104 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Summary</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<div id="log"></div>
<details>
<summary>Summary</summary>
Details
</details>
<script type="module">
const details = document.querySelector("details");
details.addEventListener("toggle",
(e) => assert_true(false, 'details should not be toggled'));
const summary = document.querySelector("summary");
summary.addEventListener("click",
(e) => assert_true(false, `summary should not be clicked`));
test(() => {
// keyCode: Enter
summary.dispatchEvent(
new KeyboardEvent("keypress", {
keyCode: 13,
})
);
// key: Enter
summary.dispatchEvent(
new KeyboardEvent("keypress", {
key: "Enter",
})
);
// keyCode: Space
summary.dispatchEvent(
new KeyboardEvent("keypress", {
keyCode: 32,
})
);
// key: Space
summary.dispatchEvent(
new KeyboardEvent("keypress", {
key: " ",
})
);
}, `Dispatching untrusted keypress events to summary should not cause click event`);
test(() => {
// keyCode: Enter
summary.dispatchEvent(
new KeyboardEvent("keydown", {
keyCode: 13,
})
);
summary.dispatchEvent(
new KeyboardEvent("keyup", {
keyCode: 13,
})
);
// key: Enter
summary.dispatchEvent(
new KeyboardEvent("keydown", {
key: "Enter",
})
);
summary.dispatchEvent(
new KeyboardEvent("keyup", {
key: "Enter",
})
);
// keyCode: Space
summary.dispatchEvent(
new KeyboardEvent("keydown", {
keyCode: 32,
})
);
summary.dispatchEvent(
new KeyboardEvent("keyup", {
keyCode: 32,
})
);
// key: Space
summary.dispatchEvent(
new KeyboardEvent("keydown", {
key: " ",
})
);
summary.dispatchEvent(
new KeyboardEvent("keyup", {
key: " ",
})
);
}, `Dispatching untrusted keyup/keydown events to summary should not cause click event`);
</script>
</body>
</html>