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