summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/editing/other/editable-state-and-focus-in-shadow-dom-in-designMode.tentative.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/editing/other/editable-state-and-focus-in-shadow-dom-in-designMode.tentative.html
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/editing/other/editable-state-and-focus-in-shadow-dom-in-designMode.tentative.html')
-rw-r--r--testing/web-platform/tests/editing/other/editable-state-and-focus-in-shadow-dom-in-designMode.tentative.html252
1 files changed, 252 insertions, 0 deletions
diff --git a/testing/web-platform/tests/editing/other/editable-state-and-focus-in-shadow-dom-in-designMode.tentative.html b/testing/web-platform/tests/editing/other/editable-state-and-focus-in-shadow-dom-in-designMode.tentative.html
new file mode 100644
index 0000000000..88e6d29129
--- /dev/null
+++ b/testing/web-platform/tests/editing/other/editable-state-and-focus-in-shadow-dom-in-designMode.tentative.html
@@ -0,0 +1,252 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Testing editable state and focus in shadow DOM in design mode</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../include/editor-test-utils.js"></script>
+</head>
+<body>
+<h3>open</h3>
+<my-shadow data-mode="open"></my-shadow>
+<h3>closed</h3>
+<my-shadow data-mode="closed"></my-shadow>
+
+<script>
+"use strict";
+
+document.designMode = "on";
+const utils = new EditorTestUtils(document.body);
+
+class MyShadow extends HTMLElement {
+ #defaultInnerHTML =
+ "<style>:focus { outline: 3px red solid; }</style>" +
+ "<div>text" +
+ "<div contenteditable=\"\">editable</div>" +
+ "<object tabindex=\"0\">object</object>" +
+ "<p tabindex=\"0\">paragraph</p>" +
+ "</div>";
+ #shadowRoot;
+
+ constructor() {
+ super();
+ this.#shadowRoot = this.attachShadow({mode: this.getAttribute("data-mode")});
+ this.#shadowRoot.innerHTML = this.#defaultInnerHTML;
+ }
+
+ reset() {
+ this.#shadowRoot.innerHTML = this.#defaultInnerHTML;
+ this.#shadowRoot.querySelector("div").getBoundingClientRect();
+ }
+
+ focusText() {
+ this.focus();
+ const div = this.#shadowRoot.querySelector("div");
+ getSelection().collapse(div.firstChild || div, 0);
+ }
+
+ focusContentEditable() {
+ this.focus();
+ const contenteditable = this.#shadowRoot.querySelector("div[contenteditable]");
+ contenteditable.focus();
+ getSelection().collapse(contenteditable.firstChild || contenteditable, 0);
+ }
+
+ focusObject() {
+ this.focus();
+ this.#shadowRoot.querySelector("object[tabindex]").focus();
+ }
+
+ focusParagraph() {
+ this.focus();
+ const tabbableP = this.#shadowRoot.querySelector("p[tabindex]");
+ tabbableP.focus();
+ getSelection().collapse(tabbableP.firstChild || tabbableP, 0);
+ }
+
+ getInnerHTML() {
+ return this.#shadowRoot.innerHTML;
+ }
+
+ getDefaultInnerHTML() {
+ return this.#defaultInnerHTML;
+ }
+
+ getFocusedElementName() {
+ return this.#shadowRoot.querySelector(":focus")?.tagName.toLocaleLowerCase() || "";
+ }
+
+ getSelectedRange() {
+ // XXX There is no standardized way to retrieve selected ranges in
+ // shadow trees, therefore, we use non-standardized API for now
+ // since the main purpose of this test is checking the behavior of
+ // selection changes in shadow trees, not checking the selection API.
+ const selection =
+ this.#shadowRoot.getSelection !== undefined
+ ? this.#shadowRoot.getSelection()
+ : getSelection();
+ return selection.getRangeAt(0);
+ }
+}
+
+customElements.define("my-shadow", MyShadow);
+
+function getRangeDescription(range) {
+ function getNodeDescription(node) {
+ if (!node) {
+ return "null";
+ }
+ switch (node.nodeType) {
+ case Node.TEXT_NODE:
+ case Node.COMMENT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ return `${node.nodeName} "${node.data}"`;
+ case Node.ELEMENT_NODE:
+ return `<${node.nodeName.toLowerCase()}>`;
+ default:
+ return `${node.nodeName}`;
+ }
+ }
+ if (range === null) {
+ return "null";
+ }
+ if (range === undefined) {
+ return "undefined";
+ }
+ return range.startContainer == range.endContainer &&
+ range.startOffset == range.endOffset
+ ? `(${getNodeDescription(range.startContainer)}, ${range.startOffset})`
+ : `(${getNodeDescription(range.startContainer)}, ${
+ range.startOffset
+ }) - (${getNodeDescription(range.endContainer)}, ${range.endOffset})`;
+}
+
+promise_test(async () => {
+ await new Promise(resolve => addEventListener("load", resolve, {once: true}));
+ assert_true(true, "Load event is fired");
+}, "Waiting for load");
+
+/**
+ * The expected result of this test is based on Blink and Gecko's behavior.
+ */
+
+for (const mode of ["open", "closed"]) {
+ const host = document.querySelector(`my-shadow[data-mode=${mode}]`);
+ promise_test(async (t) => {
+ host.reset();
+ host.focusText();
+ test(() => {
+ assert_equals(
+ host.getFocusedElementName(),
+ "",
+ `No element should have focus after ${t.name}`
+ );
+ }, `Focus after ${t.name}`);
+ await utils.sendKey("A");
+ test(() => {
+ assert_equals(
+ host.getInnerHTML(),
+ host.getDefaultInnerHTML(),
+ `The shadow DOM shouldn't be modified after ${t.name}`
+ );
+ }, `Typing "A" after ${t.name}`);
+ }, `Collapse selection into text in the ${mode} shadow DOM`);
+
+ promise_test(async (t) => {
+ host.reset();
+ host.focusContentEditable();
+ test(() => {
+ assert_equals(
+ host.getFocusedElementName(),
+ "div",
+ `<div contenteditable> should have focus after ${t.name}`
+ );
+ }, `Focus after ${t.name}`);
+ await utils.sendKey("A");
+ test(() => {
+ assert_equals(
+ host.getInnerHTML(),
+ host.getDefaultInnerHTML().replace("<div contenteditable=\"\">", "<div contenteditable=\"\">A"),
+ `The shadow DOM shouldn't be modified after ${t.name}`
+ );
+ }, `Typing "A" after ${t.name}`);
+ }, `Collapse selection into text in <div contenteditable> in the ${mode} shadow DOM`);
+
+ promise_test(async (t) => {
+ host.reset();
+ host.focusObject();
+ test(() => {
+ assert_equals(
+ host.getFocusedElementName(),
+ "object",
+ `The <object> element should have focus after ${t.name}`
+ );
+ }, `Focus after ${t.name}`);
+ await utils.sendKey("A");
+ test(() => {
+ assert_equals(
+ host.getInnerHTML(),
+ host.getDefaultInnerHTML(),
+ `The shadow DOM shouldn't be modified after ${t.name}`
+ );
+ }, `Typing "A" after ${t.name}`);
+ }, `Set focus to <object> in the ${mode} shadow DOM`);
+
+ promise_test(async (t) => {
+ host.reset();
+ host.focusParagraph();
+ test(() => {
+ assert_equals(
+ host.getFocusedElementName(),
+ "p",
+ `The <p tabindex="0"> element should have focus after ${t.name}`
+ );
+ }, `Focus after ${t.name}`);
+ await utils.sendKey("A");
+ test(() => {
+ assert_equals(
+ host.getInnerHTML(),
+ host.getDefaultInnerHTML(),
+ `The shadow DOM shouldn't be modified after ${t.name}`
+ );
+ }, `Typing "A" after ${t.name}`);
+ }, `Set focus to <p tabindex="0"> in the ${mode} shadow DOM`);
+
+ promise_test(async (t) => {
+ host.reset();
+ host.focusParagraph();
+ await utils.sendSelectAllShortcutKey();
+ assert_in_array(
+ getRangeDescription(host.getSelectedRange()),
+ [
+ // Feel free to add reasonable select all result in the <my-shadow>.
+ "(#document-fragment, 0) - (#document-fragment, 2)",
+ "(#text \"text\", 0) - (#text \"paragraph\", 9)",
+ ],
+ `Only all children of the ${mode} shadow DOM should be selected`
+ );
+ getSelection().collapse(document.body, 0);
+ }, `SelectAll in the ${mode} shadow DOM`);
+
+ promise_test(async (t) => {
+ host.reset();
+ host.focusContentEditable();
+ await utils.sendSelectAllShortcutKey();
+ assert_in_array(
+ getRangeDescription(host.getSelectedRange()),
+ [
+ // Feel free to add reasonable select all result in the <div contenteditable>.
+ "(<div>, 0) - (<div>, 1)",
+ "(#text \"editable\", 0) - (#text \"editable\", 8)",
+ ]
+ );
+ getSelection().collapse(document.body, 0);
+ }, `SelectAll in the <div contenteditable> in the ${mode} shadow DOM`);
+}
+</script>
+</body>
+</html>