diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
commit | d8bbc7858622b6d9c278469aab701ca0b609cddf (patch) | |
tree | eff41dc61d9f714852212739e6b3738b82a2af87 /testing/web-platform/tests/html/semantics | |
parent | Releasing progress-linux version 125.0.3-1~progress7.99u1. (diff) | |
download | firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/semantics')
81 files changed, 2385 insertions, 868 deletions
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html index 56edf25aa8..855f02d3b1 100644 --- a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html +++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html @@ -55,10 +55,13 @@ function type_codecs_test(type, audioCodecs, videoCodecs) { var typeSupported = false; var codecSupported = false; + var mimeSupported = canPlayType(type); + // Test 'type' without codecs. // Spec: Generally, a user agent should never return "probably" for a type // that allows the codecs parameter if that parameter is not present. test(function() { + assert_implements_optional(mimeSupported, type) t(type, 'maybe'); t(type + ';', 'maybe'); t(type + ';codecs', 'maybe'); @@ -69,6 +72,7 @@ function type_codecs_test(type, audioCodecs, videoCodecs) { function test_codec(codec) { var typeWithCodec = mime(type, [codec]); test(function() { + assert_implements_optional(canPlayType(typeWithCodec), type) t(typeWithCodec, 'probably'); codecSupported = true; }, typeWithCodec + ' (optional)'); @@ -81,6 +85,7 @@ function type_codecs_test(type, audioCodecs, videoCodecs) { // Test different pairings and orderings of audio+video codecs. if (audioCodecs.length > 0 && videoCodecs.length > 0) { test(function() { + assert_implements_optional(mimeSupported, type) audioCodecs.forEach(function(ac) { videoCodecs.forEach(function(vc) { var canPlayBoth = canPlayType(mime(type, [ac, vc])); @@ -93,6 +98,7 @@ function type_codecs_test(type, audioCodecs, videoCodecs) { }, type + ' codecs subset'); test(function() { + assert_implements_optional(mimeSupported, type) audioCodecs.forEach(function(ac) { videoCodecs.forEach(function(vc) { assert_equals(canPlayType(mime(type, [ac, vc])), diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html index 3b4c3542a9..1a8aabcaff 100644 --- a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html +++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html @@ -4,7 +4,7 @@ <script src="/resources/testharnessreport.js"></script> <video> <source src="/media/test.mp4" type="video/mp4"> - <source src="/media/test.ogv" type="video/ogg"> + <source src="/media/test.webm" type="video/webm"> </video> <script> test(function() { @@ -13,4 +13,4 @@ test(function() { track.addCue(new VTTCue(0.0, 10.0, 'wow wow')); track.mode = 'showing'; }); -</script>
\ No newline at end of file +</script> 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-delivered.tentative.sub.window.js index 95d53e1fe3..8074314557 100644 --- 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-delivered.tentative.sub.window.js @@ -9,16 +9,6 @@ '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, diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin-frame.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin-frame.tentative.sub.window.js new file mode 100644 index 0000000000..a2191b352a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin-frame.tentative.sub.window.js @@ -0,0 +1,18 @@ +// 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'; + +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'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-delivered-both.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-delivered-both.tentative.sub.window.js new file mode 100644 index 0000000000..540cc338c9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-delivered-both.tentative.sub.window.js @@ -0,0 +1,20 @@ +// META: title=Top-level navigation tests with 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe( + main, 'HTTP_ORIGIN', '', + 'allow-top-navigation allow-top-navigation-by-user-activation allow-same-origin'); + + await attemptTopNavigation(iframe_1, true); +}, 'A frame with both top navigation delivered sandbox flags uses the less \ + restrictive one'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-delivered.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-delivered.tentative.sub.window.js new file mode 100644 index 0000000000..c020513012 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-delivered.tentative.sub.window.js @@ -0,0 +1,18 @@ +// META: title=Top-level navigation tests with 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe( + main, 'HTTP_ORIGIN', '', 'allow-top-navigation allow-same-origin'); + + await attemptTopNavigation(iframe_1, true); +}, 'A same-origin frame with delivered sandbox flags can navigate top'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-frame-both.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-frame-both.tentative.sub.window.js new file mode 100644 index 0000000000..ff7d2eb584 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-frame-both.tentative.sub.window.js @@ -0,0 +1,20 @@ +// META: title=Top-level navigation tests with 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe( + main, 'HTTP_ORIGIN', + 'allow-top-navigation allow-top-navigation-by-user-activation', ''); + + await attemptTopNavigation(iframe_1, true); +}, 'A frame with both top navigation frame sandbox flags uses the less \ + restrictive one'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-frame.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-frame.tentative.sub.window.js new file mode 100644 index 0000000000..35abc554b6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-frame.tentative.sub.window.js @@ -0,0 +1,18 @@ +// META: title=Top-level navigation tests with 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe( + main, 'HTTP_ORIGIN', 'allow-top-navigation allow-same-origin', ''); + + await attemptTopNavigation(iframe_1, true); +}, 'A same-origin frame with frame sandbox flags can navigate top'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-unsandboxed.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-unsandboxed.tentative.sub.window.js new file mode 100644 index 0000000000..c2d78b6dd5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-unsandboxed.tentative.sub.window.js @@ -0,0 +1,17 @@ +// META: title=Top-level navigation tests with 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_ORIGIN', '', ''); + + await attemptTopNavigation(iframe_1, true); +}, 'A same-origin unsandboxed frame can 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 deleted file mode 100644 index 1d5ea93830..0000000000 --- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js +++ /dev/null @@ -1,56 +0,0 @@ -// META: title=Top-level navigation tests with 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'; - -/* ----------------------- SAME ORIGIN (A -> A) TESTS ----------------------- */ - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", "allow-top-navigation allow-same-origin"); - - await attemptTopNavigation(iframe_1, true); -}, "A same-origin frame with delivered sandbox flags can navigate top"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "allow-top-navigation allow-same-origin", ""); - - await attemptTopNavigation(iframe_1, true); -}, "A same-origin frame with frame sandbox flags can navigate top"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", ""); - - await attemptTopNavigation(iframe_1, true); -}, "A same-origin unsandboxed frame can navigate top"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", - "allow-top-navigation allow-top-navigation-by-user-activation allow-same-origin"); - - await attemptTopNavigation(iframe_1, true); -}, "A frame with both top navigation delivered sandbox flags uses the less \ - restrictive one"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", - "allow-top-navigation allow-top-navigation-by-user-activation", ""); - - await attemptTopNavigation(iframe_1, true); -}, "A frame with both top navigation frame sandbox flags uses the less \ - restrictive one"); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-origin-escalate.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-origin-escalate.tentative.sub.window.js new file mode 100644 index 0000000000..c394699d85 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-origin-escalate.tentative.sub.window.js @@ -0,0 +1,20 @@ +// META: title=Top-level navigation tests with frames that try to give themselves top-nav permission +// 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_REMOTE_ORIGIN', '', ''); + const iframe_2 = await createNestedIframe( + iframe_1, 'HTTP_REMOTE_ORIGIN', 'allow-top-navigation', ''); + + await attemptTopNavigation(iframe_2, false); +}, 'A cross origin unsandboxed frame can\'t escalate privileges in a child \ + frame'); 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 index 26db4eeaca..cacc5bd983 100644 --- 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 @@ -20,24 +20,3 @@ promise_test(async t => { 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 deleted file mode 100644 index 2ea0ba606e..0000000000 --- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js +++ /dev/null @@ -1,63 +0,0 @@ -// META: title=Top-level navigation tests with frames that try to give themselves top-nav permission -// 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'; - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_REMOTE_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_REMOTE_ORIGIN", "allow-top-navigation", ""); - - await attemptTopNavigation(iframe_2, false); -}, "A cross origin unsandboxed frame can't escalate privileges in a child \ - frame"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_REMOTE_ORIGIN", "allow-top-navigation", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "OTHER_ORIGIN", "", ""); - - await attemptTopNavigation(iframe_2, true); -}, "An unsandboxed grandchild inherits its parents ability to navigate top."); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_ORIGIN", "allow-top-navigation", ""); - - await attemptTopNavigation(iframe_2, true); -}, "A same-origin grandchild with frame allow-top can navigate top"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_ORIGIN", "", "allow-top-navigation"); - - await attemptTopNavigation(iframe_2, false); -}, "A sandboxed same-origin grandchild without allow-same-origin can't \ - escalate its own top-nav privileges"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_ORIGIN", "", "allow-same-origin allow-top-navigation"); - - await attemptTopNavigation(iframe_2, true); -}, "A sandboxed same-origin grandchild with allow-same-origin can \ - give itself top-nav privileges"); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-allow-same-origin.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-allow-same-origin.tentative.sub.window.js new file mode 100644 index 0000000000..2be6cd66a7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-allow-same-origin.tentative.sub.window.js @@ -0,0 +1,20 @@ +// META: title=Top-level navigation tests with frames that try to give themselves top-nav permission +// 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_ORIGIN', '', ''); + const iframe_2 = await createNestedIframe( + iframe_1, 'HTTP_ORIGIN', '', 'allow-same-origin allow-top-navigation'); + + await attemptTopNavigation(iframe_2, true); +}, 'A sandboxed same-origin grandchild with allow-same-origin can \ + give itself top-nav privileges'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-frame-allow-top.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-frame-allow-top.tentative.sub.window.js new file mode 100644 index 0000000000..43ca5eb404 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-frame-allow-top.tentative.sub.window.js @@ -0,0 +1,19 @@ +// META: title=Top-level navigation tests with frames that try to give themselves top-nav permission +// 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_ORIGIN', '', ''); + const iframe_2 = await createNestedIframe( + iframe_1, 'HTTP_ORIGIN', 'allow-top-navigation', ''); + + await attemptTopNavigation(iframe_2, true); +}, 'A same-origin grandchild with frame allow-top can navigate top'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed-cross-origin-parent.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed-cross-origin-parent.tentative.sub.window.js new file mode 100644 index 0000000000..8833ad42bb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed-cross-origin-parent.tentative.sub.window.js @@ -0,0 +1,19 @@ +// META: title=Top-level navigation tests with grandchild 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_REMOTE_ORIGIN', '', ''); + const iframe_2 = await createNestedIframe( + iframe_1, 'HTTP_ORIGIN', 'allow-top-navigation allow-same-origin', ''); + + await attemptTopNavigation(iframe_2, true); +}, 'A same-origin sandboxed grandchild in a cross-origin parent can navigate top'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed-escalate.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed-escalate.tentative.sub.window.js new file mode 100644 index 0000000000..448925144a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed-escalate.tentative.sub.window.js @@ -0,0 +1,20 @@ +// META: title=Top-level navigation tests with frames that try to give themselves top-nav permission +// 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_ORIGIN', '', ''); + const iframe_2 = await createNestedIframe( + iframe_1, 'HTTP_ORIGIN', '', 'allow-top-navigation'); + + await attemptTopNavigation(iframe_2, false); +}, 'A sandboxed same-origin grandchild without allow-same-origin can\'t \ + escalate its own top-nav privileges'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed.tentative.sub.window.js new file mode 100644 index 0000000000..a4b43a7b1f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-sandboxed.tentative.sub.window.js @@ -0,0 +1,19 @@ +// META: title=Top-level navigation tests with grandchild 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_ORIGIN', '', ''); + const iframe_2 = + await createNestedIframe(iframe_1, 'HTTP_ORIGIN', 'allow-scripts', ''); + + await attemptTopNavigation(iframe_2, false); +}, 'A fully sandboxed same-origin grandchild can\'t navigate top'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed-cross-origin-parent.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed-cross-origin-parent.tentative.sub.window.js new file mode 100644 index 0000000000..5abbb9c30c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed-cross-origin-parent.tentative.sub.window.js @@ -0,0 +1,18 @@ +// META: title=Top-level navigation tests with grandchild 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_REMOTE_ORIGIN', '', ''); + const iframe_2 = await createNestedIframe(iframe_1, 'HTTP_ORIGIN', '', ''); + + await attemptTopNavigation(iframe_2, true); +}, 'A same-origin grandchild in a cross-origin parent can navigate top'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed-inherit.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed-inherit.tentative.sub.window.js new file mode 100644 index 0000000000..a31c56b935 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed-inherit.tentative.sub.window.js @@ -0,0 +1,19 @@ +// META: title=Top-level navigation tests with frames that try to give themselves top-nav permission +// 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe( + main, 'HTTP_REMOTE_ORIGIN', 'allow-top-navigation', ''); + const iframe_2 = await createNestedIframe(iframe_1, 'OTHER_ORIGIN', '', ''); + + await attemptTopNavigation(iframe_2, true); +}, 'An unsandboxed grandchild inherits its parents ability to navigate top.'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed.tentative.sub.window.js new file mode 100644 index 0000000000..7fe80dfa1b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild-unsandboxed.tentative.sub.window.js @@ -0,0 +1,18 @@ +// META: title=Top-level navigation tests with grandchild 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'; + +promise_test(async t => { + const main = await setupTest(); + const iframe_1 = await createNestedIframe(main, 'HTTP_ORIGIN', '', ''); + const iframe_2 = await createNestedIframe(iframe_1, 'HTTP_ORIGIN', '', ''); + + await attemptTopNavigation(iframe_2, true); +}, 'An unsandboxed same-origin grandchild can navigate top'); 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 deleted file mode 100644 index 326c1dd54a..0000000000 --- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js +++ /dev/null @@ -1,50 +0,0 @@ -// META: title=Top-level navigation tests with grandchild 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'; - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_ORIGIN", "allow-scripts", ""); - - await attemptTopNavigation(iframe_2, false); -}, "A fully sandboxed same-origin grandchild can't navigate top"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_ORIGIN", "", ""); - - await attemptTopNavigation(iframe_2, true); -}, "An unsandboxed same-origin grandchild can navigate top"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_REMOTE_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_ORIGIN", "", ""); - - await attemptTopNavigation(iframe_2, true); -}, "A same-origin grandchild in a cross-origin parent can navigate top"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_REMOTE_ORIGIN", "", ""); - const iframe_2 = await createNestedIframe(iframe_1, - "HTTP_ORIGIN", "allow-top-navigation allow-same-origin", ""); - - await attemptTopNavigation(iframe_2, true); -}, "A same-origin sandboxed grandchild in a cross-origin parent can navigate top");
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-same-site-no-activation.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-same-site-no-activation.tentative.sub.window.js new file mode 100644 index 0000000000..03350e76e2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-same-site-no-activation.tentative.sub.window.js @@ -0,0 +1,23 @@ +// 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', '', ''); + + 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-same-site.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-same-site.tentative.sub.window.js new file mode 100644 index 0000000000..0ee6b8edcc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-same-site.tentative.sub.window.js @@ -0,0 +1,24 @@ +// 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, 'HTTP_REMOTE_ORIGIN'); + await attemptTopNavigation(new_iframe, true); + }, + 'A same-site unsandboxed iframe navigation does not consume user ' + + 'activation and allows top-level navigation.'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation-no-sticky.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation-no-sticky.tentative.sub.window.js new file mode 100644 index 0000000000..c62155ce30 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation-no-sticky.tentative.sub.window.js @@ -0,0 +1,19 @@ +// 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_1 = await createNestedIframe( + main, 'HTTP_ORIGIN', 'allow-top-navigation-by-user-activation', ''); + + await attemptTopNavigation(iframe_1, false); +}, 'allow-top-navigation-by-user-activation set but no sticky activation'); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation-sticky.tentative.sub.window.js index 5079c8ad14..e62fbdfb22 100644 --- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation-sticky.tentative.sub.window.js @@ -10,8 +10,6 @@ 'use strict'; -/* ------------------------- USER ACTIVATION TESTS ------------------------- */ - promise_test(async t => { const main = await setupTest(); const iframe_1 = await createNestedIframe(main, @@ -20,11 +18,3 @@ promise_test(async t => { await attemptTopNavigation(iframe_1, true); }, "Allow top with user activation + user activation"); - -promise_test(async t => { - const main = await setupTest(); - const iframe_1 = await createNestedIframe(main, - "HTTP_ORIGIN", "allow-top-navigation-by-user-activation", ""); - - await attemptTopNavigation(iframe_1, false); -}, "allow-top-navigation-by-user-activation set but no sticky activation"); diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-object-element/usemap-casing.html b/testing/web-platform/tests/html/semantics/embedded-content/the-object-element/usemap-casing.html index 114a472fb6..9431c73fe7 100644 --- a/testing/web-platform/tests/html/semantics/embedded-content/the-object-element/usemap-casing.html +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-object-element/usemap-casing.html @@ -8,53 +8,53 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<div id="log"></div> +<object data="/images/threecolors.png" usemap="#sanityCheck" width="100" height="100"></object> +<map name="sanityCheck"><area shape="rect" coords="0,0,100,100"></map> + +<object data="/images/threecolors.png" usemap="#sImPlE" width="100" height="100"></object> +<map name="simple"><area shape="rect" coords="0,0,100,100"></map> +<map name="SIMPLE"><area shape="rect" coords="0,0,100,100"></map> + +<object data="/images/threecolors.png" usemap="#paSSfield-killroyß" width="100" height="100"></object> +<map name="passfield-killroyß"><area shape="rect" coords="0,0,100,100"></map> +<map name="PASSFIELD-KILLROYß"><area shape="rect" coords="0,0,100,100"></map> +<map name="paſſfield-killroyß"><area shape="rect" coords="0,0,100,100"></map> +<map name="passfield-Killroyß"><area shape="rect" coords="0,0,100,100"></map> +<map name="paßfield-killroyß"><area shape="rect" coords="0,0,100,100"></map> +<map name="paẞfield-killroyß"><area shape="rect" coords="0,0,100,100"></map> +<map name="passfield-killroyẞ"><area shape="rect" coords="0,0,100,100"></map> +<map name="passfield-killroyß"><area shape="rect" coords="0,0,100,100"></map> +<map name="passfıeld-killroyß"><area shape="rect" coords="0,0,100,100"></map> +<map name="passfİeld-killroyß"><area shape="rect" coords="0,0,100,100"></map> + +<object data="/images/threecolors.png" usemap="#глупый" width="100" height="100"></object> +<map name="глупый"><area shape="rect" coords="0,0,100,100"></map> +<map name="ГЛУПЫЙ"><area shape="rect" coords="0,0,100,100"></map> +<map name="ГЛУПЫЙ"><area shape="rect" coords="0,0,100,100"></map> + +<object data="/images/threecolors.png" usemap="#åωk" width="100" height="100"></object> +<map name="ÅΩK"><area shape="rect" coords="0,0,100,100"></map> +<map name="Åωk"><area shape="rect" coords="0,0,100,100"></map> +<map name="åΩk"><area shape="rect" coords="0,0,100,100"></map> +<map name="åωK"><area shape="rect" coords="0,0,100,100"></map> + +<object data="/images/threecolors.png" usemap="#blah1" width="100" height="100"></object> +<map name="blah①"><area shape="rect" coords="0,0,100,100"></map> +<map name="blⒶh1"><area shape="rect" coords="0,0,100,100"></map> +<map name="blⓐh1"><area shape="rect" coords="0,0,100,100"></map> + +<object data="/images/threecolors.png" usemap="#tÉdz5アパートFi" width="100" height="100"></object> +<map name="TÉDZ5アパートFi"><area shape="rect" coords="0,0,100,100"></map> +<map name="TéDZ⁵アパートFi"><area shape="rect" coords="0,0,100,100"></map> +<map name="tÉdz5㌀Fi"><area shape="rect" coords="0,0,100,100"></map> +<map name="tÉdz5アパートFi"><area shape="rect" coords="0,0,100,100"></map> +<map name="TÉDZ⁵アパートFi"><area shape="rect" coords="0,0,100,100"></map> +<map name="TÉDZ5アパートfi"><area shape="rect" coords="0,0,100,100"></map> + +<object data="/images/threecolors.png" usemap="#ΣΣ" width="100" height="100"></object> +<map name="σς"><area shape="rect" coords="0,0,100,100"></map> -<object data="/images/threecolors.png" usemap="#sanityCheck" width="300" height="300"></object> -<map name="sanityCheck"><area shape="rect" coords="0,0,300,300"></map> - -<object data="/images/threecolors.png" usemap="#sImPlE" width="300" height="300"></object> -<map name="simple"><area shape="rect" coords="0,0,300,300"></map> -<map name="SIMPLE"><area shape="rect" coords="0,0,300,300"></map> - -<object data="/images/threecolors.png" usemap="#paSSfield-killroyß" width="300" height="300"></object> -<map name="passfield-killroyß"><area shape="rect" coords="0,0,300,300"></map> -<map name="PASSFIELD-KILLROYß"><area shape="rect" coords="0,0,300,300"></map> -<map name="paſſfield-killroyß"><area shape="rect" coords="0,0,300,300"></map> -<map name="passfield-Killroyß"><area shape="rect" coords="0,0,300,300"></map> -<map name="paßfield-killroyß"><area shape="rect" coords="0,0,300,300"></map> -<map name="paẞfield-killroyß"><area shape="rect" coords="0,0,300,300"></map> -<map name="passfield-killroyẞ"><area shape="rect" coords="0,0,300,300"></map> -<map name="passfield-killroyß"><area shape="rect" coords="0,0,300,300"></map> -<map name="passfıeld-killroyß"><area shape="rect" coords="0,0,300,300"></map> -<map name="passfİeld-killroyß"><area shape="rect" coords="0,0,300,300"></map> - -<object data="/images/threecolors.png" usemap="#глупый" width="300" height="300"></object> -<map name="глупый"><area shape="rect" coords="0,0,300,300"></map> -<map name="ГЛУПЫЙ"><area shape="rect" coords="0,0,300,300"></map> -<map name="ГЛУПЫЙ"><area shape="rect" coords="0,0,300,300"></map> - -<object data="/images/threecolors.png" usemap="#åωk" width="300" height="300"></object> -<map name="ÅΩK"><area shape="rect" coords="0,0,300,300"></map> -<map name="Åωk"><area shape="rect" coords="0,0,300,300"></map> -<map name="åΩk"><area shape="rect" coords="0,0,300,300"></map> -<map name="åωK"><area shape="rect" coords="0,0,300,300"></map> - -<object data="/images/threecolors.png" usemap="#blah1" width="300" height="300"></object> -<map name="blah①"><area shape="rect" coords="0,0,300,300"></map> -<map name="blⒶh1"><area shape="rect" coords="0,0,300,300"></map> -<map name="blⓐh1"><area shape="rect" coords="0,0,300,300"></map> - -<object data="/images/threecolors.png" usemap="#tÉdz5アパートFi" width="300" height="300"></object> -<map name="TÉDZ5アパートFi"><area shape="rect" coords="0,0,300,300"></map> -<map name="TéDZ⁵アパートFi"><area shape="rect" coords="0,0,300,300"></map> -<map name="tÉdz5㌀Fi"><area shape="rect" coords="0,0,300,300"></map> -<map name="tÉdz5アパートFi"><area shape="rect" coords="0,0,300,300"></map> -<map name="TÉDZ⁵アパートFi"><area shape="rect" coords="0,0,300,300"></map> -<map name="TÉDZ5アパートfi"><area shape="rect" coords="0,0,300,300"></map> - -<object data="/images/threecolors.png" usemap="#ΣΣ" width="300" height="300"></object> -<map name="σς"><area shape="rect" coords="0,0,300,300"></map> +<div id="log"></div> <script> "use strict"; diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/resources/stylable-select-styles.css b/testing/web-platform/tests/html/semantics/forms/the-select-element/resources/stylable-select-styles.css deleted file mode 100644 index a7e9a87cdf..0000000000 --- a/testing/web-platform/tests/html/semantics/forms/the-select-element/resources/stylable-select-styles.css +++ /dev/null @@ -1,18 +0,0 @@ -.stylable-select-datalist { - box-shadow: 0px 12.8px 28.8px rgba(0, 0, 0, 0.13), 0px 0px 9.2px rgba(0, 0, 0, 0.11); - box-sizing: border-box; - overflow: auto; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 0.25em; - padding: 0.25em 0; - background-color: Field; - margin: 0; - inset: auto; - min-inline-size: anchor-size(self-inline); - min-block-size: 1lh; - inset-block-start: anchor(self-end); - inset-inline-start: anchor(self-start); - - font-family: Arial; - font-size: 13.3333px; -} diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-ref.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-ref.html deleted file mode 100644 index 46bbd0ccd0..0000000000 --- a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-ref.html +++ /dev/null @@ -1,12 +0,0 @@ -<!DOCTYPE html> -<link rel=stylesheet href="resources/stylable-select-styles.css"> - -<button popovertarget=popover id=button>button</button> -<div id=popover popover=auto anchor=button class=stylable-select-datalist> - <option>one</option> - <option>two</option> -</div> - -<script> -document.getElementById('popover').showPopover(); -</script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/resources/select-reset-non-interoperable-styles.css b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/resources/select-reset-non-interoperable-styles.css new file mode 100644 index 0000000000..d2b9d9df26 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/resources/select-reset-non-interoperable-styles.css @@ -0,0 +1,5 @@ +/* TODO(crbug.com/1511354): linux.css sets background-color on select, consider + * removing it. */ +select { + background-color: Field; +} diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/resources/stylable-select-styles.css b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/resources/stylable-select-styles.css new file mode 100644 index 0000000000..042de838d1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/resources/stylable-select-styles.css @@ -0,0 +1,37 @@ +/* These are UA styles for select and stylable select. */ + +.stylable-select-container { + background-color: Field; + border: 1px solid rgba(0, 0, 0, 0); + border-radius: 0; + box-sizing: border-box; + display: inline-block; +} + +.stylable-select-datalist { + box-shadow: 0px 12.8px 28.8px rgba(0, 0, 0, 0.13), 0px 0px 9.2px rgba(0, 0, 0, 0.11); + box-sizing: border-box; + overflow: auto; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25em; + padding: 0.25em 0; + background-color: Field; + margin: 0; + inset: auto; + min-inline-size: anchor-size(self-inline); + min-block-size: 1lh; + inset-block-start: anchor(self-end); + inset-inline-start: anchor(self-start); + + font-family: Arial; + font-size: 13.3333px; +} + +/* These are the UA styles for <option> in chromium. + * They will either have to be specced or also added to the main test file. + * TODO(crbug.com/1511354): Spec these UA styles. */ +.stylable-select-option { + min-height: 1.2em; + padding: 0px 2px 1px; + white-space: nowrap; +} diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-custom-button-no-datalist.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-custom-button-no-datalist.tentative.html new file mode 100644 index 0000000000..94d7fd53b3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-custom-button-no-datalist.tentative.html @@ -0,0 +1,22 @@ +<!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-appearance-no-button-custom-datalist-ref.html"> +<link rel=stylesheet href="resources/select-reset-non-interoperable-styles.css"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<select style="appearance:base-select"> + <button type=popover>one</button> + <option>one</option> + <option>two</option> +</select> + +<script> +(async () => { + await test_driver.bless(); + document.querySelector('select').showPicker(); + document.documentElement.classList.remove('reftest-wait'); +})(); +</script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-no-button-custom-datalist-ref.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-no-button-custom-datalist-ref.html new file mode 100644 index 0000000000..8e5eadaf57 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-no-button-custom-datalist-ref.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<link rel=stylesheet href="resources/stylable-select-styles.css"> + +<div id=container class=stylable-select-container> + <button popovertarget=popover id=button>one</button> + <div id=popover popover=auto anchor=container class=stylable-select-datalist> + <div class=stylable-select-option>one</div> + <div class=stylable-select-option>two</div> + </div> +</div> + +<script> +document.getElementById('popover').showPopover(); +</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/stylable-select/select-appearance-no-button-custom-datalist.tentative.html index f71c1e52fc..87425cf7a3 100644 --- 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/stylable-select/select-appearance-no-button-custom-datalist.tentative.html @@ -2,12 +2,12 @@ <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"> +<link rel=match href="select-appearance-no-button-custom-datalist-ref.html"> +<link rel=stylesheet href="resources/select-reset-non-interoperable-styles.css"> <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> -<select> - <button type=popover>button</button> +<select style="appearance:base-select"> <datalist> <option>one</option> <option>two</option> @@ -15,9 +15,9 @@ </select> <script> -requestAnimationFrame(() => { - document.querySelector('select').style = 'appearance:bikeshed'; - document.querySelector('button').click(); +(async () => { + await test_driver.bless(); + document.querySelector('select').showPicker(); document.documentElement.classList.remove('reftest-wait'); -}); +})(); </script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-no-button-no-datalist.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-no-button-no-datalist.tentative.html new file mode 100644 index 0000000000..b2a6b5a6d3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-appearance-no-button-no-datalist.tentative.html @@ -0,0 +1,21 @@ +<!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-appearance-no-button-custom-datalist-ref.html"> +<link rel=stylesheet href="resources/select-reset-non-interoperable-styles.css"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<select style="appearance:base-select"> + <option>one</option> + <option>two</option> +</select> + +<script> +(async () => { + await test_driver.bless(); + document.querySelector('select').showPicker(); + document.documentElement.classList.remove('reftest-wait'); +})(); +</script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-child-button-and-datalist-invalidation.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-child-button-and-datalist-invalidation.tentative.html new file mode 100644 index 0000000000..b6d85ac90a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-child-button-and-datalist-invalidation.tentative.html @@ -0,0 +1,32 @@ +<!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"> +<link rel=stylesheet href="resources/select-reset-non-interoperable-styles.css"> + +<style> +.blue { + color: blue; +} +</style> + +<select> + <button type=popover>button</button> + <datalist> + <option> + <span class=blue>option</span> one + </option> + <option> + <span class=blue>option</span> two + </option> + </datalist> +</select> + +<script> +requestAnimationFrame(() => { + document.querySelector('select').style = 'appearance:base-select'; + document.querySelector('button').click(); + document.documentElement.classList.remove('reftest-wait'); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-child-button-and-datalist-ref.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-child-button-and-datalist-ref.html new file mode 100644 index 0000000000..e99ca4d57a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-child-button-and-datalist-ref.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<link rel=stylesheet href="resources/stylable-select-styles.css"> + +<style> +.blue { + color: blue; +} +</style> + +<div id=container class=stylable-select-container> + <button popovertarget=popover id=button>button</button> + <div id=popover popover=auto anchor=container class=stylable-select-datalist> + <div tabindex=0 class=stylable-select-option> + <span class=blue>option</span> one + </div> + <div tabindex=0 class=stylable-select-option> + <span class=blue>option</span> two + </div> + </div> +</div> + +<script> +document.getElementById('popover').showPopover(); +document.querySelector('div.stylable-select-option').focus(); +</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/stylable-select/select-child-button-and-datalist.tentative.html index 54785ace95..610861aad8 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/stylable-select/select-child-button-and-datalist.tentative.html @@ -2,14 +2,23 @@ <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> +<link rel=stylesheet href="resources/select-reset-non-interoperable-styles.css"> -<select style="appearance:bikeshed"> +<style> +.blue { + color: blue; +} +</style> + +<select style="appearance:base-select"> <button type=popover>button</button> <datalist> - <option>one</option> - <option>two</option> + <option> + <span class=blue>option</span> one + </option> + <option> + <span class=blue>option</span> two + </option> </datalist> </select> 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/stylable-select/select-datalist-options-idl.tentative.html index 993f6e126c..92eabdc5d8 100644 --- 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/stylable-select/select-datalist-options-idl.tentative.html @@ -12,6 +12,9 @@ </div> <option class=three>three</option> </datalist> + <datalist> + <option>ignored since not in first datalist</option> + </datalist> </select> <script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html new file mode 100644 index 0000000000..2fb11ba68b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html @@ -0,0 +1,208 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1422275"> +<link rel=help href="https://github.com/openui/open-ui/issues/433#issuecomment-1452461404"> +<link rel=help href="https://github.com/openui/open-ui/issues/386#issuecomment-1452469497"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/resources/testdriver-actions.js"></script> + +<style> +select { + appearance: base-select; +} +</style> + +<form></form> + +<div id=notform> + <select id=defaultbutton-defaultdatalist> + <option class=one>one</option> + <option class=two>two</option> + <option class=three>three</option> + </select> + + <select id=defaultbutton-customdatalist> + <datalist> + <option class=one>one</option> + <option class=two>two</option> + <option class=three>three</option> + </datalist> + </select> + + <select id=custombutton-defaultdatalist> + <button type=popover>custom button</button> + <option class=one>one</option> + <option class=two>two</option> + <option class=three>three</option> + </select> + + <select id=custombutton-customdatalist> + <button type=popover>custom button</button> + <datalist> + <option class=one>one</option> + <option class=two>two</option> + <option class=three>three</option> + </datalist> + </select> +</div> + +<script> +const Enter = '\uE007'; +const Escape = '\uE00C'; +const ArrowLeft = '\uE012'; +const ArrowUp = '\uE013'; +const ArrowRight = '\uE014'; +const ArrowDown = '\uE015'; +const Space = ' '; +const form = document.querySelector('form'); +const notform = document.getElementById('notform'); + +for (const id of ['defaultbutton-defaultdatalist', + 'defaultbutton-customdatalist', + 'custombutton-defaultdatalist', + 'custombutton-customdatalist']) { + const select = document.getElementById(id); + + async function closeListbox() { + await test_driver.click(select); + } + + function addCloseCleanup(t) { + t.add_cleanup(async () => { + if (select.matches(':open')) { + await closeListbox(); + } + if (select.matches(':open')) { + throw new Error('select failed to close!'); + } + select.value = 'one'; + }); + } + + promise_test(async t => { + addCloseCleanup(t); + // TODO(http://crbug.com/1350299): When focus for custom buttons is fixed, + // then we shouldn't need to explicitly focus the custom button like this + // anymore. + const customButton = select.querySelector('button'); + if (customButton) { + customButton.focus(); + } else { + select.focus(); + } + assert_false(select.matches(':open'), + 'The select should initially be closed.'); + await test_driver.send_keys(document.activeElement, Space); + assert_true(select.matches(':open'), + 'The select should be open after pressing space.'); + }, `${id}: When the listbox is closed, spacebar should open the listbox.`); + + promise_test(async t => { + addCloseCleanup(t); + select.value = 'two'; + select.focus(); + assert_false(select.matches(':open'), + 'The select should initially be closed.'); + + await test_driver.send_keys(document.activeElement, ArrowLeft); + assert_true(select.matches(':open'), + 'Arrow left should open the listbox.'); + assert_equals(select.value, 'two', + 'Arrow left should not change the selected value.'); + await closeListbox(); + + await test_driver.send_keys(document.activeElement, ArrowUp); + assert_true(select.matches(':open'), + 'Arrow up should open the listbox.'); + assert_equals(select.value, 'two', + 'Arrow up should not change the selected value.'); + await closeListbox(); + + await test_driver.send_keys(document.activeElement, ArrowRight); + assert_true(select.matches(':open'), + 'Arrow right should open the listbox.'); + assert_equals(select.value, 'two', + 'Arrow right should not change the selected value.'); + await closeListbox(); + + await test_driver.send_keys(document.activeElement, ArrowDown); + assert_true(select.matches(':open'), + 'Arrow down should open the listbox.'); + assert_equals(select.value, 'two', + 'Arrow down should not change the selected value.'); + }, `${id}: When the listbox is closed, all arrow keys should open the listbox.`); + + promise_test(async t => { + addCloseCleanup(t); + + // TODO(http://crbug.com/1350299): When focus for custom buttons is fixed, + // then we shouldn't need to explicitly use the custom button like this + // anymore. + const customButton = select.querySelector('button'); + if (customButton) { + await test_driver.send_keys(customButton, Enter); + } else { + await test_driver.send_keys(select, Enter); + } + assert_false(select.matches(':open'), + 'Enter should not open the listbox when outside a form.'); + + form.appendChild(select); + let formWasSubmitted = false; + form.addEventListener('submit', event => { + event.preventDefault(); + formWasSubmitted = true; + }, {once: true}); + if (customButton) { + await test_driver.send_keys(customButton, Enter); + } else { + await test_driver.send_keys(select, Enter); + } + assert_true(formWasSubmitted, + 'Enter should submit the form when the listbox is closed.'); + assert_false(select.matches(':open'), + 'Enter should not open the listbox when it is in a form.'); + }, `${id}: When the listbox is closed, the enter key should submit the form or do nothing.`); + + promise_test(async t => { + addCloseCleanup(t); + const optionOne = select.querySelector('.one'); + const optionTwo = select.querySelector('.two'); + const optionThree = select.querySelector('.three'); + + select.value = 'two'; + await test_driver.click(select); + assert_true(select.matches(':open'), + 'The select should open when clicked.'); + assert_equals(document.activeElement, optionTwo, + 'The selected option should receive initial focus.'); + + await test_driver.send_keys(document.activeElement, ArrowDown); + assert_equals(document.activeElement, optionThree, + 'The next option should receive focus when the down arrow key is pressed.'); + assert_equals(select.value, 'two', + 'The selects value should not change when focusing another option.'); + + await test_driver.send_keys(document.activeElement, ArrowUp); + assert_equals(document.activeElement, optionTwo, + 'The previous option should receive focus when the up arrow key is pressed.'); + assert_equals(select.value, 'two', + 'The selects value should not change when focusing another option.'); + + await test_driver.send_keys(document.activeElement, ArrowUp); + assert_equals(document.activeElement, optionOne, + 'The first option should be selected.'); + assert_equals(select.value, 'two', + 'The selects value should not change when focusing another option.'); + + await test_driver.send_keys(document.activeElement, Enter); + assert_false(select.matches(':open'), + 'The listbox should be closed after pressing enter.'); + assert_equals(select.value, 'one', + 'The selects value should change after pressing enter on a different option.'); + }, `${id}: When the listbox is open, the enter key should commit the selected option.`); +} +</script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-mouse-behavior.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-mouse-behavior.tentative.html new file mode 100644 index 0000000000..aff976d1ad --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-mouse-behavior.tentative.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1422275"> +<link rel=help href="https://github.com/openui/open-ui/issues/433#issuecomment-1452461404"> +<link rel=help href="https://github.com/openui/open-ui/issues/386#issuecomment-1452469497"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/resources/testdriver-actions.js"></script> + +<style> +select { + appearance: base-select; +} +</style> + +<!-- TODO(http://crbug.com/1511354): Add test cases with no <button> and no <datalist>. --> +<select> + <button type=popover>button</button> + <datalist> + <option class=one>one</option> + <option class=two>two</option> + </datalist> +</select> + +<script> +const select = document.querySelector('select'); +const button = document.querySelector('button'); +const optionOne = document.querySelector('option.one'); +const optionTwo = document.querySelector('option.two'); + +promise_test(async () => { + assert_false(select.matches(':open'), + 'Select should be closed at the start of the test.'); + + await test_driver.click(button); + assert_true(select.matches(':open'), + 'Select should be open after clicking the button.'); + + await test_driver.click(button); + assert_false(select.matches(':open'), + 'Select should be closed after clicking the button a second time.'); +}, 'Select with appearance:base-select should open and close when clicking the button.'); + +promise_test(async () => { + assert_false(select.matches(':open'), + 'Select should be closed at the start of the test.'); + assert_equals(select.value, 'one', + 'Select.value should be one at the start of the test.'); + + await test_driver.click(button); + assert_true(select.matches(':open'), + 'Select should be open after clicking the button.'); + + await test_driver.click(optionTwo); + assert_false(select.matches(':open'), + 'Select should be closed after clicking an option.'); + assert_equals(select.value, 'two', + 'Select.value should be two after clicking the option.'); +}, 'Clicking an option in an appearance:base-select select should choose the option and close the popover.'); +</script> diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-parsing.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-parsing.tentative.html index 31133446d4..31133446d4 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-parsing.tentative.html +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/select-parsing.tentative.html diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/selectedoption.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/selectedoption.tentative.html new file mode 100644 index 0000000000..16d711515c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/stylable-select/selectedoption.tentative.html @@ -0,0 +1,82 @@ +<!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> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<form> + <select style="appearance:base-select"> + <button> + <selectedoption></selectedoption> + </button> + <datalist> + <option class=one value=one> + <span class=one>span</span> one + </option> + <option class=two value=two> + <span class=two>span</span> two + </option> + </datalist> + </select> +</form> + +<script> +promise_test(async () => { + const optionOne = document.querySelector('option.one'); + const optionTwo = document.querySelector('option.two'); + const selectedOption = document.querySelector('selectedoption'); + const select = document.querySelector('select'); + const spanTwo = document.querySelector('span.two'); + const form = document.querySelector('form'); + const button = document.querySelector('button'); + + assert_equals(selectedOption.innerHTML, optionOne.innerHTML, + 'The innerHTML of <selectedoption> should initially match the innerHTML of the selected <option>.'); + + select.value = 'two'; + assert_equals(selectedOption.innerHTML, optionTwo.innerHTML, + 'The innerHTML of <selectedoption> should change after the selected option is changed.'); + + spanTwo.textContent = 'new span'; + assert_equals(selectedOption.innerHTML, optionTwo.innerHTML, + '<selectedoption> should respond to text content changes.'); + + spanTwo.appendChild(document.createElement('div')); + assert_equals(selectedOption.innerHTML, optionTwo.innerHTML, + '<selectedoption> should respond to new elements being added to descendants.'); + + spanTwo.setAttribute('data-foo', 'bar'); + assert_equals(selectedOption.innerHTML, optionTwo.innerHTML, + '<selectedoption> should respond to attributes being added to descendants.'); + + form.reset(); + assert_equals(select.value, 'one', + 'form.reset() should change the selects value to one.'); + assert_equals(selectedOption.innerHTML, optionOne.innerHTML, + 'The innerHTML of <selectedoption> should be updated in response to a form reset.'); + + await test_driver.bless(); + select.showPicker(); + await test_driver.click(optionTwo); + assert_equals(select.value, 'two', + 'Clicking on another option should change select.value.'); + assert_equals(selectedOption.innerHTML, optionTwo.innerHTML, + 'Clicking on an option element should update the <selectedoption>.'); + + selectedOption.remove(); + assert_equals(selectedOption.innerHTML, '', + 'Removing the <selectedoption> from the <select> should make it clear its contents.'); + button.appendChild(selectedOption); + assert_equals(selectedOption.innerHTML, optionTwo.innerHTML, + 'Re-inserting the <selectedoption> should make it update its contents.'); + + optionTwo.remove(); + assert_equals(selectedOption.innerHTML, optionOne.innerHTML, + 'The innerHTML of <selectedoption> should be updated in response to selected <option> removal.'); + optionOne.remove(); + assert_equals(selectedOption.innerHTML, '', + 'The content of <selectedoption> should be cleared if there is no selected <option>.'); +}, 'The <selectedoption> element should reflect the HTML contents of the selected <option>.'); +</script> diff --git a/testing/web-platform/tests/html/semantics/invokers/idlharness.tentative.html b/testing/web-platform/tests/html/semantics/invokers/idlharness.tentative.html index b215f65813..8a86a5aaa1 100644 --- a/testing/web-platform/tests/html/semantics/invokers/idlharness.tentative.html +++ b/testing/web-platform/tests/html/semantics/invokers/idlharness.tentative.html @@ -1,6 +1,6 @@ <!doctype html> <meta charset="utf-8" /> -<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></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 index dc119de833..8b1e375695 100644 --- a/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html +++ b/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html @@ -1,5 +1,6 @@ <!doctype html> <meta charset="utf-8" /> +<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> <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> diff --git a/testing/web-platform/tests/html/semantics/invokers/interestevent-dispatch-shadow.tentative.html b/testing/web-platform/tests/html/semantics/invokers/interestevent-dispatch-shadow.tentative.html new file mode 100644 index 0000000000..d96907ec84 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/interestevent-dispatch-shadow.tentative.html @@ -0,0 +1,104 @@ +<!doctype html> +<meta charset="utf-8" /> +<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<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> +<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> + +<div id="div"></div> +<button id="button"></button> + +<script> + test(function () { + const host = document.createElement("div"); + const shadow = host.attachShadow({ mode: "closed" }); + const slot = shadow.appendChild(document.createElement("slot")); + let childEvent = null; + let childEventTarget = null; + let childEventInvoker = null; + let hostEvent = null; + let hostEventTarget = null; + let hostEventInvoker = null; + slot.addEventListener( + "interest", + (e) => { + childEvent = e; + childEventTarget = e.target; + childEventInvoker = e.invoker; + }, + { once: true }, + ); + host.addEventListener( + "interest", + (e) => { + hostEvent = e; + hostEventTarget = e.target; + hostEventInvoker = e.invoker; + }, + { once: true }, + ); + const event = new InterestEvent("interest", { + bubbles: true, + invoker: slot, + composed: true, + }); + slot.dispatchEvent(event); + assert_true(childEvent instanceof InterestEvent, "slot saw interest event"); + assert_equals( + childEventTarget, + slot, + "target is child inside shadow boundary", + ); + assert_equals( + childEventInvoker, + slot, + "invoker is child inside shadow boundary", + ); + assert_equals( + hostEvent, + childEvent, + "event dispatch propagates across shadow boundary", + ); + assert_equals( + hostEventTarget, + host, + "target is retargeted to shadowroot host", + ); + assert_equals( + hostEventInvoker, + host, + "invoker is retargeted to shadowroot host", + ); + }, "InterestEvent propagates across shadow boundaries retargeting invoker"); + + test(function (t) { + const host = document.createElement("div"); + document.body.append(host); + t.add_cleanup(() => host.remove()); + const shadow = host.attachShadow({ mode: "open" }); + const button = shadow.appendChild(document.createElement("button")); + const interestee = host.appendChild(document.createElement("div")); + button.interestTargetElement = interestee; + let event = null; + let eventTarget = null; + let eventInvoker = null; + interestee.addEventListener( + "interest", + (e) => { + event = e; + eventTarget = e.target; + eventInvoker = e.invoker; + }, + { once: true }, + ); + button.focus(); + assert_true(event instanceof InterestEvent); + assert_equals(eventTarget, interestee, "target is interestee"); + assert_equals(eventInvoker, host, "interestee is host"); + }, "cross shadow InterestEvent retargets interestee to host element"); +</script> diff --git a/testing/web-platform/tests/html/semantics/invokers/interestevent-interface.tentative.html b/testing/web-platform/tests/html/semantics/invokers/interestevent-interface.tentative.html new file mode 100644 index 0000000000..ed7d82f1fb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/interestevent-interface.tentative.html @@ -0,0 +1,167 @@ +<!doctype html> +<meta charset="utf-8" /> +<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<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> +<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> + +<div id="div"></div> +<button id="button"></button> + +<script> + test(function () { + const event = new InterestEvent("test"); + assert_equals(event.action, ""); + assert_readonly(event, "action", "readonly attribute value"); + }, "action is a readonly defaulting to ''"); + + test(function () { + const event = new InterestEvent("test"); + assert_equals(event.invoker, null); + assert_readonly(event, "invoker", "readonly attribute value"); + }, "invoker is readonly defaulting to null"); + + test(function () { + const event = new InterestEvent("test", { action: "sAmPle" }); + assert_equals(event.action, "sAmPle"); + }, "action reflects initialized attribute"); + + test(function () { + const event = new InterestEvent("test", { action: undefined }); + assert_equals(event.action, ""); + }, "action set to undefined"); + + test(function () { + const event = new InterestEvent("test", { action: null }); + assert_equals(event.action, "null"); + }, "action set to null"); + + test(function () { + const event = new InterestEvent("test", { action: false }); + assert_equals(event.action, "false"); + }, "action set to false"); + + test(function () { + const event = new InterestEvent("test", { action: "" }); + assert_equals(event.action, ""); + }, "action explicitly set to empty string"); + + test(function () { + const event = new InterestEvent("test", { action: true }); + assert_equals(event.action, "true"); + }, "action set to true"); + + test(function () { + const event = new InterestEvent("test", { action: 0.5 }); + assert_equals(event.action, "0.5"); + }, "action set to a number"); + + test(function () { + const event = new InterestEvent("test", { action: [] }); + assert_equals(event.action, ""); + }, "action set to []"); + + test(function () { + const event = new InterestEvent("test", { action: [1, 2, 3] }); + assert_equals(event.action, "1,2,3"); + }, "action set to [1, 2, 3]"); + + test(function () { + const event = new InterestEvent("test", { action: { sample: 0.5 } }); + assert_equals(event.action, "[object Object]"); + }, "action set to an object"); + + test(function () { + const event = new InterestEvent("test", { + action: { + toString() { + return "sample"; + }, + }, + }); + assert_equals(event.action, "sample"); + }, "action set to an object with a toString function"); + + test(function () { + const eventInit = { action: "sample", invoker: document.body }; + const event = new InterestEvent("test", eventInit); + assert_equals(event.action, "sample"); + assert_equals(event.invoker, document.body); + }, "InterestEventInit properties set value"); + + test(function () { + const eventInit = { + action: "open", + invoker: document.getElementById("div"), + }; + const event = new InterestEvent("beforetoggle", eventInit); + assert_equals(event.action, "open"); + assert_equals(event.invoker, document.getElementById("div")); + }, "InterestEventInit properties set value 2"); + + test(function () { + const eventInit = { + action: "closed", + invoker: document.getElementById("button"), + }; + const event = new InterestEvent("toggle", eventInit); + assert_equals(event.action, "closed"); + assert_equals(event.invoker, document.getElementById("button")); + }, "InterestEventInit properties set value 3"); + + test(function () { + const event = new InterestEvent("test", { invoker: undefined }); + assert_equals(event.invoker, null); + }, "invoker set to undefined"); + + test(function () { + const event = new InterestEvent("test", { invoker: null }); + assert_equals(event.invoker, null); + }, "invoker set to null"); + + test(function () { + assert_throws_js( + TypeError, + function () { + new InterestEvent("test", { invoker: false }); + }, + "invoker is not an object", + ); + }, "invoker set to false"); + + test(function () { + assert_throws_js( + TypeError, + function () { + const event = new InterestEvent("test", { invoker: true }); + }, + "invoker is not an object", + ); + }, "invoker set to true"); + + test(function () { + assert_throws_js( + TypeError, + function () { + const event = new InterestEvent("test", { invoker: {} }); + }, + "invoker is not an object", + ); + }, "invoker set to {}"); + + test(function () { + assert_throws_js( + TypeError, + function () { + const eventInit = { action: "closed", invoker: new XMLHttpRequest() }; + const event = new InterestEvent("toggle", eventInit); + }, + "invoker is not an Element", + ); + }, "invoker set to non-Element EventTarget"); +</script> diff --git a/testing/web-platform/tests/html/semantics/invokers/interesttarget-button-event-dispatch.tentative.html b/testing/web-platform/tests/html/semantics/invokers/interesttarget-button-event-dispatch.tentative.html new file mode 100644 index 0000000000..7fdfdfaa70 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/interesttarget-button-event-dispatch.tentative.html @@ -0,0 +1,155 @@ +<!doctype html> +<meta charset="utf-8" /> +<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<meta name="author" title="Luke Warlow" href="mailto:lwarlow@igalia.com" /> +<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> + +<div id="interestee"></div> +<button id="interestbutton" interesttarget="interestee">Button</button> +<a href="/" id="interestanchor" interesttarget="interestee">Anchor</a> +<button id="otherbutton">Other Button</button> + +<script> + promise_test(async function (t) { + t.add_cleanup(() => otherbutton.focus()); + let event = null; + interestee.addEventListener("interest", (e) => (event = e), { once: true }); + interestbutton.focus(); + assert_true(event instanceof InterestEvent, "event is InterestEvent"); + assert_equals(event.type, "interest", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, "", "action"); + assert_equals(event.target, interestee, "target"); + assert_equals(event.invoker, interestbutton, "invoker"); + }, "InterestEvent dispatches on button focus"); + + promise_test(async function (t) { + t.add_cleanup(() => otherbutton.focus()); + let event = null; + interestee.addEventListener("interest", (e) => (event = e), { once: true }); + await hoverOver(interestbutton); + assert_true(event instanceof InterestEvent, "event is InterestEvent"); + assert_equals(event.type, "interest", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, "", "action"); + assert_equals(event.target, interestee, "target"); + assert_equals(event.invoker, interestbutton, "invoker"); + }, "InterestEvent dispatches on button hover"); + + promise_test(async function (t) { + t.add_cleanup(() => otherbutton.focus()); + let event = null; + interestee.addEventListener("interest", (e) => (event = e), { once: true }); + interestanchor.focus(); + assert_true(event instanceof InterestEvent, "event is InterestEvent"); + assert_equals(event.type, "interest", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, "", "action"); + assert_equals(event.target, interestee, "target"); + assert_equals(event.invoker, interestanchor, "invoker"); + }, "InterestEvent dispatches on anchor focus"); + + promise_test(async function (t) { + t.add_cleanup(() => otherbutton.focus()); + let event = null; + interestee.addEventListener("interest", (e) => (event = e), { once: true }); + await hoverOver(interestanchor); + assert_true(event instanceof InterestEvent, "event is InterestEvent"); + assert_equals(event.type, "interest", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, "", "action"); + assert_equals(event.target, interestee, "target"); + assert_equals(event.invoker, interestanchor, "invoker"); + }, "InterestEvent dispatches on anchor hover"); + + promise_test(async function (t) { + t.add_cleanup(() => otherbutton.focus()); + let event = null; + interestee.addEventListener("interest", (e) => (event = e), { once: true }); + interestbutton.interestAction = "fooBar"; + interestbutton.focus(); + assert_true(event instanceof InterestEvent, "event is InterestEvent"); + assert_equals(event.type, "interest", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, "fooBar", "action"); + assert_equals(event.target, interestee, "target"); + assert_equals(event.invoker, interestbutton, "invoker"); + }, "event action is set to interestAction"); + + promise_test(async function (t) { + t.add_cleanup(() => otherbutton.focus()); + let event = null; + interestee.addEventListener("interest", (e) => (event = e), { once: true }); + interestbutton.setAttribute("interestaction", "BaRbAz"); + interestbutton.focus(); + assert_true(event instanceof InterestEvent, "event is InterestEvent"); + assert_equals(event.type, "interest", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, "BaRbAz", "action"); + assert_equals(event.target, interestee, "target"); + assert_equals(event.invoker, interestbutton, "invoker"); + }, "event action is set to interestaction attribute"); + + promise_test(async function (t) { + t.add_cleanup(() => { + interestbutton.removeAttribute('disabled'); + otherbutton.focus(); + }); + let called = false; + interestee.addEventListener( + "interest", + () => { + called = true; + }, + { once: true }, + ); + interestbutton.setAttribute("disabled", ""); + interestbutton.focus(); + assert_false(called, "event was not called"); + }, "event does not dispatch if invoker is disabled"); + + promise_test(async function (t) { + svgInterestee = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + t.add_cleanup(() => { + interestbutton.interestTargetElement = interestee; + svgInterestee.remove(); + otherbutton.focus(); + }); + document.body.append(svgInterestee); + let called = false; + assert_false(svgInterestee instanceof HTMLElement); + assert_true(svgInterestee instanceof Element); + let event = null; + svgInterestee.addEventListener( + "interest", + (e) => { + event = e; + called = true; + }, + { once: true }, + ); + interestbutton.interestTargetElement = svgInterestee; + interestbutton.focus(); + assert_true(called, "event was called"); + assert_equals(event.invoker, interestbutton, "event.invoker is set to right element"); + assert_equals(event.target, svgInterestee, "event.target is set to right element"); + }, "event dispatches if interestee is non-HTML Element"); +</script> diff --git a/testing/web-platform/tests/html/semantics/invokers/interesttarget-on-popover-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/interesttarget-on-popover-behavior.tentative.html new file mode 100644 index 0000000000..b930fc645d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/interesttarget-on-popover-behavior.tentative.html @@ -0,0 +1,113 @@ +<!doctype html> +<meta charset="utf-8" /> +<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<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> +<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> + +<div id="interestee" popover> + Popover Content +</div> +<button id="interestbutton" interesttarget="interestee">Interest Invoker</button> +<button id="otherbutton">Other button</button> + +<script> + function reset() { + hoverOver(otherbutton); + otherbutton.focus(); + interestee.hidePopover(); + interestbutton.removeAttribute("interestaction"); + } + + // auto + + promise_test(async function (t) { + t.add_cleanup(reset); + assert_false(interestee.matches(":popover-open")); + await hoverOver(interestbutton); + assert_true(interestee.matches(":popover-open")); + }, "hover interest invoking (as auto) closed popover opens"); + + promise_test(async function (t) { + t.add_cleanup(reset); + interestee.showPopover(); + assert_true(interestee.matches(":popover-open")); + await hoverOver(interestbutton); + assert_false(interestee.matches(":popover-open")); + }, "hover interest invoking (as auto) open popover closes"); + + promise_test(async function (t) { + t.add_cleanup(reset); + assert_false(interestee.matches(":popover-open")); + interestbutton.focus(); + assert_true(interestee.matches(":popover-open")); + }, "focus interest invoking (as auto) closed popover opens"); + + promise_test(async function (t) { + t.add_cleanup(reset); + interestee.showPopover(); + assert_true(interestee.matches(":popover-open")); + interestbutton.focus(); + assert_false(interestee.matches(":popover-open")); + }, "focus interest invoking (as auto) open popover closes"); + + promise_test(async function (t) { + t.add_cleanup(reset); + assert_false(interestee.matches(":popover-open")); + interestee.addEventListener("interest", (e) => e.preventDefault(), { + once: true, + }); + await hoverOver(interestbutton); + assert_false(interestee.matches(":popover-open")); + }, "interest invoking (as auto) closed popover with preventDefault does not open"); + + // togglepopover + + promise_test(async function (t) { + t.add_cleanup(reset); + assert_false(interestee.matches(":popover-open")); + interestbutton.setAttribute("interestaction", "togglepopover"); + await hoverOver(interestbutton); + assert_true(interestee.matches(":popover-open")); + }, "hover interest invoking (as togglepopover) closed popover opens"); + + promise_test(async function (t) { + t.add_cleanup(reset); + interestee.showPopover(); + assert_true(interestee.matches(":popover-open")); + interestbutton.setAttribute("interestaction", "togglepopover"); + await hoverOver(interestbutton); + assert_false(interestee.matches(":popover-open")); + }, "hover interest invoking (as togglepopover) open popover closes"); + + promise_test(async function (t) { + t.add_cleanup(reset); + assert_false(interestee.matches(":popover-open")); + interestbutton.setAttribute("interestaction", "togglepopover"); + interestbutton.focus(); + assert_true(interestee.matches(":popover-open")); + }, "focus interest invoking (as togglepopover) closed popover opens"); + + promise_test(async function (t) { + t.add_cleanup(reset); + interestee.showPopover(); + assert_true(interestee.matches(":popover-open")); + interestbutton.setAttribute("interestaction", "togglepopover"); + interestbutton.focus(); + assert_false(interestee.matches(":popover-open")); + }, "focus interest invoking (as togglepopover) open popover closes"); + + promise_test(async function (t) { + t.add_cleanup(reset); + assert_false(interestee.matches(":popover-open")); + interestbutton.setAttribute("interestaction", "tOgGlEpOpOvEr"); + interestbutton.focus(); + assert_true(interestee.matches(":popover-open")); + }, "interest invoking (as togglepopover - case insensitive) closed popover opens"); + +</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 5a2854fe31..5adacadabb 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 @@ -1,6 +1,6 @@ <!doctype html> <meta charset="utf-8" /> -<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> diff --git a/testing/web-platform/tests/html/semantics/invokers/invokeevent-dispatch-shadow.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invokeevent-dispatch-shadow.tentative.html index 84337d5723..1ecff88760 100644 --- a/testing/web-platform/tests/html/semantics/invokers/invokeevent-dispatch-shadow.tentative.html +++ b/testing/web-platform/tests/html/semantics/invokers/invokeevent-dispatch-shadow.tentative.html @@ -1,6 +1,6 @@ <!doctype html> <meta charset="utf-8" /> -<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> 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 382f808071..0cfb4d5ee5 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 @@ -1,6 +1,6 @@ <!doctype html> <meta charset="utf-8" /> -<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> 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 d8d9c04022..9120cc3192 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 @@ -1,6 +1,7 @@ <!doctype html> <meta charset="utf-8" /> -<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<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> @@ -27,35 +28,63 @@ assert_equals(event.invoker, invokerbutton, "invoker"); }, "event dispatches on click"); - promise_test(async function (t) { - let event = null; - invokee.addEventListener("invoke", (e) => (event = e), { once: true }); - invokerbutton.invokeAction = "fooBar"; - await clickOn(invokerbutton); - assert_true(event instanceof InvokeEvent, "event is InvokeEvent"); - assert_equals(event.type, "invoke", "type"); - assert_equals(event.bubbles, false, "bubbles"); - assert_equals(event.composed, true, "composed"); - assert_equals(event.isTrusted, true, "isTrusted"); - assert_equals(event.action, "fooBar", "action"); - assert_equals(event.target, invokee, "target"); - assert_equals(event.invoker, invokerbutton, "invoker"); - }, "event action is set to invokeAction"); + // valid custom invokeactions + ["-foo", "foo-", "cAsE-cArRiEs", "-", "-a-", "a-b", "---", "show-picker"].forEach( + (action) => { + promise_test(async function (t) { + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + let event = null; + invokee.addEventListener("invoke", (e) => (event = e), { once: true }); + invokerbutton.invokeAction = action; + await clickOn(invokerbutton); + assert_true(event instanceof InvokeEvent, "event is InvokeEvent"); + assert_equals(event.type, "invoke", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, action, "action"); + assert_equals(event.target, invokee, "target"); + assert_equals(event.invoker, invokerbutton, "invoker"); + }, `setting custom invokeAction property to ${action} (must include dash) sets event action`); - promise_test(async function (t) { - let event = null; - invokee.addEventListener("invoke", (e) => (event = e), { once: true }); - invokerbutton.setAttribute("invokeaction", "BaRbAz"); - await clickOn(invokerbutton); - assert_true(event instanceof InvokeEvent, "event is InvokeEvent"); - assert_equals(event.type, "invoke", "type"); - assert_equals(event.bubbles, false, "bubbles"); - assert_equals(event.composed, true, "composed"); - assert_equals(event.isTrusted, true, "isTrusted"); - assert_equals(event.action, "BaRbAz", "action"); - assert_equals(event.target, invokee, "target"); - assert_equals(event.invoker, invokerbutton, "invoker"); - }, "event action is set to invokeaction attribute"); + promise_test(async function (t) { + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + let event = null; + invokee.addEventListener("invoke", (e) => (event = e), { once: true }); + invokerbutton.setAttribute("invokeaction", action); + await clickOn(invokerbutton); + assert_true(event instanceof InvokeEvent, "event is InvokeEvent"); + assert_equals(event.type, "invoke", "type"); + assert_equals(event.bubbles, false, "bubbles"); + assert_equals(event.composed, true, "composed"); + assert_equals(event.isTrusted, true, "isTrusted"); + assert_equals(event.action, action, "action"); + assert_equals(event.target, invokee, "target"); + assert_equals(event.invoker, invokerbutton, "invoker"); + }, `setting custom invokeaction attribute to ${action} (must include dash) sets event action`); + }, + ); + + // invalid custom invokeactions + ["foo", "foobar", "foo bar", "em—dash", "hidedocument"].forEach((action) => { + promise_test(async function (t) { + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + let event = null; + invokee.addEventListener("invoke", (e) => (event = e), { once: true }); + invokerbutton.invokeAction = action; + await clickOn(invokerbutton); + assert_equals(event, null, "event should not have fired"); + }, `setting custom invokeAction property to ${action} (no dash) did not dispatch an event`); + + promise_test(async function (t) { + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + let event = null; + invokee.addEventListener("invoke", (e) => (event = e), { once: true }); + invokerbutton.setAttribute("invokeaction", action); + await clickOn(invokerbutton); + assert_equals(event, null, "event should not have fired"); + }, `setting custom invokeaction attribute to ${action} (no dash) did not dispatch an event`); + }); promise_test(async function (t) { let called = false; @@ -78,7 +107,7 @@ }, "event does not dispatch if click:preventDefault is called"); promise_test(async function (t) { - t.add_cleanup(() => invokerbutton.removeAttribute('disabled')); + t.add_cleanup(() => invokerbutton.removeAttribute("disabled")); let called = false; invokee.addEventListener( "invoke", @@ -93,7 +122,7 @@ }, "event does not dispatch if invoker is disabled"); promise_test(async function (t) { - svgInvokee = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svgInvokee = document.createElementNS("http://www.w3.org/2000/svg", "svg"); t.add_cleanup(() => { invokerbutton.invokeTargetElement = invokee; svgInvokee.remove(); @@ -115,7 +144,15 @@ invokerbutton.invokeTargetElement = svgInvokee; await clickOn(invokerbutton); assert_true(called, "event was called"); - assert_equals(eventInvoker, invokerbutton, "event.invoker is set to right element"); - assert_equals(eventTarget, svgInvokee, "event.target is set to right 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-fullscreen-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-fullscreen-behavior.tentative.html index b72020283e..2e2c5f683f 100644 --- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-fullscreen-behavior.tentative.html +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-fullscreen-behavior.tentative.html @@ -1,6 +1,7 @@ <!doctype html> <meta charset="utf-8" /> <meta name="author" title="Luke Warlow" href="mailto:luke@warlow.dev" /> +<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> diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-audio-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-audio-behavior.tentative.html index f3abeae165..37acb7a539 100644 --- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-audio-behavior.tentative.html +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-audio-behavior.tentative.html @@ -1,6 +1,7 @@ <!doctype html> <meta charset="utf-8" /> <meta name="author" title="Luke Warlow" href="mailto:luke@warlow.dev" /> +<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> @@ -25,7 +26,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", ""); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -43,7 +44,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "playpause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -59,7 +60,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "playpause"); invokerbutton.click(); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -78,7 +79,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "playpause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -91,12 +92,12 @@ invokee.currentTime = 0; invokee.muted = false; }); - await test_driver.bless('play audio'); + await test_driver.bless("play audio"); invokee.play(); assert_false(invokee.paused); invokerbutton.setAttribute("invokeaction", "playpause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -114,7 +115,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "play"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -130,7 +131,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "play"); invokerbutton.click(); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -149,7 +150,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "play"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -162,12 +163,12 @@ invokee.currentTime = 0; invokee.muted = false; }); - await test_driver.bless('play audio'); + await test_driver.bless("play audio"); invokee.play(); assert_false(invokee.paused); invokerbutton.setAttribute("invokeaction", "play"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -185,8 +186,8 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "pause"); await clickOn(invokerbutton); - await new Promise(resolve => { - requestAnimationFrame(resolve); + await new Promise((resolve) => { + requestAnimationFrame(resolve); }); assert_true(invokee.paused); }, "invoking audio with pause action is a no-op"); @@ -204,7 +205,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "pause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -217,12 +218,12 @@ invokee.currentTime = 0; invokee.muted = false; }); - await test_driver.bless('play audio'); + await test_driver.bless("play audio"); invokee.play(); assert_false(invokee.paused); invokerbutton.setAttribute("invokeaction", "pause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -240,7 +241,7 @@ assert_false(invokee.muted); invokerbutton.setAttribute("invokeaction", "toggleMuted"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.muted); @@ -259,7 +260,7 @@ assert_false(invokee.muted); invokerbutton.setAttribute("invokeaction", "toggleMuted"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.muted); @@ -276,10 +277,9 @@ assert_true(invokee.muted); invokerbutton.setAttribute("invokeaction", "toggleMuted"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.muted); }, "invoking muted audio with toggleMuted action unmutes it"); - </script> diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-audio-invalid-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-audio-invalid-behavior.tentative.html new file mode 100644 index 0000000000..9e15ce38e8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-audio-invalid-behavior.tentative.html @@ -0,0 +1,37 @@ +<!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> + +<audio controls id="invokee" src="/media/sound_5.mp3"></audio> +<button id="invokerbutton" invoketarget="invokee"></button> + +<script> + // invalid actions on audio + [ + "foo-bar", + "showpopover", + "showmodal", + "showpicker", + "open", + "close", + ].forEach((action) => { + promise_test(async function (t) { + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + invokerbutton.setAttribute("invokeaction", action); + assert_true(invokee.paused); + assert_false(invokee.muted); + await clickOn(invokerbutton); + await waitForRender(); + assert_true(invokee.paused); + assert_false(invokee.muted); + }, `invoking (as ${action}) on audio does nothing`); + }); +</script> diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-details-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-details-behavior.tentative.html index c6735e2611..ad9b6caa57 100644 --- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-details-behavior.tentative.html +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-details-behavior.tentative.html @@ -1,6 +1,7 @@ <!doctype html> <meta charset="utf-8" /> <meta name="author" title="Luke Warlow" href="mailto:luke@warlow.dev" /> +<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> @@ -9,210 +10,136 @@ <script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> -<details id="invokee"> - Details Contents -</details> +<details id="invokee">Details Contents</details> <button id="invokerbutton" invoketarget="invokee"></button> <script> - // auto - - promise_test(async function (t) { - assert_false(invokee.matches("[open]")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_true(invokee.matches("[open]")); - }, "invoking closed details with auto action opens"); - - promise_test(async function (t) { - assert_false(invokee.matches("[open]")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, - }); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_false(invokee.matches("[open]")); - }, "invoking closed details with auto action and preventDefault does not open"); - - promise_test(async function (t) { - invokee.setAttribute('open', ''); - assert_true(invokee.matches("[open]")); - await clickOn(invokerbutton); - assert_false(invokee.matches("[open]")); - }, "invoking open details with auto action closes"); - - promise_test(async function (t) { - invokee.setAttribute('open', ''); - t.add_cleanup(() => invokee.removeAttribute('open')); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, - }); - assert_true(invokee.matches("[open]")); - await clickOn(invokerbutton); - assert_true(invokee.matches("[open]")); - }, "invoking open details with auto action and preventDefault does not close"); - - promise_test(async function (t) { - t.add_cleanup(() => invokee.removeAttribute('open')); - invokee.addEventListener("invoke", (e) => { - invokee.setAttribute('open', ''); - }, { - once: true, - }); - assert_false(invokee.matches("[open]")); - await clickOn(invokerbutton); - assert_false(invokee.matches("[open]")); - }, "invoking details with auto action where event listener opens leads to a closed details"); - - promise_test(async function (t) { - invokee.setAttribute('open', ''); - t.add_cleanup(() => invokee.removeAttribute('open')); - invokee.addEventListener("invoke", (e) => { - invokee.removeAttribute('open'); - }, { - once: true, - }); - assert_true(invokee.matches("[open]")); - await clickOn(invokerbutton); - assert_true(invokee.matches("[open]")); - }, "invoking open details with auto action where event listener closes leads to an open details"); - - // toggle - - promise_test(async function (t) { - assert_false(invokee.matches("[open]")); - invokerbutton.setAttribute("invokeaction", "toggle"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_true(invokee.matches("[open]")); - }, "invoking closed details with toggle action opens"); - - promise_test(async function (t) { - assert_false(invokee.matches("[open]")); - invokerbutton.setAttribute("invokeaction", "tOgGlE"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_true(invokee.matches("[open]")); - }, "invoking closed details with toggle (case-insensitive) action opens"); - - promise_test(async function (t) { - assert_false(invokee.matches("[open]")); - invokerbutton.setAttribute("invokeaction", "toggle"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { + function resetState() { + invokerbutton.removeAttribute("invokeaction"); + invokee.removeAttribute("open"); + } + + // Open actions + [ + null, + "", + "toggle", + "open", + /* test case sensitivity */ + "tOgGlE", + "oPeN", + ].forEach((action) => { + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invokerbutton.invokeAction = action; + assert_false(invokee.matches("[open]")); + await clickOn(invokerbutton); + assert_true(invokee.matches("[open]")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) closed details opens`, + ); + + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invokerbutton.invokeAction = action; + assert_false(invokee.matches("[open]")); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.removeAttribute("open")); + assert_false(invokee.matches("[open]")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) closed details with preventDefault does not open`, + ); + }); + + // Close actions + [ + null, + "", + "toggle", + "close", + /* test case sensitivity */ + "tOgGlE", + "cLoSe", + ].forEach((action) => { + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invokerbutton.invokeAction = action; + invokee.setAttribute("open", ""); + assert_true(invokee.matches("[open]")); + await clickOn(invokerbutton); + assert_false(invokee.matches("[open]")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) open details closes`, + ); + + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invokerbutton.invokeAction = action; + invokee.setAttribute("open", ""); + invokerbutton.setAttribute("invokeaction", "toggle"); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + assert_true(invokee.matches("[open]")); + await clickOn(invokerbutton); + assert_true(invokee.matches("[open]")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) open details with prevent default closes`, + ); + }); + + // toggle specific + + promise_test(async function (t) { + t.add_cleanup(resetState); + invokerbutton.invokeAction = "toggle"; + invokee.addEventListener( + "invoke", + (e) => { + invokee.setAttribute("open", ""); + }, + { once: true, - }); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); + }, + ); assert_false(invokee.matches("[open]")); - }, "invoking closed details with toggle action and preventDefault does not open"); - - promise_test(async function (t) { - invokee.setAttribute('open', ''); - invokerbutton.setAttribute("invokeaction", "toggle"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - assert_true(invokee.matches("[open]")); await clickOn(invokerbutton); assert_false(invokee.matches("[open]")); - }, "invoking open details with toggle action closes"); + }, "invoking (as toggle) closed details where event listener opens leads to a closed details"); - promise_test(async function (t) { - invokee.setAttribute('open', ''); - t.add_cleanup(() => invokee.removeAttribute('open')); - invokerbutton.setAttribute("invokeaction", "toggle"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, - }); - assert_true(invokee.matches("[open]")); - await clickOn(invokerbutton); - assert_true(invokee.matches("[open]")); - }, "invoking open details with toggle action and preventDefault does not close"); - - // open - - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "open"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - assert_false(invokee.matches("[open]")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_true(invokee.matches("[open]")); - }, "invoking closed details with open action opens"); - - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "oPeN"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - assert_false(invokee.matches("[open]")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_true(invokee.matches("[open]")); - }, "invoking closed details with open (case insensitive) action opens"); + // open specific promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "open"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - invokee.setAttribute('open', ''); + t.add_cleanup(resetState); + invokerbutton.invokeAction = "open"; + invokee.setAttribute("open", ""); assert_true(invokee.matches("[open]")); await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); assert_true(invokee.matches("[open]")); }, "invoking open details with open action is noop"); - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "open"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - assert_false(invokee.matches("[open]")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, - }); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_false(invokee.matches("[open]")); - }, "invoking closed popover with open action and preventDefault does not open"); - // close promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "close"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + t.add_cleanup(resetState); + invokerbutton.invokeAction = "close"; assert_false(invokee.matches("[open]")); await clickOn(invokerbutton); assert_false(invokee.matches("[open]")); }, "invoking closed details with close action is noop"); - - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "close"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - invokee.setAttribute('open', ''); - assert_true(invokee.matches("[open]")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_false(invokee.matches("[open]")); - }, "invoking open details with close action closes"); - - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "cLoSe"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - invokee.setAttribute('open', ''); - assert_true(invokee.matches("[open]")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_false(invokee.matches("[open]")); - }, "invoking open details with close (case insensitive) action closes"); - - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "close"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - invokee.setAttribute('open', ''); - t.add_cleanup(() => invokee.removeAttribute('open')); - assert_true(invokee.matches("[open]")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, - }); - await clickOn(invokerbutton); - assert_true(invokee.matches("[open]")); - }, "invoking open details with close action with preventDefault does not close"); </script> diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-details-invalid-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-details-invalid-behavior.tentative.html new file mode 100644 index 0000000000..d5e90af9c0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-details-invalid-behavior.tentative.html @@ -0,0 +1,49 @@ +<!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> + +<details id="invokee">Details Contents</details> +<button id="invokerbutton" invoketarget="invokee"></button> + +<script> + function resetState() { + invokerbutton.removeAttribute("invokeaction"); + invokee.removeAttribute("open"); + } + + // invalid actions on details + [ + "foo-bar", + "showpopover", + "showmodal", + "showpicker", + "hidepopover", + "hide", + "toggleopen", + ].forEach((action) => { + promise_test(async function (t) { + t.add_cleanup(resetState); + invokerbutton.invokeAction = action; + assert_false(invokee.matches("[open]")); + await clickOn(invokerbutton); + assert_false(invokee.matches("[open]")); + }, `invoking (as ${action}) on details does nothing`); + + promise_test(async function (t) { + t.add_cleanup(resetState); + invokerbutton.invokeAction = action; + invokee.setAttribute("open", ""); + assert_true(invokee.matches("[open]")); + await clickOn(invokerbutton); + assert_true(invokee.matches("[open]")); + }, `invoking (as ${action}) on open details does nothing`); + }); +</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 index 774d308703..9f73e092b0 100644 --- 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 @@ -295,67 +295,6 @@ 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) => { diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-invalid-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-invalid-behavior.tentative.html new file mode 100644 index 0000000000..af84c22594 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-invalid-behavior.tentative.html @@ -0,0 +1,120 @@ +<!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"); + } + + // 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`, + ); + }); + }); +</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 2bddfa7621..f414559e55 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 @@ -1,6 +1,7 @@ <!doctype html> <meta charset="utf-8" /> -<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<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> @@ -19,215 +20,138 @@ promise_test(async function (t) { assert_false(invokee.matches(":popover-open")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_true(invokee.matches(":popover-open")); - }, "invoking (as auto) closed popover opens"); - - promise_test(async function (t) { - assert_false(invokee.matches(":popover-open")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { + invokee.addEventListener("invoke", (e) => { invokerbutton.setAttribute('invokeaction', 'hidepopover'); }, { once: true, }); await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_false(invokee.matches(":popover-open")); - }, "invoking (as auto) closed popover with preventDefault does not open"); - - promise_test(async function (t) { - invokee.showPopover(); - assert_true(invokee.matches(":popover-open")); - await clickOn(invokerbutton); - assert_false(invokee.matches(":popover-open")); - }, "invoking (as auto) open popover closes"); - - promise_test(async function (t) { - invokee.showPopover(); - assert_true(invokee.matches(":popover-open")); - await clickOn(containedinvoker); - assert_false(invokee.matches(":popover-open")); - }, "invoking (as auto) from within open popover closes"); - - promise_test(async function (t) { - invokee.showPopover(); - t.add_cleanup(() => invokee.hidePopover()); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, + t.add_cleanup(() => { + invokee.hidePopover(); + invokerbutton.removeAttribute("invokeaction"); }); assert_true(invokee.matches(":popover-open")); - await clickOn(containedinvoker); - assert_true(invokee.matches(":popover-open")); - }, "invoking (as auto) open popover with preventDefault does not close"); - - // togglepopover - - promise_test(async function (t) { - assert_false(invokee.matches(":popover-open")); - invokerbutton.setAttribute("invokeaction", "togglepopover"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_true(invokee.matches(":popover-open")); - }, "invoking (as togglepopover) closed popover opens"); - - promise_test(async function (t) { - assert_false(invokee.matches(":popover-open")); - invokerbutton.setAttribute("invokeaction", "tOgGlEpOpOvEr"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_true(invokee.matches(":popover-open")); - }, "invoking (as togglepopover - case insensitive) closed popover opens"); - - promise_test(async function (t) { - assert_false(invokee.matches(":popover-open")); - invokerbutton.setAttribute("invokeaction", "togglepopover"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, - }); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_false(invokee.matches(":popover-open")); - }, "invoking (as togglepopover) closed popover with preventDefault does not open"); - - promise_test(async function (t) { - invokee.showPopover(); - 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")); - }, "invoking (as togglepopover) open popover closes"); - - promise_test(async function (t) { - invokee.showPopover(); - containedinvoker.setAttribute("invokeaction", "togglepopover"); - t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction")); - assert_true(invokee.matches(":popover-open")); - 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()); - 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(containedinvoker); - assert_true(invokee.matches(":popover-open")); - }, "invoking (as togglepopover) open popover with preventDefault does not close"); - - // showpopover - - promise_test(async function (t) { + }, "changing invokeaction attribute inside invokeevent doesn't impact the invocation"); + + function resetState() { + invokerbutton.removeAttribute("invokeaction"); + containedinvoker.removeAttribute("invokeaction"); + try { + invokee.hidePopover(); + } catch {} + invokee.setAttribute("popover", ""); + } + + // Open actions + [ + null, + "", + "togglepopover", + "showpopover", + /* test case sensitivity */ + "tOgGlEpOpOvEr", + "sHoWpOpOvEr", + ].forEach((action) => { + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invokerbutton.invokeAction = action; + assert_false(invokee.matches(":popover-open")); + await clickOn(invokerbutton); + assert_true(invokee.matches(":popover-open")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) closed popover opens`, + ); + + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invokerbutton.invokeAction = action; + assert_false(invokee.matches(":popover-open")); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + await clickOn(invokerbutton); + assert_false(invokee.matches(":popover-open")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) closed popover with preventDefault does not open`, + ); + }); + + // Close actions + [ + null, + "", + "togglepopover", + "hidepopover", + /* test case sensitivity */ + "tOgGlEpOpOvEr", + "hIdEpOpOvEr", + ].forEach((action) => { + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invokerbutton.invokeAction = action; + invokee.showPopover(); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton); + assert_false(invokee.matches(":popover-open")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) open popover closes`, + ); + + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) containedinvoker.invokeAction = action; + invokee.showPopover(); + assert_true(invokee.matches(":popover-open")); + await clickOn(containedinvoker); + assert_false(invokee.matches(":popover-open")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) from within open popover closes`, + ); + + promise_test( + async function (t) { + t.add_cleanup(resetState); + if (action !== null) invcontainedinvokervokeaction = action; + invokee.showPopover(); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + assert_true(invokee.matches(":popover-open")); + await clickOn(containedinvoker); + assert_true(invokee.matches(":popover-open")); + }, + `invoking (as ${ + action === null ? "auto" : action || "explicit empty" + }) open popover with preventDefault does not close`, + ); + }); + + // showpopover specific + promise_test(async function (t) { + t.add_cleanup(resetState); invokerbutton.setAttribute("invokeaction", "showpopover"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - assert_false(invokee.matches(":popover-open")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_true(invokee.matches(":popover-open")); - }, "invoking (as showpopover) closed popover opens"); - - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "sHoWpOpOvEr"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - assert_false(invokee.matches(":popover-open")); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_true(invokee.matches(":popover-open")); - }, "invoking (as showpopover - case insensitive) closed popover opens"); - - promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "showpopover"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); invokee.showPopover(); assert_true(invokee.matches(":popover-open")); await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); assert_true(invokee.matches(":popover-open")); }, "invoking (as showpopover) open popover is noop"); + // hidepopover specific promise_test(async function (t) { - invokerbutton.setAttribute("invokeaction", "showpopover"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); - assert_false(invokee.matches(":popover-open")); - invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, - }); - await clickOn(invokerbutton); - t.add_cleanup(() => invokee.hidePopover()); - assert_false(invokee.matches(":popover-open")); - }, "invoking (as showpopover) closed popover with preventDefault does not open"); - - // hidepopover - - promise_test(async function (t) { + t.add_cleanup(resetState); invokerbutton.setAttribute("invokeaction", "hidepopover"); - t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); assert_false(invokee.matches(":popover-open")); await clickOn(invokerbutton); assert_false(invokee.matches(":popover-open")); }, "invoking (as hidepopover) closed popover is noop"); - - promise_test(async function (t) { - containedinvoker.setAttribute("invokeaction", "hidepopover"); - t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction")); - invokee.showPopover(); - assert_true(invokee.matches(":popover-open")); - 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) { - containedinvoker.setAttribute("invokeaction", "hIdEpOpOvEr"); - t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction")); - invokee.showPopover(); - assert_true(invokee.matches(":popover-open")); - 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) { - 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(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/invoketarget-on-popover-invalid-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-invalid-behavior.tentative.html new file mode 100644 index 0000000000..755f3a6777 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-invalid-behavior.tentative.html @@ -0,0 +1,47 @@ +<!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> + +<div id="invokee" popover> + <button id="containedinvoker" invoketarget="invokee"></button> +</div> +<button id="invokerbutton" invoketarget="invokee"></button> + +<script> + function resetState() { + invokerbutton.removeAttribute("invokeaction"); + containedinvoker.removeAttribute("invokeaction"); + try { + invokee.hidePopover(); + } catch {} + invokee.setAttribute("popover", ""); + } + + // invalid actions on showpopover + ["foo-bar", "showmodal", "showpicker", "open", "close"].forEach((action) => { + promise_test(async function (t) { + t.add_cleanup(resetState); + invokerbutton.invokeAction = action; + 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) { + t.add_cleanup(resetState); + invokerbutton.invokeAction = action; + 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/invoketarget-on-video-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-video-behavior.tentative.html index 5bbcd83e72..d15d6f9584 100644 --- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-video-behavior.tentative.html +++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-video-behavior.tentative.html @@ -1,6 +1,7 @@ <!doctype html> <meta charset="utf-8" /> <meta name="author" title="Luke Warlow" href="mailto:luke@warlow.dev" /> +<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> @@ -25,7 +26,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", ""); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -43,7 +44,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "playpause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -62,7 +63,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "playpause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -75,12 +76,12 @@ invokee.currentTime = 0; invokee.muted = false; }); - await test_driver.bless('play video'); + await test_driver.bless("play video"); invokee.play(); assert_false(invokee.paused); invokerbutton.setAttribute("invokeaction", "playpause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -98,7 +99,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "play"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -112,12 +113,12 @@ invokee.muted = false; }); invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, + once: true, }); assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "play"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -130,12 +131,12 @@ invokee.currentTime = 0; invokee.muted = false; }); - await test_driver.bless('play video'); + await test_driver.bless("play video"); invokee.play(); assert_false(invokee.paused); invokerbutton.setAttribute("invokeaction", "play"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.paused); @@ -153,7 +154,7 @@ assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "pause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -167,12 +168,12 @@ invokee.muted = false; }); invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, + once: true, }); assert_true(invokee.paused); invokerbutton.setAttribute("invokeaction", "pause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -185,12 +186,12 @@ invokee.currentTime = 0; invokee.muted = false; }); - await test_driver.bless('play video'); + await test_driver.bless("play video"); invokee.play(); assert_false(invokee.paused); invokerbutton.setAttribute("invokeaction", "pause"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.paused); @@ -208,7 +209,7 @@ assert_false(invokee.muted); invokerbutton.setAttribute("invokeaction", "toggleMuted"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_true(invokee.muted); @@ -222,12 +223,12 @@ invokee.muted = false; }); invokee.addEventListener("invoke", (e) => e.preventDefault(), { - once: true, + once: true, }); assert_false(invokee.muted); invokerbutton.setAttribute("invokeaction", "toggleMuted"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.muted); @@ -244,10 +245,9 @@ assert_true(invokee.muted); invokerbutton.setAttribute("invokeaction", "toggleMuted"); await clickOn(invokerbutton); - await new Promise(resolve => { + await new Promise((resolve) => { requestAnimationFrame(resolve); }); assert_false(invokee.muted); }, "invoking muted video with toggleMuted action unmutes it"); - </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 8420f24b6f..4261f9c0d3 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 @@ -14,3 +14,14 @@ async function clickOn(element) { .send(); await waitForRender(); } +async function hoverOver(element) { + await waitForRender(); + 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), {}) + .send(); + await waitForRender(); +} diff --git a/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties-reference-expected.html b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties-reference-expected.html new file mode 100644 index 0000000000..c62ff5b24d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties-reference-expected.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<body> + <div> + The permission element should have some limits for specific properties: + <ul> + <li>font-weight is adjusted to be at least 200.</li> + <li>font-style should only have "normal" or "italic" values.</li> + <li>word-spacing should be at most 0.5 of the font size, and non-negative.</li> + <li>letter-spacing should be between -0.05 and 0.2 of the font size.</li> + </ul> + </div> + +<style> + #id1 { + font-weight: 200; + font-style: normal; + word-spacing: 0.5em; + font-size: 100px; + height: auto; + width: auto; + letter-spacing: 20px; + } + #id2 { + word-spacing: 0em; + height: auto; + width: auto; + font-size: 10px; + letter-spacing: -0.5px; + } +</style> + +<permission id="id1" type="geolocation"> +<permission id="id2" type="camera"> +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties-reference.tentative.html b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties-reference.tentative.html new file mode 100644 index 0000000000..b8337ab87d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties-reference.tentative.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<link rel="match" href="bounded-css-properties-reference-expected.html"> +<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style"> +<body> + <div> + The permission element should have some limits for specific properties: + <ul> + <li>font-weight is adjusted to be at least 200.</li> + <li>font-style should only have "normal" or "italic" values.</li> + <li>word-spacing should be at most 0.5 of the font size, and non-negative.</li> + <li>letter-spacing should be between -0.05 and 0.2 of the font size.</li> + </ul> + </div> + +<style> + #id1 { + font-weight: 100; + font-style: oblique 30deg; + word-spacing: 1em; + font-size: 100px; + height: auto; + width: auto; + letter-spacing: 25px; + } + #id2 { + word-spacing: -1000px; + height: auto; + width: auto; + font-size: 10px; + letter-spacing: -1px; + } +</style> + +<permission id="id1" type="geolocation"> +<permission id="id2" type="camera"> +</body>
\ No newline at end of file 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 deleted file mode 100644 index 98c3d70e98..0000000000 --- a/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html +++ /dev/null @@ -1,38 +0,0 @@ -<!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/bounded-css-properties.tentative.html b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.tentative.html new file mode 100644 index 0000000000..c0f0fe3454 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.tentative.html @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style"> +<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. + * word-spacing should be at most 0.5 of the font size, and non-negative. + * letter-spacing should be between -0.05 and 0.2 of the font size. +--> +<style> + #id-over-bounds { + font-weight: 100; + font-style: oblique 30deg; + word-spacing: 1em; + font-size: 100px; + letter-spacing: 21px; + } + #id-under-bounds { + word-spacing: -1px; + font-size: 100px; + letter-spacing: -6px; + } + #id-within-bounds { + font-weight: 300; + font-style: italic; + word-spacing: 0.4em; + font-size: 100px; + letter-spacing: 15px; + } +</style> + + +<permission id="id-over-bounds" type="geolocation"> +<permission id="id-under-bounds" type="camera"> +<permission id="id-within-bounds" type="microphone"> + +<script> + test(function(){ + var el = document.getElementById("id-over-bounds"); + assert_equals(getComputedStyle(el).fontWeight, "200", "font-weight"); + assert_equals(getComputedStyle(el).fontStyle, "normal", "font-style"); + assert_equals(getComputedStyle(el).wordSpacing, "50px", "word-spacing"); + assert_equals(getComputedStyle(el).letterSpacing, "20px", "letter-spacing"); + + el = document.getElementById("id-under-bounds"); + assert_equals(getComputedStyle(el).wordSpacing, "0px", "word-spacing, negative"); + assert_equals(getComputedStyle(el).letterSpacing, "-5px", "letter-spacing, negative"); + }, "Properties with out-of-bounds values should be corrected"); + + test(function(){ + var el = document.getElementById("id-within-bounds"); + assert_equals(getComputedStyle(el).fontWeight, "300", "font-weight"); + assert_equals(getComputedStyle(el).fontStyle, "italic", "font-style"); + assert_equals(getComputedStyle(el).wordSpacing, "40px", "word-spacing"); + assert_equals(getComputedStyle(el).letterSpacing, "15px", "letter-spacing"); + + el.style.letterSpacing = "-4px"; + assert_equals(getComputedStyle(el).letterSpacing, "-4px", "letter-spacing, negative"); + }, "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/display-css-property-reference-expected.html b/testing/web-platform/tests/html/semantics/permission-element/display-css-property-reference-expected.html new file mode 100644 index 0000000000..6a04c94c03 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/permission-element/display-css-property-reference-expected.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<body> + <div> + The permission element should either be display 'none' or 'inline-block' + </div> + +<style> + #id1 { + display: inline-block; + } +</style> + +<permission id="id1" type="geolocation"> +<span>After element</span> +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/permission-element/display-css-property-reference.tentative.html b/testing/web-platform/tests/html/semantics/permission-element/display-css-property-reference.tentative.html new file mode 100644 index 0000000000..973a76d723 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/permission-element/display-css-property-reference.tentative.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<link rel="match" href="display-css-property-reference-expected.html"> +<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style"> +<body> + <div> + The permission element should either be display 'none' or 'inline-block' + </div> + +<style> + #id1 { + display: flex; + } + #id2 { + display: none; + } +</style> + +<permission id="id1" type="geolocation"> +<permission id="id2" type="camera"> +<span>After element</span> +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/permission-element/display-css-property.tentative.html b/testing/web-platform/tests/html/semantics/permission-element/display-css-property.tentative.html new file mode 100644 index 0000000000..7aa22ef4a2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/permission-element/display-css-property.tentative.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<!-- + 'display' should either be 'none' or 'inline-block' +--> +<style> + #id1 { + display: inline-block; + } + #id2 { + display: block; + } + #id3 { + display: none; + } +</style> + + +<permission id="id1" type="geolocation"> +<permission id="id2" type="camera"> +<permission id="id3" type="microphone"> + +<script> + test(function(){ + assert_equals(getComputedStyle(document.getElementById("id1")).display, "inline-block", "'inline-block' should be kept"); + assert_equals(getComputedStyle(document.getElementById("id2")).display, "inline-block", "'block' should be changed to 'inline-block'"); + assert_equals(getComputedStyle(document.getElementById("id3")).display, "none", "'none' should be kept"); + }, "'display' should be either 'inline-block' or 'none'"); +</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.tentative.html index c7186563f0..334280c83b 100644 --- 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.tentative.html @@ -1,5 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> +<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <body> 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.tentative.html index 97290bb4df..de622bbb3e 100644 --- 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.tentative.html @@ -1,5 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> +<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <body> diff --git a/testing/web-platform/tests/html/semantics/permission-element/no-end-tag-no-contents.html b/testing/web-platform/tests/html/semantics/permission-element/no-end-tag-no-contents.tentative.html index 5fcce1421b..bea3d7102c 100644 --- a/testing/web-platform/tests/html/semantics/permission-element/no-end-tag-no-contents.html +++ b/testing/web-platform/tests/html/semantics/permission-element/no-end-tag-no-contents.tentative.html @@ -1,5 +1,6 @@ <!DOCTYPE html> <meta charset=utf-8> +<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <body> diff --git a/testing/web-platform/tests/html/semantics/popovers/button-type-reset-popovertarget.tentative.html b/testing/web-platform/tests/html/semantics/popovers/button-type-reset-popovertarget.tentative.html new file mode 100644 index 0000000000..975eab0d66 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/popovers/button-type-reset-popovertarget.tentative.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://issues.chromium.org/issues/329118508"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id=mypopover popover=auto>popover</div> + +<iframe name=foo></iframe> +<form target=foo action="about:blank"> + <button id=reset-in-form type=reset popovertarget=mypopover>reset</button> + <button id=submit-in-form type=submit popovertarget=mypopover>submit</button> + <button id=button-in-form type=button popovertarget=mypopover>type=button</button> +</form> + +<button id=reset-outside-form type=reset popovertarget=mypopover>reset</button> +<button id=submit-outside-form type=submit popovertarget=mypopover>submit</button> +<button id=button-outside-form type=button popovertarget=mypopover>type=button</button> + +<script> +test(() => { + const testButton = (id, expectedToToggle) => { + document.getElementById(id).click(); + if (expectedToToggle) { + assert_true(mypopover.matches(':popover-open'), + `${id}: button should open the popover.`); + } else { + assert_false(mypopover.matches(':popover-open'), + `${id}: button should not open the popover.`); + } + if (mypopover.matches(':popover-open')) { + mypopover.hidePopover(); + } + }; + + testButton('reset-in-form', false); + testButton('submit-in-form', false); + testButton('button-in-form', true); + testButton('reset-outside-form', true); + testButton('submit-outside-form', true); + testButton('button-outside-form', true); +}, 'Button type=reset and type=submit should not run popover algorithms when in a form.'); +</script> diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-anchor-display.tentative.html b/testing/web-platform/tests/html/semantics/popovers/popover-anchor-display.tentative.html index d50dd6c857..bddc44006d 100644 --- a/testing/web-platform/tests/html/semantics/popovers/popover-anchor-display.tentative.html +++ b/testing/web-platform/tests/html/semantics/popovers/popover-anchor-display.tentative.html @@ -94,7 +94,7 @@ showDefaultopenPopoversOnLoad(); top: anchor(top); } #popover5 { - anchor-default: --anchor1; /* shouldn't be used */ + position-anchor: --anchor1; /* shouldn't be used */ left: anchor(implicit right); top: anchor(implicit top); } @@ -102,7 +102,7 @@ showDefaultopenPopoversOnLoad(); anchor-name: --anchor6; } #popover6 { - anchor-default: --anchor6; + position-anchor: --anchor6; left: anchor(right); /* shouldn't use the implicit anchor */ top: anchor(top); } diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-anchor-scroll-display.tentative.html b/testing/web-platform/tests/html/semantics/popovers/popover-anchor-scroll-display.tentative.html index 7ed6cf1adf..2c6b0bafb9 100644 --- a/testing/web-platform/tests/html/semantics/popovers/popover-anchor-scroll-display.tentative.html +++ b/testing/web-platform/tests/html/semantics/popovers/popover-anchor-scroll-display.tentative.html @@ -56,7 +56,7 @@ anchor-name: --anchor2; } #popover2 { - anchor-default: --anchor2; + position-anchor: --anchor2; left: anchor(right); top: anchor(top); } diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-light-dismiss.html b/testing/web-platform/tests/html/semantics/popovers/popover-light-dismiss.html index 916d52ef5e..45db242e91 100644 --- a/testing/web-platform/tests/html/semantics/popovers/popover-light-dismiss.html +++ b/testing/web-platform/tests/html/semantics/popovers/popover-light-dismiss.html @@ -11,6 +11,19 @@ <script src="/resources/testdriver-vendor.js"></script> <script src="resources/popover-utils.js"></script> +<style> + [popover] { + /* Position most popovers at the bottom-right, out of the way */ + inset:auto; + bottom:0; + right:0; + } + [popover]::backdrop { + /* This should *not* affect anything: */ + pointer-events: auto; + } +</style> + <button id=b1t popovertarget='p1'>Popover 1</button> <button id=b1s popovertarget='p1' popovertargetaction=show>Popover 1</button> <span id=outside>Outside all popovers</span> @@ -26,11 +39,6 @@ <style> #p1 {top: 50px;} #p2 {top: 120px;} - [popover] {bottom:auto;} - [popover]::backdrop { - /* This should *not* affect anything: */ - pointer-events: auto; - } </style> <script> const popover1 = document.querySelector('#p1'); @@ -584,24 +592,50 @@ promise_test(async () => { <div id=p29 popover>Popover 29</div> <button id=b29 popovertarget=p29>Open popover 29</button> -<iframe id=iframe29 width=100 height=100></iframe> +<iframe id=iframe29 width=100 height=30></iframe> <script> promise_test(async () => { let iframe_url = (new URL("/common/blank.html", location.href)).href; iframe29.src = iframe_url; iframe29.contentDocument.body.style.height = '100%'; - assert_false(p29.matches(':popover-open')); + assert_false(p29.matches(':popover-open'),'initially hidden'); p29.showPopover(); - assert_true(p29.matches(':popover-open')); + assert_true(p29.matches(':popover-open'),'showing'); let actions = new test_driver.Actions(); await actions.pointerMove(0,0,{origin: b29}) .pointerDown({button: actions.ButtonType.LEFT}) .send(); + await waitForRender(); + assert_true(p29.matches(':popover-open'),'showing after pointerdown'); actions = new test_driver.Actions(); await actions.pointerMove(0,0,{origin: iframe29.contentDocument.body}) .pointerUp({button: actions.ButtonType.LEFT}) .send(); - assert_true(p29.matches(':popover-open')); + await waitForRender(); + assert_true(p29.matches(':popover-open'),'showing after pointerup'); },`Pointer down in one document and pointer up in another document shouldn't dismiss popover`); </script> + +<div id=p30 popover>Popover 30</div> +<button id=b30 popovertarget=p30>Open popover 30</button> +<button id=b30b>Non-invoker</button> +<script> +promise_test(async () => { + assert_false(p30.matches(':popover-open'),'initially hidden'); + p30.showPopover(); + assert_true(p30.matches(':popover-open'),'showing'); + let actions = new test_driver.Actions(); + await actions.pointerMove(0,0,{origin: b30}) + .pointerDown({button: actions.ButtonType.LEFT}) + .send(); + await waitForRender(); + assert_true(p30.matches(':popover-open'),'showing after pointerdown'); + actions = new test_driver.Actions(); + await actions.pointerMove(0,0,{origin: b30b}) + .pointerUp({button: actions.ButtonType.LEFT}) + .send(); + await waitForRender(); + assert_true(p30.matches(':popover-open'),'showing after pointerup'); +},`Pointer down inside invoker and up outside that invoker shouldn't dismiss popover`); +</script> diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-top-layer-nesting.tentative.html b/testing/web-platform/tests/html/semantics/popovers/popover-top-layer-nesting.html index a0b3b60b72..a0b3b60b72 100644 --- a/testing/web-platform/tests/html/semantics/popovers/popover-top-layer-nesting.tentative.html +++ b/testing/web-platform/tests/html/semantics/popovers/popover-top-layer-nesting.html diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/integrity.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/integrity.html index 1dd0dad470..7ee6452bcc 100644 --- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/integrity.html +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/integrity.html @@ -12,7 +12,7 @@ window.matchesEvents = []; window.mismatchesLog = []; window.mismatchesEvents = []; </script> -<script type="module" src="resources/integrity-matches.js" integrity="sha384-xvbfmg9iJFHqmCoOS4VNMCwnFPPxEoIlW1Ojzl+fgEd+Wf8Pyez+SMWue+KNovjA" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> +<script type="module" src="resources/integrity-matches.js" integrity="sha384-KtvB2Fgbhx2NAEizVeuGMa+QgvBzlBvVRxdpRnIECuGUvzzQsnVejyDL5J0fVP9M" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> <script type="module" src="resources/integrity-mismatches.js" integrity="sha384-doesnotmatch" onload="window.mismatchesEvents.push('load');" onerror="window.mismatchesEvents.push('error')"></script> <script type="module"> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity.html index 68a794b973..0aa92d9fdc 100644 --- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity.html +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity.html @@ -12,7 +12,7 @@ window.matchesEvents = []; window.mismatchesLog = []; window.mismatchesEvents = []; </script> -<script type="module" src="integrity-matches.js" integrity="sha384-VmQQfGzBiLKdyzw4FA4kL4ohu4tyujV68ddgW1aN/1v3cBZNNBn2gDFdVQxfL7+a" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> +<script type="module" src="integrity-matches.js" integrity="sha384-kc1K2KFKQhnYE1AdnpmUUpFVnxz1GCgGbQ19e3zmXrZw23rgpwa9il4/pHp7NYWA" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> <script type="module" src="integrity-mismatches.js" integrity="sha384-doesnotmatch" onload="window.mismatchesEvents.push('load');" onerror="window.mismatchesEvents.push('error')"></script> <script type="module"> |