summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/semantics
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/semantics')
-rw-r--r--testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html1
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis4
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css0
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers1
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers1
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html27
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.https.html (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.https.html (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.sub.js (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.js)18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js43
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js)21
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html18
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html23
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html2
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html81
-rw-r--r--testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html1
-rw-r--r--testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html4
-rw-r--r--testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html232
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html164
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html16
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html6
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html8
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html455
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html64
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js8
-rw-r--r--testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html38
-rw-r--r--testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html34
-rw-r--r--testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html67
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html99
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html94
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html8
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js8
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html2
-rw-r--r--testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html4
51 files changed, 1485 insertions, 172 deletions
diff --git a/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html b/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
index e3dcd43a17..2be6dc72fe 100644
--- a/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
+++ b/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<meta charset="utf8">
<meta name="timeout" content="long">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event propagation on disabled form elements</title>
<link rel="author" href="mailto:krosylight@mozilla.com">
<link rel="help" href="https://github.com/whatwg/html/issues/2368">
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis
new file mode 100644
index 0000000000..ddf4898d3f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis
@@ -0,0 +1,4 @@
+HTTP/1.1 302 Found
+Content-Type: text/css
+
+body { background-color: red; }
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers
new file mode 100644
index 0000000000..156209f9c8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css
new file mode 100644
index 0000000000..e1b2552ffe
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css
@@ -0,0 +1,3 @@
+body {
+ background-color: green;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers
new file mode 100644
index 0000000000..156209f9c8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html
new file mode 100644
index 0000000000..08176d6cd2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>stylesheets served with bad MIME types</title>
+<link rel="author" title="Michael[tm] Smith" href="mailto:mike@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/#link-type-stylesheet:process-the-linked-resource">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ async_test((t) => {
+ const link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "resources/stylesheet-bad-mime-type.css";
+ link.onload = t.unreached_func();
+ link.onerror = t.step_func_done();
+ document.head.append(link);
+ }, "'load' event does not fire at link@rel=stylesheet having non-empty resource with bad MIME type");
+ async_test((t) => {
+ t.step_timeout(() => {
+ const link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "resources/stylesheet-bad-mime-type-empty.css";
+ link.onload = t.unreached_func();
+ link.onerror = t.step_func_done();
+ document.head.append(link);
+ }, 2000);
+ }, "'load' event does not fire at link@rel=stylesheet having empty resource with bad MIME type");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html
new file mode 100644
index 0000000000..28ac55ff1a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>stylesheet served with non-OK status</title>
+<link rel="author" title="Michael[tm] Smith" href="mailto:mike@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/#fetching-and-processing-a-resource-from-a-link-element:processresponseconsumebody">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ async_test((t) => {
+ const link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "resources/302-no-Location-header-text-css.asis";
+ link.onload = t.unreached_func();
+ link.onerror = t.step_func_done();
+ document.head.append(link);
+ }, "'load' event does not fire at link@rel=stylesheet having resource with non-OK response status");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html
new file mode 100644
index 0000000000..22b579d720
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>playback should not reset when moving within a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video autoplay muted hidden></video>
+<div id="elsewhere"></div>
+<script>
+async_test(t => {
+ const v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.currentTime = 0;
+ v.onplaying = t.step_func(() => {
+ v.currentTime = 10;
+ t.step_timeout(() => {
+ assert_greater_than_equal(v.currentTime, 10);
+ document.getElementById('elsewhere').appendChild(v);
+ assert_false(v.paused, 'paused after moving');
+ assert_greater_than_equal(v.currentTime, 10);
+ t.step_timeout(() => {
+ assert_greater_than_equal(v.currentTime, 10);
+ t.done();
+ }, 0);
+ }, 0);
+
+ });
+ v.play();
+ v.onpause = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html
index d080831175..9eec621c89 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html
@@ -31,7 +31,7 @@
<div id=scroller2>
<div id="spacer"></div>
<div id="scroller">
- <iframe>
+ <iframe
id="target"
src="resources/subframe.html"
loading="lazy"
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.https.html
index 6b3b3104ef..6b3b3104ef 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.https.html
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.html b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.https.html
index 158fc4f947..158fc4f947 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.https.html
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.sub.js
index 413f392dfc..bec8f6a64a 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.sub.js
@@ -5,7 +5,7 @@
// // META: script=/resources/testdriver.js
// // META: script=/resources/testdriver-vendor.js
// // META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// // META: script=./resources/sandbox-top-navigation-helper.js
+// // META: script=./resources/sandbox-top-navigation-helper.sub.js
// Helper file that provides various functions to test top-level navigation
// with various frame and sandbox flag configurations.
@@ -27,18 +27,28 @@ async function createNestedIframe(parent, origin, frame_sandbox, header_sandbox)
origin: origin,
scripts: [
'/resources/testdriver.js',
- '/resources/testdriver-driver.js',
- '/resources/testdriver-vendor.js'
+ '/resources/testdriver-vendor.js',
],
headers: headers,
}, iframe_attributes);
}
+async function navigateFrameTo(frame, origin) {
+ return frame.navigateToNew({
+ origin: origin,
+ scripts: [
+ '/resources/testdriver.js',
+ '/resources/testdriver-vendor.js',
+ ],
+ });
+}
+
async function attemptTopNavigation(iframe, should_succeed) {
let did_succeed;
try {
await iframe.executeScript(() => {
- window.top.location.href = "https://google.com";
+ window.top.location.href =
+ 'http://{{hosts[alt][www2]}}:{{ports[http][0]}}';
});
did_succeed = true;
} catch (e) {
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js
new file mode 100644
index 0000000000..95d53e1fe3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js
@@ -0,0 +1,28 @@
+// META: title=Top-level navigation tests with cross origin & user activated child frames
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/get-host-info.sub.js
+// META: script=/common/utils.js
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
+
+'use strict';
+
+// /* ---------------------- CROSS ORIGIN (A -> B) TESTS ---------------------- */
+
+promise_test(async t => {
+ const main = await setupTest();
+ const iframe_1 = await createNestedIframe(main,
+ "HTTP_REMOTE_ORIGIN", "allow-top-navigation", "");
+
+ await attemptTopNavigation(iframe_1, true);
+}, "A cross-origin frame with frame sandbox flags can navigate top");
+
+promise_test(async t => {
+ const main = await setupTest();
+ const iframe_1 = await createNestedIframe(main,
+ "HTTP_REMOTE_ORIGIN", "", "allow-top-navigation");
+
+ await attemptTopNavigation(iframe_1, false);
+}, "A cross-origin frame with delivered sandbox flags can not navigate top");
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js
index 53faa99a40..1d5ea93830 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js
@@ -5,7 +5,7 @@
// META: script=/resources/testdriver.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js
new file mode 100644
index 0000000000..26db4eeaca
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js
@@ -0,0 +1,43 @@
+// META: title=Top-level navigation tests with cross origin & user activated child frames
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/get-host-info.sub.js
+// META: script=/common/utils.js
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-actions.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
+
+'use strict';
+
+promise_test(async t => {
+ const main = await setupTest();
+
+ const iframe = await createNestedIframe(main, "HTTP_ORIGIN", "", "");
+ await activate(iframe);
+
+ const new_iframe = await navigateFrameTo(iframe, "HTTPS_REMOTE_ORIGIN");
+ await attemptTopNavigation(new_iframe, false);
+}, "A cross-site unsandboxed iframe navigation consumes user activation and " +
+ "disallows top-level navigation.");
+
+promise_test(async t => {
+ const main = await setupTest();
+
+ const iframe = await createNestedIframe(main, "HTTP_ORIGIN", "", "");
+ await activate(iframe);
+
+ const new_iframe = await navigateFrameTo(iframe, "HTTP_REMOTE_ORIGIN");
+ await attemptTopNavigation(new_iframe, true);
+}, "A same-site unsandboxed iframe navigation does not consume user " +
+ "activation and allows top-level navigation.");
+
+promise_test(async t => {
+ const main = await setupTest();
+
+ const iframe = await createNestedIframe(main, "HTTP_ORIGIN", "", "");
+
+ const new_iframe = await navigateFrameTo(iframe, "HTTP_REMOTE_ORIGIN");
+ await attemptTopNavigation(new_iframe, false);
+}, "A same-site unsandboxed iframe navigation without sticky user activation " +
+ "does not allow top-level navigation.");
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js
index a5cda9b0b9..2ea0ba606e 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js
@@ -5,7 +5,7 @@
// META: script=/resources/testdriver.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js
index a07148f802..326c1dd54a 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js
@@ -5,7 +5,7 @@
// META: script=/resources/testdriver.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js
index 8681411dd7..5079c8ad14 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js
@@ -3,9 +3,10 @@
// META: script=/common/get-host-info.sub.js
// META: script=/common/utils.js
// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-actions.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
@@ -27,21 +28,3 @@ promise_test(async t => {
await attemptTopNavigation(iframe_1, false);
}, "allow-top-navigation-by-user-activation set but no sticky activation");
-
-/* ---------------------- CROSS ORIGIN (A -> B) TESTS ---------------------- */
-
-promise_test(async t => {
- const main = await setupTest();
- const iframe_1 = await createNestedIframe(main,
- "HTTP_REMOTE_ORIGIN", "allow-top-navigation", "");
-
- await attemptTopNavigation(iframe_1, true);
-}, "A cross-origin frame with frame sandbox flags can navigate top");
-
-promise_test(async t => {
- const main = await setupTest();
- const iframe_1 = await createNestedIframe(main,
- "HTTP_REMOTE_ORIGIN", "", "allow-top-navigation");
-
- await attemptTopNavigation(iframe_1, false);
-}, "A cross-origin frame with delivered sandbox flags can not navigate top");
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html
new file mode 100644
index 0000000000..5330411a5d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html class=test-wait>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://issues.chromium.org/324325525">
+
+<!-- Attempting to slot a child of <select> after initial slot assignment should not crash. -->
+
+<select size=1>
+ <optgroup></optgroup>
+</select>
+<script>
+requestAnimationFrame(() => {
+ document.querySelector('optgroup').setAttribute('slot', 'slot1');
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove('test-wait');
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html
new file mode 100644
index 0000000000..f71c1e52fc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/whatwg/html/issues/9799">
+<link rel=match href="select-child-button-and-datalist-ref.html">
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<select>
+ <button type=popover>button</button>
+ <datalist>
+ <option>one</option>
+ <option>two</option>
+ </datalist>
+</select>
+
+<script>
+requestAnimationFrame(() => {
+ document.querySelector('select').style = 'appearance:bikeshed';
+ document.querySelector('button').click();
+ document.documentElement.classList.remove('reftest-wait');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html
index b74957feed..54785ace95 100644
--- a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html
@@ -5,7 +5,7 @@
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
-<select>
+<select style="appearance:bikeshed">
<button type=popover>button</button>
<datalist>
<option>one</option>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html
new file mode 100644
index 0000000000..993f6e126c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/whatwg/html/issues/9799">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<select>
+ <datalist>
+ <option class=one>one</option>
+ <div>
+ <option class=two>two</option>
+ </div>
+ <option class=three>three</option>
+ </datalist>
+</select>
+
+<script>
+const select = document.querySelector('select');
+
+function runTest() {
+ const datalist = select.querySelector('datalist');
+ const firstOption = select.querySelector('option.one');
+ const secondOption = select.querySelector('option.two');
+ const thirdOption = select.querySelector('option.three');
+ const datalistChildDiv = datalist.querySelector('div');
+
+ let selectChildDiv = document.querySelector('select > div');
+ if (!selectChildDiv) {
+ selectChildDiv = document.createElement('div');
+ select.appendChild(selectChildDiv);
+ }
+
+ assert_equals(select.length, 3, 'select.length');
+ assert_equals(select.options.length, 3, 'select.options.length');
+ assert_equals(select.options[0], firstOption, 'select.options[0]');
+ assert_equals(select.options[1], secondOption, 'select.options[1]');
+ assert_equals(select.options[2], thirdOption, 'select.options[2]');
+
+ assert_equals(select.value, 'one', 'initial select.value');
+ select.value = 'two';
+ assert_equals(select.value, 'two', 'select.value after modifying');
+
+ secondOption.remove();
+ assert_equals(select.length, 2, 'select.length after removing an option');
+ assert_equals(select.options.length, 2, 'select.options.length after removing an option');
+ assert_equals(select.options[0], firstOption, 'select.options[0] after removing an option');
+ assert_equals(select.options[1], thirdOption, 'select.options[1] after removing an option');
+
+ datalist.appendChild(secondOption);
+ assert_equals(select.length, 3, 'select.length after re-adding an option');
+ assert_equals(select.options.length, 3, 'select.options.length after re-adding an option');
+ assert_equals(select.options[0], firstOption, 'select.options[0] after re-adding an option');
+ assert_equals(select.options[1], thirdOption, 'select.options[1] after re-adding an option');
+ assert_equals(select.options[2], secondOption, 'select.options[2] after re-adding an option');
+
+ selectChildDiv.appendChild(secondOption);
+ assert_equals(select.length, 2, 'select.length after moving option to child div');
+ assert_equals(select.options.length, 2, 'select.options.length after moving option to child div');
+ assert_equals(select.options[0], firstOption, 'select.options[0] after moving option to child div');
+ assert_equals(select.options[1], thirdOption, 'select.options[1] after moving option to child div');
+
+ // reset back to normal for the next test
+ datalistChildDiv.appendChild(secondOption);
+ select.value = 'one';
+}
+
+test(() => {
+ runTest();
+}, 'Option elements should work if they are a descendant of a selects datalist.');
+
+test(() => {
+ select.setAttribute('multiple', '');
+ runTest();
+}, 'Options in datalist should still work when the multiple attribute is added.');
+
+test(() => {
+ select.innerHTML = select.innerHTML;
+ select.value = 'one';
+ runTest();
+}, 'Options in datalist in multiple should work after re-parsing and re-attaching.');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html
index e368bde6fb..db757861e7 100644
--- a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html
+++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html
@@ -66,6 +66,7 @@ promise_test(async () => {
event.preventDefault();
});
+ await test_driver.bless();
bottomDialog.showModal();
await blessTopLayer(bottomDialog);
topDialog.showModal();
diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html
index e1f4c6ab82..bcd6ebebc1 100644
--- a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html
+++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html
@@ -37,7 +37,9 @@
// close event is async, give it a chance to be fired
t.step_timeout(function() {
- t.done();
+ requestAnimationFrame(() => {
+ t.done();
+ });
}, 0);
}, "On setting it to false, the close event should not be fired");
</script>
diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html
new file mode 100644
index 0000000000..94869dc9b6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>summary element: interactive content</title>
+<link rel="author" title="Michael[tm] Smith" href="mailto:mike@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interactive-elements.html#the-summary-element">
+<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>
+
+<details>
+ <summary id=summary>
+ <a id=a href="#">anchor element</a>
+ <svg style="width: 160px; height: 100px" viewBox="0 0 100 100">
+ <a href="#" id="svg_a"><text id="svg_text" x="50" y="90" text-anchor="middle">SVG anchor element</text></a>
+ </svg>
+ <svg style="width: 100px; height: 200px" viewBox="0 0 100 100">
+ <foreignObject x="0" y="60" width="100" height="200" text-anchor="middle">
+ <a xmlns="http://www.w3.org/1999/xhtml" href="#" id="svg_foreignObject_a">SVG foreignObject with HTML anchor element</a>
+ </foreignObject>
+ </svg>
+ <audio id="audio" controls src=/media/sound_5.mp3></audio>
+ <button id=button>button element</button>
+ <embed id=embed src="/images/blue.png" height="100" width="100">
+ <iframe id=iframe srcdoc="iframe element"></iframe>
+ <img id=img_usemap usemap src=/media/poster.png></img>
+ <img id=img src=/media/poster.png></img>
+ <input type="text" value="input@type=text" id="input_text">
+ <input type="search" value="input@type=search" id="input_search">
+ <input type="tel" value="input@type=tel" id="input_tel">
+ <input type="url" value="input@type=url" id="input_url">
+ <input type="email" value="input@type=email" id="input_email">
+ <input type="password" value="input@type=password" id="input_password">
+ <input type="button" value="input@type=button" id="input_button">
+ <input type="reset" id="input_reset">
+ <input type="submit" id="input_submit">
+ <input type="date" value="input@type=date" id="input_date">
+ <input type="month" value="input@type=month" id="input_month">
+ <input type="week" value="input@type=week" id="input_week">
+ <input type="time" id="input_time">
+ <input type="datetime-local" id="input_datetime-local">
+ <input type="color" id="input_color">
+ <input type="number" value="1337" id="input_number">
+ <input type="range" id="input_range">
+ <input type="checkbox" id="input_checkbox">
+ <input type="radio" id="input_radio" disabled>
+ <input type="file" id="input_file">
+ <input type="image" id="input_image" src=/media/poster.png>
+ <label id=label style="display: block">label element</label>
+ <textarea value="textarea" id="textarea">textarea element</textarea>
+ <video id="video" controls>
+ <source src="/media/test-1s.mp4" type="video/mp4">
+ <source src="/media/test-1s.webm" type="video/webm">
+ </video>
+ <div id="non-interactive">This is clickable summary text</div>
+ </summary>
+</details>
+
+<script>
+const details = document.querySelector("details");
+
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("non-interactive"));
+ assert_true(details.open)
+}, "Clicking on non-interactive child of a <summary> opens its <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("a"));
+ assert_false(details.open)
+}, "Clicking an <a> link doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("svg_a"));
+ assert_false(details.open)
+}, "Clicking an SVG <a> link doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("svg_foreignObject_a"));
+ assert_false(details.open)
+}, "Clicking an HTML <a> link in an SVG <foreignObject> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("audio"));
+ assert_false(details.open)
+}, "Clicking an <audio> element doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("button"));
+ assert_false(details.open)
+}, "Clicking a <button> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("embed"));
+ assert_false(details.open)
+}, "Clicking the content of an <embed> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("iframe"));
+ assert_false(details.open)
+}, "Clicking in an <iframe> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("img_usemap"));
+ assert_false(details.open)
+}, "Clicking an <img> with a 'usemap' attribute doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("img"));
+ assert_true(details.open)
+}, "Clicking an <img> without a 'usemap' attribute opens <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_button"));
+ assert_false(details.open)
+}, "Clicking an <input type=button> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_reset"));
+ assert_false(details.open)
+}, "Clicking an <input type=reset> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_submit"));
+ assert_false(details.open)
+}, "Clicking an <input type=submit> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_text"));
+ assert_false(details.open)
+}, "Clicking an <input type=text> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_search"));
+ assert_false(details.open)
+}, "Clicking an <input type=search> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_tel"));
+ assert_false(details.open)
+}, "Clicking an <input type=tel> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_url"));
+ assert_false(details.open)
+}, "Clicking an <input type=url> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_email"));
+ assert_false(details.open)
+}, "Clicking an <input type=email> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_password"));
+ assert_false(details.open)
+}, "Clicking an <input type=password> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_date"));
+ assert_false(details.open)
+}, "Clicking an <input type=date> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_month"));
+ assert_false(details.open)
+}, "Clicking an <input type=month> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_week"));
+ assert_false(details.open)
+}, "Clicking an <input type=week> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_time"));
+ assert_false(details.open)
+}, "Clicking an <input type=time> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_datetime-local"));
+ assert_false(details.open)
+}, "Clicking an <input type=datetime-local> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_number"));
+ assert_false(details.open)
+}, "Clicking an <input type=number> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_range"));
+ assert_false(details.open)
+}, "Clicking an <input type=range> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_color"));
+ assert_false(details.open)
+}, "Clicking an <input type=color> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_checkbox"));
+ assert_false(details.open)
+}, "Clicking an <input type=checkbox> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_radio"));
+ assert_false(details.open)
+}, "Clicking an <input type=radio> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_file"));
+ assert_false(details.open)
+}, "Clicking an <input type=file> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_image"));
+ assert_false(details.open)
+}, "Clicking an <input type=image> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("label"));
+ assert_false(details.open)
+}, "Clicking a <label> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("textarea"));
+ assert_false(details.open)
+}, "Clicking in a <textarea> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("video"));
+ assert_false(details.open)
+}, "Clicking a <video> doesn't open <details>");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html b/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html
new file mode 100644
index 0000000000..dc119de833
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html
@@ -0,0 +1,164 @@
+<!doctype html>
+<meta charset="utf-8" />
+<meta name="author" title="Luke Warlow" href="mailto:lwarlow@igalia.com" />
+<link rel="help" href="https://open-ui.org/components/interest-invokers.explainer/" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<button id="buttonInvoker" interesttarget="interestee"></button>
+<a id="aInvoker" interesttarget="interestee"></a>
+<input type="button" id="inputInvoker" interesttarget="interestee" />
+<div id="interestee"></div>
+
+<script>
+ test(function () {
+ assert_equals(buttonInvoker.interestTargetElement, interestee);
+ assert_equals(aInvoker.interestTargetElement, interestee);
+ assert_equals(inputInvoker.interestTargetElement, interestee);
+ }, "interestTargetElement reflects interestee HTML element");
+
+ test(function () {
+ const div = document.body.appendChild(document.createElement("div"));
+ buttonInvoker.interestTargetElement = div;
+ aInvoker.interestTargetElement = div;
+ inputInvoker.interestTargetElement = div;
+ assert_equals(buttonInvoker.interestTargetElement, div);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "");
+ assert_equals(aInvoker.interestTargetElement, div);
+ assert_equals(aInvoker.getAttribute("interesttarget"), "");
+ assert_equals(inputInvoker.interestTargetElement, div);
+ assert_equals(inputInvoker.getAttribute("interesttarget"), "");
+ }, "interestTargetElement reflects set value");
+
+ test(function () {
+ const host = document.body.appendChild(document.createElement("div"));
+ const shadow = host.attachShadow({ mode: "open" });
+ const button = shadow.appendChild(document.createElement("button"));
+ button.interestTargetElement = interestee;
+ assert_equals(button.interestTargetElement, interestee);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "");
+ }, "interestTargetElement reflects set value across shadow root into light dom");
+
+ test(function () {
+ const host = document.body.appendChild(document.createElement("div"));
+ const shadow = host.attachShadow({ mode: "open" });
+ const div = shadow.appendChild(document.createElement("div"));
+ buttonInvoker.interestTargetElement = div;
+ assert_equals(buttonInvoker.interestTargetElement, null);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "");
+ }, "interestTargetElement does not reflect set value inside shadowroot");
+
+ test(function () {
+ buttonInvoker.setAttribute('interesttarget', 'invalid');
+ assert_equals(buttonInvoker.interestTargetElement, null);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "invalid");
+ aInvoker.setAttribute('interesttarget', 'invalid');
+ assert_equals(aInvoker.interestTargetElement, null);
+ assert_equals(aInvoker.getAttribute("interesttarget"), "invalid");
+ inputInvoker.setAttribute('interesttarget', 'invalid');
+ assert_equals(inputInvoker.interestTargetElement, null);
+ assert_equals(inputInvoker.getAttribute("interesttarget"), "invalid");
+ }, "interestTargetElement does not reflect invalid value");
+
+ test(function () {
+ assert_throws_js(
+ TypeError,
+ function () {
+ buttonInvoker.interestTargetElement = {};
+ },
+ "interestTargetElement attribute value must be an instance of Element",
+ );
+ assert_throws_js(
+ TypeError,
+ function () {
+ aInvoker.interestTargetElement = {};
+ },
+ "interestTargetElement attribute value must be an instance of Element",
+ );
+ assert_throws_js(
+ TypeError,
+ function () {
+ inputInvoker.interestTargetElement = {};
+ },
+ "interestTargetElement attribute value must be an instance of Element",
+ );
+ }, "interestTargetElement throws error on assignment of non Element");
+
+ test(function () {
+ assert_false(buttonInvoker.hasAttribute("interestaction"));
+ assert_equals(buttonInvoker.interestAction, "");
+ assert_false(aInvoker.hasAttribute("interestaction"));
+ assert_equals(aInvoker.interestAction, "");
+ assert_false(inputInvoker.hasAttribute("interestaction"));
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute not present");
+
+ test(function () {
+ buttonInvoker.setAttribute("interestaction", "");
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "");
+ assert_equals(buttonInvoker.interestAction, "");
+ aInvoker.setAttribute("interestaction", "");
+ assert_equals(aInvoker.getAttribute("interestaction"), "");
+ assert_equals(aInvoker.interestAction, "");
+ inputInvoker.setAttribute("interestaction", "");
+ assert_equals(inputInvoker.getAttribute("interestaction"), "");
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute empty, setAttribute version");
+
+ test(function () {
+ buttonInvoker.interestAction = "";
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "");
+ assert_equals(buttonInvoker.interestAction, "");
+ aInvoker.interestAction = "";
+ assert_equals(aInvoker.getAttribute("interestaction"), "");
+ assert_equals(aInvoker.interestAction, "");
+ inputInvoker.interestAction = "";
+ assert_equals(inputInvoker.getAttribute("interestaction"), "");
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute empty, IDL setter version");
+
+ test(function () {
+ buttonInvoker.interestAction = "fooBarBaz";
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "fooBarBaz");
+ assert_equals(buttonInvoker.interestAction, "fooBarBaz");
+ aInvoker.interestAction = "fooBarBaz";
+ assert_equals(aInvoker.getAttribute("interestaction"), "fooBarBaz");
+ assert_equals(aInvoker.interestAction, "fooBarBaz");
+ inputInvoker.interestAction = "fooBarBaz";
+ assert_equals(inputInvoker.getAttribute("interestaction"), "fooBarBaz");
+ assert_equals(inputInvoker.interestAction, "fooBarBaz");
+ }, "interestAction reflects same casing");
+
+ test(function () {
+ buttonInvoker.interestAction = [];
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "");
+ assert_equals(buttonInvoker.interestAction, "");
+ aInvoker.interestAction = [];
+ assert_equals(aInvoker.getAttribute("interestaction"), "");
+ assert_equals(aInvoker.interestAction, "");
+ inputInvoker.interestAction = [];
+ assert_equals(inputInvoker.getAttribute("interestaction"), "");
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute set to []");
+
+ test(function () {
+ buttonInvoker.interestAction = [1, 2, 3];
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "1,2,3");
+ assert_equals(buttonInvoker.interestAction, "1,2,3");
+ aInvoker.interestAction = [1, 2, 3];
+ assert_equals(aInvoker.getAttribute("interestaction"), "1,2,3");
+ assert_equals(aInvoker.interestAction, "1,2,3");
+ inputInvoker.interestAction = [1, 2, 3];
+ assert_equals(inputInvoker.getAttribute("interestaction"), "1,2,3");
+ assert_equals(inputInvoker.interestAction, "1,2,3");
+ }, "interestAction reflects tostring value");
+
+ test(function () {
+ buttonInvoker.interestAction = {};
+ assert_equals(buttonInvoker.interestAction, "[object Object]");
+ aInvoker.interestAction = {};
+ assert_equals(aInvoker.interestAction, "[object Object]");
+ inputInvoker.interestAction = {};
+ assert_equals(inputInvoker.interestAction, "[object Object]");
+ }, "interestAction reflects tostring value 2");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html
index b003daf20d..5a2854fe31 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html
@@ -53,14 +53,14 @@
test(function () {
assert_false(invoker.hasAttribute("invokeaction"));
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute not present");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute not present");
test(function () {
invoker.setAttribute("invokeaction", "");
assert_equals(invoker.getAttribute("invokeaction"), "");
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute empty");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute empty, setAttribute version");
test(function () {
invoker.invokeAction = "fooBarBaz";
@@ -71,8 +71,8 @@
test(function () {
invoker.invokeAction = "";
assert_equals(invoker.getAttribute("invokeaction"), "");
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute empty 2");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute empty, IDL version");
test(function () {
invoker.invokeAction = [1, 2, 3];
@@ -83,8 +83,8 @@
test(function () {
invoker.invokeAction = [];
assert_equals(invoker.getAttribute("invokeaction"), "");
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute set to []");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute set to []");
test(function () {
invoker.invokeAction = {};
diff --git a/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html
index 82910b3d44..382f808071 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html
@@ -15,9 +15,9 @@
<script>
test(function () {
const event = new InvokeEvent("test");
- assert_equals(event.action, "auto");
+ assert_equals(event.action, "");
assert_readonly(event, "action", "readonly attribute value");
- }, "action is a readonly defaulting to 'auto'");
+ }, "action is a readonly defaulting to ''");
test(function () {
const event = new InvokeEvent("test");
@@ -32,7 +32,7 @@
test(function () {
const event = new InvokeEvent("test", { action: undefined });
- assert_equals(event.action, "auto");
+ assert_equals(event.action, "");
}, "action set to undefined");
test(function () {
diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
index b19c1d3adc..d8d9c04022 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
@@ -22,7 +22,7 @@
assert_equals(event.bubbles, false, "bubbles");
assert_equals(event.composed, true, "composed");
assert_equals(event.isTrusted, true, "isTrusted");
- assert_equals(event.action, "auto", "action");
+ assert_equals(event.action, "", "action");
assert_equals(event.target, invokee, "target");
assert_equals(event.invoker, invokerbutton, "invoker");
}, "event dispatches on click");
@@ -107,6 +107,7 @@
"invoke",
(event) => {
eventInvoker = event.invoker;
+ eventTarget = event.target;
called = true;
},
{ once: true },
@@ -114,6 +115,7 @@
invokerbutton.invokeTargetElement = svgInvokee;
await clickOn(invokerbutton);
assert_true(called, "event was called");
- assert_true(eventInvoker == svgInvokee, "event invoker is set to right element");
- }, "event dispatches if invoker is non-HTML Element");
+ assert_equals(eventInvoker, invokerbutton, "event.invoker is set to right element");
+ assert_equals(eventTarget, svgInvokee, "event.target is set to right element");
+ }, "event dispatches if invokee is non-HTML Element");
</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html
new file mode 100644
index 0000000000..774d308703
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html
@@ -0,0 +1,455 @@
+<!doctype html>
+<meta charset="utf-8" />
+<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
+<meta name="timeout" content="long">
+<link rel="help" href="https://open-ui.org/components/invokers.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>
+<script src="resources/invoker-utils.js"></script>
+
+<dialog id="invokee">
+ <button id="containedinvoker" invoketarget="invokee"></button>
+</dialog>
+<button id="invokerbutton" invoketarget="invokee"></button>
+
+<script>
+ function resetState() {
+ invokee.close();
+ try { invokee.hidePopover(); } catch {}
+ invokee.removeAttribute("popover");
+ invokerbutton.removeAttribute("invokeaction");
+ containedinvoker.removeAttribute("invokeaction");
+ }
+
+ // opening a dialog
+
+ [null, "", "showmodal", /* test case sensitivity */ "sHoWmOdAl"].forEach(
+ (action) => {
+ ["property", "attribute"].forEach((setType) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ invokerbutton.invokeaction = action;
+ } else {
+ invokerbutton.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) closed dialog opens as modal`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ if (typeof action === "string") {
+ if (setType === "property") {
+ invokerbutton.invokeaction = action;
+ } else {
+ invokerbutton.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) closed dialog with preventDefault is noop`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ invokerbutton.setAttribute("invokeaction", "close");
+ },
+ { once: true },
+ );
+ if (typeof action === "string") {
+ if (setType === "property") {
+ invokerbutton.invokeaction = action;
+ } else {
+ invokerbutton.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) while changing action still opens as modal`,
+ );
+ });
+ },
+ );
+
+ // closing an already open dialog
+
+ [null, "", "close", /* test case sensitivity */ "cLoSe"].forEach((action) => {
+ ["property", "attribute"].forEach((setType) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open dialog closes`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open dialog with preventDefault is no-op`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open modal dialog with preventDefault is no-op`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "show");
+ },
+ { once: true },
+ );
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open dialog while changing action still closes`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "show");
+ },
+ { once: true },
+ );
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open modal dialog while changing action still closes`,
+ );
+ });
+ });
+
+ // showmodal explicit behaviours
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", "showModal");
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as showmodal) open dialog is noop");
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", "showmodal");
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "close");
+ },
+ { once: true },
+ );
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as showmodal) open modal, while changing action still a no-op");
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ invokerbutton.setAttribute("invokeaction", "showmodal");
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.setAttribute("popover", "auto");
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as showmodal) closed popover dialog opens as modal");
+
+ // close explicit behaviours
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ invokerbutton.setAttribute("invokeaction", "close");
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as close) already closed dialog is noop");
+
+ // invalid
+ [
+ "foo",
+ "foo-bar",
+ "auto",
+ "showpopover",
+ "hidepopover",
+ "togglepopover",
+ "showpicker",
+ ].forEach((action) => {
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on dialog does nothing`);
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", action);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on open dialog does nothing`);
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", action);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on open modal dialog does nothing`);
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", action);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "");
+ },
+ { once: true },
+ );
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on open modal while changing the attributer does nothing`);
+ });
+
+ // Open Popovers using Dialog actions
+ ["showmodal", "close", ""].forEach((action) => {
+ ["manual", "auto"].forEach((popoverState) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.setAttribute("popover", popoverState);
+ invokee.showPopover();
+ containedinvoker.setAttribute("invokeaction", action);
+ assert_true(
+ invokee.matches(":popover-open"),
+ "invokee :popover-open",
+ );
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ await clickOn(containedinvoker);
+ assert_true(
+ invokee.matches(":popover-open"),
+ "invokee :popover-open",
+ );
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) dialog as open popover=${popoverState} is noop`,
+ );
+ });
+ });
+
+ // Elements being disconnected during invoke steps
+ ["showmodal", "close", ""].forEach((action) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(() => {
+ document.body.prepend(invokee);
+ resetState();
+ });
+ const invokee = document.querySelector("#invokee");
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ invokee.remove();
+ },
+ {
+ once: true,
+ },
+ );
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) dialog that is removed is noop`,
+ );
+
+ promise_test(
+ async function (t) {
+ const invokerbutton = document.createElement("button");
+ invokerbutton.invokeTargetElement = invokee;
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) dialog from a detached invoker`,
+ );
+
+ promise_test(
+ async function (t) {
+ const invokerbutton = document.createElement("button");
+ const invokee = document.createElement("dialog");
+ invokerbutton.invokeTargetElement = invokee;
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) detached dialog from a detached invoker`,
+ );
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html
index 03eba22285..2bddfa7621 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html
@@ -10,7 +10,7 @@
<script src="resources/invoker-utils.js"></script>
<div id="invokee" popover>
- <button id="invokerbutton2" invoketarget="invokee"></button>
+ <button id="containedinvoker" invoketarget="invokee"></button>
</div>
<button id="invokerbutton" invoketarget="invokee"></button>
@@ -44,7 +44,7 @@
promise_test(async function (t) {
invokee.showPopover();
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_false(invokee.matches(":popover-open"));
}, "invoking (as auto) from within open popover closes");
@@ -55,7 +55,7 @@
once: true,
});
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_true(invokee.matches(":popover-open"));
}, "invoking (as auto) open popover with preventDefault does not close");
@@ -93,8 +93,8 @@
promise_test(async function (t) {
invokee.showPopover();
- invokerbutton2.setAttribute("invokeaction", "togglepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "togglepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
assert_true(invokee.matches(":popover-open"));
await clickOn(invokerbutton);
assert_false(invokee.matches(":popover-open"));
@@ -102,23 +102,23 @@
promise_test(async function (t) {
invokee.showPopover();
- invokerbutton2.setAttribute("invokeaction", "togglepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "togglepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_false(invokee.matches(":popover-open"));
}, "invoking (as togglepopover) from within open popover closes");
promise_test(async function (t) {
invokee.showPopover();
t.add_cleanup(() => invokee.hidePopover());
- invokerbutton2.setAttribute("invokeaction", "togglepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "togglepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.addEventListener("invoke", (e) => e.preventDefault(), {
once: true,
});
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_true(invokee.matches(":popover-open"));
}, "invoking (as togglepopover) open popover with preventDefault does not close");
@@ -175,35 +175,59 @@
}, "invoking (as hidepopover) closed popover is noop");
promise_test(async function (t) {
- invokerbutton2.setAttribute("invokeaction", "hidepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "hidepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.showPopover();
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
t.add_cleanup(() => invokee.hidePopover());
assert_false(invokee.matches(":popover-open"));
}, "invoking (as hidepopover) open popover closes");
promise_test(async function (t) {
- invokerbutton2.setAttribute("invokeaction", "hIdEpOpOvEr");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "hIdEpOpOvEr");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.showPopover();
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
t.add_cleanup(() => invokee.hidePopover());
assert_false(invokee.matches(":popover-open"));
}, "invoking (as hidepopover - case insensitive) open popover closes");
promise_test(async function (t) {
- invokerbutton2.setAttribute("invokeaction", "hidepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "hidepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.showPopover();
t.add_cleanup(() => invokee.hidePopover());
assert_true(invokee.matches(":popover-open"));
invokee.addEventListener("invoke", (e) => e.preventDefault(), {
once: true,
});
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_true(invokee.matches(":popover-open"));
}, "invoking (as hidepopover) open popover with preventDefault does not close");
+
+ // invalid
+
+ ["foo", "togglemodal", "showpicker", "toggle", "open", "close"].forEach(action => {
+ promise_test(async function (t) {
+ invokerbutton.setAttribute("invokeaction", action);
+ t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction"));
+ assert_false(invokee.matches(":popover-open"));
+ await clickOn(invokerbutton);
+ assert_false(invokee.matches(":popover-open"));
+ }, `invoking (as ${action}) on popover does nothing`);
+
+ promise_test(async function (t) {
+ invokerbutton.setAttribute("invokeaction", action);
+ t.add_cleanup(() => {
+ invokerbutton.removeAttribute("invokeaction")
+ invokee.hidePopover();
+ });
+ invokee.showPopover()
+ assert_true(invokee.matches(":popover-open"));
+ await clickOn(invokerbutton);
+ assert_true(invokee.matches(":popover-open"));
+ }, `invoking (as ${action}) on open popover does nothing`);
+ })
</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js b/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js
index 317945502d..8420f24b6f 100644
--- a/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js
+++ b/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js
@@ -2,9 +2,13 @@ function waitForRender() {
return new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
}
async function clickOn(element) {
- const actions = new test_driver.Actions();
await waitForRender();
- await actions.pointerMove(0, 0, {origin: element})
+ let rect = element.getBoundingClientRect();
+ let actions = new test_driver.Actions();
+ // FIXME: Switch to pointerMove(0, 0, {origin: element}) once
+ // https://github.com/web-platform-tests/wpt/issues/41257 is fixed.
+ await actions
+ .pointerMove(Math.round(rect.x + rect.width / 2), Math.round(rect.y + rect.height / 2), {})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
diff --git a/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html
new file mode 100644
index 0000000000..98c3d70e98
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<!--The permission element should have some limits for specific properties:
+ * font-weight is adjusted to be at least 200.
+ * font-style should only have "normal" or "italic" values.
+-->
+<style>
+ #id1 {
+ font-weight: 100;
+ font-style: oblique 30deg;
+ }
+ #id2 {
+ font-weight: 300;
+ font-style: italic;
+ }
+</style>
+
+
+<permission id="id1" type="geolocation">
+<permission id="id2" type="camera">
+
+<script>
+ test(function(){
+ var el_outside_bounds = document.getElementById("id1");
+ assert_equals(getComputedStyle(el_outside_bounds).fontWeight, "200", "font-weight");
+ assert_equals(getComputedStyle(el_outside_bounds).fontStyle, "normal", "font-style");
+ }, "Properties with out-of-bounds values should be corrected");
+
+ test(function(){
+ var el_inside_bounds = document.getElementById("id2");
+ assert_equals(getComputedStyle(el_inside_bounds).fontWeight, "300", "font-weight");
+ assert_equals(getComputedStyle(el_inside_bounds).fontStyle, "italic", "font-style");
+ }, "Properties with values in bounds should not be modified");
+</script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html b/testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html
new file mode 100644
index 0000000000..c7186563f0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<!--The permission element does not allow certain CSS properties
+-->
+<style>
+ #id1 {
+ border-image: url('test-url');
+ background-image: url('test-url');
+ clip-path: circle(10px);
+ filter: blur(10px);
+ mask: url('test-url');
+ padding-left: 10px;
+ transform: rotate(10);
+ }
+</style>
+
+<permission id="id1" type="geolocation">
+
+<script>
+ test(function(){
+ var el_with_negatives = document.getElementById("id1");
+ assert_equals(getComputedStyle(el_with_negatives).borderImage, "none", "border-image");
+ assert_equals(getComputedStyle(el_with_negatives).backgroundImage, "none", "background-image");
+ assert_equals(getComputedStyle(el_with_negatives).clipPath, "none", "clip-path");
+ assert_equals(getComputedStyle(el_with_negatives).filter, "none", "filter");
+ assert_equals(getComputedStyle(el_with_negatives).mask, "none", "mask");
+ assert_equals(getComputedStyle(el_with_negatives).paddingLeft, "0px", "padding-left");
+ assert_equals(getComputedStyle(el_with_negatives).transform, "none", "transform");
+ }, "None of the listed properties should be applied");
+</script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html b/testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html
new file mode 100644
index 0000000000..97290bb4df
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<!--The permission element should not allow setting negative margins or outline-offset
+-->
+<style>
+ #id1 {
+ outline-offset: -50px;
+ margin-top: -50px;
+ margin-left: -50px;
+ margin-bottom: -50px;
+ margin-right: -50px;
+ }
+ #id2 {
+ outline-offset: 50px;
+ margin-top: 50px;
+ margin-left: 50px;
+ margin-bottom: 50px;
+ margin-right: 50px;
+ }
+
+ /* These various expressions all result in a negative value when calculated */
+ #id3 {
+ outline-offset: min(-50px, 50px);
+ margin-top: min(10%, -50px);
+ margin-left: clamp(-100px, 1vw, -50px);
+ margin-bottom: 1% - 10000px;
+ margin-right: max(min(-1em, 10em), -5%);
+ }
+</style>
+
+
+<permission id="id1" type="geolocation">
+<permission id="id2" type="camera">
+<permission id="id3" type="microphone">
+
+<script>
+ test(function(){
+ var el_with_negatives = document.getElementById("id1");
+ assert_equals(getComputedStyle(el_with_negatives).outlineOffset, "0px", "outline-offset");
+ assert_equals(getComputedStyle(el_with_negatives).marginLeft, "0px", "margin-left");
+ assert_equals(getComputedStyle(el_with_negatives).marginRight, "0px", "margin-right");
+ assert_equals(getComputedStyle(el_with_negatives).marginTop, "0px", "margin-top");
+ assert_equals(getComputedStyle(el_with_negatives).marginBottom, "0px", "margin-bottom");
+ }, "Negative margins/offset should be changed to 0px");
+
+ test(function(){
+ var el_with_positives = document.getElementById("id2");
+ assert_equals(getComputedStyle(el_with_positives).outlineOffset, "50px", "outline-offset");
+ assert_equals(getComputedStyle(el_with_positives).marginLeft, "50px", "margin-left");
+ assert_equals(getComputedStyle(el_with_positives).marginRight, "50px", "margin-right");
+ assert_equals(getComputedStyle(el_with_positives).marginTop, "50px", "margin-top");
+ assert_equals(getComputedStyle(el_with_positives).marginBottom, "50px", "margin-bottom");
+ }, "Positive margins/offset are unaffected");
+
+ test(function(){
+ var el_with_negative_expr = document.getElementById("id3");
+ assert_equals(getComputedStyle(el_with_negative_expr).outlineOffset, "0px", "outline-offset");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginLeft, "0px", "margin-left");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginRight, "0px", "margin-right");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginTop, "0px", "margin-top");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginBottom, "0px", "margin-bottom");
+ }, "Expressions margins/offset should always return at least 0px");
+</script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html
new file mode 100644
index 0000000000..7c87d2d039
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel=help href="https://open-ui.org/components/popover.research.explainer">
+<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/popover-utils.js"></script>
+
+<!-- Once anchor positioning lands in the spec, the tests in this file can
+ be re-inserted into popover-shadow-dom.html. -->
+
+<script>
+ function findPopovers(root) {
+ let popovers = [];
+ if (!root)
+ return popovers;
+ if (root instanceof Element && root.matches('[popover]'))
+ popovers.push(root);
+ popovers.push(...findPopovers(root.shadowRoot));
+ root.childNodes.forEach(child => {
+ popovers.push(...findPopovers(child));
+ })
+ return popovers;
+ }
+ function getPopoverReferences(testId) {
+ const testRoot = document.querySelector(`#${testId}`);
+ assert_true(!!testRoot);
+ return findPopovers(testRoot);
+ }
+</script>
+
+<div id=test1>
+ <button id=t2b1>Test 1 Popover 1</button>
+ <div popover anchor=t2b1 style="top: 200px;">
+ <p>Popover 1</p>
+ <button id=t2b2>Test 1 Popover 2</button>
+ </div>
+ <my-element>
+ <template shadowrootmode=open>
+ <div popover anchor=t2b2 style="top: 400px;">
+ <p>Hiding this popover will hide *all* open popovers,</p>
+ <p>because t2b2 doesn't exist in this context.</p>
+ </div>
+ </template>
+ </my-element>
+</div>
+
+<script>
+ test(function() {
+ const [popover1,popover2] = getPopoverReferences('test1');
+ popover1.showPopover();
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ popover2.showPopover();
+ assert_false(popover1.matches(':popover-open'), 'popover1 open'); // P1 was closed by P2
+ assert_false(isElementVisible(popover1), 'popover1 visible');
+ assert_true(popover2.matches(':popover-open'), 'popover2 open'); // P2 is open
+ assert_true(isElementVisible(popover2), 'popover2 visible');
+ popover2.hidePopover(); // Cleanup
+ }, "anchor references do not cross shadow boundaries");
+</script>
+
+
+<div id=test2>
+ <my-element>
+ <template shadowrootmode=open>
+ <button id=t3b1>Test 2 Popover 1</button>
+ <div popover anchor=t3b1>
+ <p>This popover will stay open when popover2 shows.</p>
+ <slot></slot>
+ </div>
+ </template>
+ <button id=t3b2>Test 2 Popover 2</button>
+ </my-element>
+ <div popover anchor=t3b2>Popover 2</div>
+</div>
+
+<script>
+ promise_test(async function() {
+ const [popover1,popover2] = getPopoverReferences('test2');
+ popover1.showPopover();
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ // Showing popover2 should not close popover1, since it is a flat
+ // tree ancestor of popover2's anchor button.
+ popover2.showPopover();
+ assert_true(popover2.matches(':popover-open'));
+ assert_true(isElementVisible(popover2));
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ popover1.hidePopover();
+ await waitForRender();
+ assert_false(popover1.matches(':popover-open'));
+ assert_false(isElementVisible(popover1));
+ assert_false(popover2.matches(':popover-open'));
+ assert_false(isElementVisible(popover2));
+ }, "anchor references use the flat tree not the DOM tree");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
index 62aa135b56..18ac500270 100644
--- a/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
+++ b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
@@ -8,17 +8,6 @@
<script src="resources/popover-utils.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 findPopovers(root) {
let popovers = [];
if (!root)
@@ -34,16 +23,12 @@
function getPopoverReferences(testId) {
const testRoot = document.querySelector(`#${testId}`);
assert_true(!!testRoot);
- ensureShadowDom(testRoot);
return findPopovers(testRoot);
}
- function showTestPopover(testId,popoverNum) {
- getPopoverReferences(testId)[popoverNum].showPopover();
- }
</script>
<div id=test1>
- <button onclick='showTestPopover("test1",0)'>Test1 Popover</button>
+ <button>Test1 Popover</button>
<my-element>
<template shadowrootmode=open>
<div popover>
@@ -64,83 +49,14 @@
</script>
-<div id=test2>
- <button id=t2b1 onclick='showTestPopover("test2",0)'>Test 2 Popover 1</button>
- <div popover anchor=t2b1 style="top: 200px;">
- <p>Popover 1</p>
- <button id=t2b2 onclick='showTestPopover("test2",1)'>Test 2 Popover 2</button>
- </div>
- <my-element>
- <template shadowrootmode=open>
- <div popover anchor=t2b2 style="top: 400px;">
- <p>Hiding this popover will hide *all* open popovers,</p>
- <p>because t2b2 doesn't exist in this context.</p>
- </div>
- </template>
- </my-element>
-</div>
-
-<script>
- test(function() {
- const [popover1,popover2] = getPopoverReferences('test2');
- popover1.showPopover();
- assert_true(popover1.matches(':popover-open'));
- assert_true(isElementVisible(popover1));
- popover2.showPopover();
- assert_false(popover1.matches(':popover-open'), 'popover1 open'); // P1 was closed by P2
- assert_false(isElementVisible(popover1), 'popover1 visible');
- assert_true(popover2.matches(':popover-open'), 'popover2 open'); // P2 is open
- assert_true(isElementVisible(popover2), 'popover2 visible');
- popover2.hidePopover(); // Cleanup
- }, "anchor references do not cross shadow boundaries");
-</script>
-
-
-<div id=test3>
- <my-element>
- <template shadowrootmode=open>
- <button id=t3b1 onclick='showTestPopover("test3",0)'>Test 3 Popover 1</button>
- <div popover anchor=t3b1>
- <p>This popover will stay open when popover2 shows.</p>
- <slot></slot>
- </div>
- </template>
- <button id=t3b2 onclick='showTestPopover("test3",1)'>Test 3 Popover 2</button>
- </my-element>
- <div popover anchor=t3b2>Popover 2</div>
-</div>
-
-<script>
- promise_test(async function() {
- const [popover1,popover2] = getPopoverReferences('test3');
- popover1.showPopover();
- assert_true(popover1.matches(':popover-open'));
- assert_true(isElementVisible(popover1));
- // Showing popover2 should not close popover1, since it is a flat
- // tree ancestor of popover2's anchor button.
- popover2.showPopover();
- assert_true(popover2.matches(':popover-open'));
- assert_true(isElementVisible(popover2));
- assert_true(popover1.matches(':popover-open'));
- assert_true(isElementVisible(popover1));
- popover1.hidePopover();
- await waitForRender();
- assert_false(popover1.matches(':popover-open'));
- assert_false(isElementVisible(popover1));
- assert_false(popover2.matches(':popover-open'));
- assert_false(isElementVisible(popover2));
- }, "anchor references use the flat tree not the DOM tree");
-</script>
-
-
<div id=test4>
- <button id=t4b1 onclick='showTestPopover("test4",0)'>Test 4 Popover 1</button>
- <div popover anchor=t4b1>
+ <button>Test 4 Popover 1</button>
+ <div popover>
<p>This should not get hidden when popover2 opens.</p>
<my-element>
<template shadowrootmode=open>
- <button id=t4b2 onclick='showTestPopover("test4",1)'>Test 4 Popover 2</button>
- <div popover anchor=t4b2>
+ <button id=t4b2>Test 4 Popover 2</button>
+ <div popover>
<p>This should not hide popover1.</p>
</div>
</template>
diff --git a/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html b/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html
index d0750fdd4c..b4f99631ab 100644
--- a/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html
+++ b/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html
@@ -11,7 +11,7 @@
<script>
test(() => {
- assert_equals(mybutton.popoverTargetElement.id, "mypopover",
+ assert_equals(mybutton.popoverTargetElement.id, "mypopover",
'Setting element.popoverTargetElement to a valid element should work');
mybutton.popoverTargetElement = null;
@@ -33,13 +33,13 @@ test(() => {
'Assigning to element.popoverTargetElement should set the popovertarget attribute.');
mybutton.setAttribute("popovertarget", 'invalid');
- assert_equals(mybutton.popoverTargetElement, null,
+ assert_equals(mybutton.popoverTargetElement, null,
'Setting the popovertarget attribute to a localName that is not attr should remove the existing element from element.popoverTargetElement.');
mybutton.popoverTargetElement = mypopover;
mybutton.setAttribute("popovertarget", "");
- assert_equals(mybutton.popoverTargetElement.id, "mypopover",
- 'Setting the popovertarget attribute to empty string right after explicitly setting attribute element should have no effect.');
+ assert_equals(mybutton.popoverTargetElement, null,
+ 'Setting the popovertarget attribute to empty string right after setting explicit element does remove the explicit element.');
mybutton.setAttribute("popovertarget", "mypopover");
assert_equals(mybutton.popoverTargetElement.id, "mypopover",
diff --git a/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js b/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js
index bfc1f89ec1..96ac7e03f0 100644
--- a/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js
+++ b/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js
@@ -7,9 +7,13 @@ function waitForTick() {
}
async function clickOn(element) {
- const actions = new test_driver.Actions();
await waitForRender();
- await actions.pointerMove(0, 0, {origin: element})
+ let rect = element.getBoundingClientRect();
+ let actions = new test_driver.Actions();
+ // FIXME: Switch to pointerMove(0, 0, {origin: element}) once
+ // https://github.com/web-platform-tests/wpt/issues/41257 is fixed.
+ await actions
+ .pointerMove(Math.round(rect.x + rect.width / 2), Math.round(rect.y + rect.height / 2), {})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
index 50933da2c1..3645279d61 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Parse errors in different files should be reported " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
index 51adb09d11..d40aaba8df 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Instantiation errors in different files should be reported " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
index bc52119bfe..2d74af864b 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Evaluation errors are cached in intermediate module scripts");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
index 2480a60d6d..0484b614ab 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"network error has higher priority than parse error");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
index 673bf28ca2..7303a838a5 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"parse error has higher priority than instantiation error");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
index 8a16266f4c..f80f74cbe4 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"instantiation error has higher priority than evaluation error");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html
index 3f2bb35f4e..b12d178fb5 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that exceptions during evaluation lead to error events on " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html
index 4f2b3c5a74..a890ca6457 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that ill-founded cyclic dependencies cause ReferenceError " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html
index 9bfb5df2cf..4062bc8a3a 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that exceptions during evaluation lead to error events on " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html
index 0b4b7d1662..256aea508e 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that exceptions during evaluation lead to error events on " +
diff --git a/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html b/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
index 3a9d90c76b..e658500a4e 100644
--- a/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
+++ b/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
@@ -30,13 +30,13 @@
&#x202D; - The LRO (left-to-right override) formatting character.
&#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
In each DIV of the test:
- - the first BDI, having no characters with strong direction, should inherit the parent direction;
+ - the first BDI, having no characters with strong direction, should be LTR by default;
- the second BDI, having an LTR character first, should be LTR by default;
- the third BDI, having an RTL character first, should be RTL by default.
</div>
<div class="test">
<div dir="ltr"><bdi>[:)]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
- <div dir="rtl"><bdi>[(:]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
+ <div dir="rtl"><bdi>[:)]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
</div>
<div class="ref">
<div dir="ltr">&#x202D;[:)], [+- a &#x05D1;], [d &#x05D2; 1]...&#x202C;</div>