mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Update web-platform-tests to revision b'b728032f59a396243864b0f8584e7211e3632005'
This commit is contained in:
parent
ace9b32b1c
commit
df68c4e5d1
15632 changed files with 514865 additions and 155000 deletions
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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}`);
|
||||
}
|
||||
|
|
|
@ -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>");
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<iframe></iframe>
|
|
@ -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>
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<object width="200" type="image/svg+xml" data="../../../../images/100px-green-rect.svg"></object>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue