summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html')
-rw-r--r--testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html312
1 files changed, 312 insertions, 0 deletions
diff --git a/testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html b/testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html
new file mode 100644
index 0000000000..99667029ad
--- /dev/null
+++ b/testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html
@@ -0,0 +1,312 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus() on shadow host with delegatesFocus</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/shadow-utils.js"></script>
+
+<body>
+<div id="host">
+ <div id="slottedToSecondSlot" slot="secondSlot">slottedToSecondSlot</div>
+ <div id="slottedToFirstSlot" slot="firstSlot">slottedToFirstSlot</div>
+</div>
+<div id="outside">outside</div>
+</body>
+
+<script>
+const host = document.getElementById("host");
+const slottedToSecondSlot = document.getElementById("slottedToSecondSlot");
+const slottedToFirstSlot = document.getElementById("slottedToFirstSlot");
+const outside = document.getElementById("outside");
+
+const shadowRoot = host.attachShadow({ mode: "open", delegatesFocus: true });
+const aboveSlots = document.createElement("div");
+aboveSlots.innerText = "aboveSlots";
+const firstSlot = document.createElement("slot");
+firstSlot.name = "firstSlot";
+const secondSlot = document.createElement("slot");
+secondSlot.name = "secondSlot";
+const belowSlots = document.createElement("div");
+belowSlots.innerText = "belowSlots";
+shadowRoot.appendChild(aboveSlots);
+shadowRoot.appendChild(firstSlot);
+shadowRoot.appendChild(secondSlot);
+shadowRoot.appendChild(belowSlots);
+
+const elementsInFlatTreeOrder = [host, aboveSlots, firstSlot,
+ slottedToFirstSlot, secondSlot, slottedToSecondSlot, belowSlots, outside];
+
+// Final structure:
+// <div #host> (delegatesFocus=true)
+// #shadowRoot
+// <div #aboveSlots>
+// <slot #firstSlot>
+// (slotted) <div #slottedToFirstSlot>
+// <slot #secondSlot>
+// (slotted) <div #slottedToSecondSlot>
+// <div #belowSlots>
+// <div #outside>
+
+
+function setAllTabIndex(value) {
+ setTabIndex(elementsInFlatTreeOrder, value);
+}
+
+function removeAllTabIndex() {
+ removeTabIndex(elementsInFlatTreeOrder);
+}
+
+function resetTabIndexAndFocus() {
+ removeAllTabIndex();
+ resetFocus(document);
+ resetFocus(shadowRoot);
+}
+
+test(() => {
+ resetTabIndexAndFocus();
+ setAllTabIndex(0);
+ // Structure:
+ // <div #host> (delegatesFocus=true) tabindex=0
+ // #shadowRoot
+ // <div #aboveSlots> tabindex=0
+ // <slot #firstSlot> tabindex=0
+ // (slotted) <div #slottedToFirstSlot> tabindex=0
+ // <slot #secondSlot> tabindex=0
+ // (slotted) <div #slottedToSecondSlot> tabindex=0
+ // <div #belowSlots> tabindex=0
+ // <div #outside> tabindex=0
+ // First focusable = #aboveSlots
+ host.focus();
+ assert_equals(shadowRoot.activeElement, aboveSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus, all tabindex=0");
+
+test(() => {
+ resetTabIndexAndFocus();
+ setAllTabIndex(0);
+ setTabIndex([host], -1);
+ // First focusable = #aboveSlots
+ host.focus();
+ assert_equals(shadowRoot.activeElement, aboveSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus & tabindex =-1, all other tabindex=0");
+
+test(() => {
+ resetTabIndexAndFocus();
+ setTabIndex([aboveSlots, slottedToFirstSlot, slottedToSecondSlot, belowSlots], 0);
+ // First focusable = #aboveSlots
+ host.focus();
+ assert_equals(shadowRoot.activeElement, aboveSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus & no tabindex, all other tabindex=0");
+
+test(() => {
+ resetTabIndexAndFocus();
+ setAllTabIndex(-1);
+ setTabIndex([host], 0);
+ // First focusable = #aboveSlots
+ host.focus();
+ assert_equals(shadowRoot.activeElement, aboveSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus & tabindex = 0, all other tabindex=-1");
+
+test(() => {
+ resetTabIndexAndFocus();
+ removeAllTabIndex();
+ // No focusable element under #host in the flat tree.
+ host.focus();
+ assert_equals(shadowRoot.activeElement, null);
+ assert_equals(document.activeElement, document.body);
+}, "focus() on host with delegatesFocus, all without tabindex");
+
+test(() => {
+ resetTabIndexAndFocus();
+ // First focusable = #aboveSlots
+ setAllTabIndex(-1);
+ host.focus();
+ assert_equals(shadowRoot.activeElement, aboveSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus, all tabindex=-1");
+
+test(() => {
+ resetTabIndexAndFocus();
+ removeAllTabIndex();
+ setTabIndex([host, belowSlots], 0);
+ // Structure:
+ // <div #host> (delegatesFocus=true) tabindex=0
+ // #shadowRoot
+ // <div #aboveSlots>
+ // <slot #firstSlot>
+ // (slotted) <div #slottedToFirstSlot>
+ // <slot #secondSlot>
+ // (slotted) <div #slottedToSecondSlot>
+ // <div #belowSlots> tabindex=0
+ // <div #outside>
+ // First focusable = #belowSlots
+ host.focus();
+ assert_equals(shadowRoot.activeElement, belowSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus & tabindex=0, #belowSlots with tabindex=0");
+
+test(() => {
+ resetTabIndexAndFocus();
+ removeAllTabIndex();
+ setTabIndex([host, outside], 0);
+ // Structure:
+ // <div #host> (delegatesFocus=true) tabindex=0
+ // #shadowRoot
+ // <div #aboveSlots>
+ // <slot #firstSlot>
+ // (slotted) <div #slottedToFirstSlot>
+ // <slot #secondSlot>
+ // (slotted) <div #slottedToSecondSlot>
+ // <div #belowSlots>
+ // <div #outside> tabindex=0
+ // No focusable element under #host in the flat tree.
+ host.focus();
+ assert_equals(shadowRoot.activeElement, null);
+ assert_equals(document.activeElement, document.body);
+}, "focus() on host with delegatesFocus & tabindex=0, #outside with tabindex=0");
+
+test(() => {
+ resetTabIndexAndFocus();
+ setTabIndex([host, aboveSlots, belowSlots], 0);
+ // Structure:
+ // <div #host> (delegatesFocus=true) tabindex=0
+ // #shadowRoot
+ // <div #aboveSlots> tabindex=0
+ // <slot #firstSlot>
+ // (slotted) <div #slottedToFirstSlot>
+ // <slot #secondSlot>
+ // (slotted) <div #slottedToSecondSlot>
+ // <div #belowSlots> tabindex=0
+ // <div #outside>
+ // First focusable = #aboveSlots
+ host.focus();
+ assert_equals(shadowRoot.activeElement, aboveSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus & tabindex=0, #aboveSlots and #belowSlots with tabindex=0");
+
+test(() => {
+ resetTabIndexAndFocus();
+ setTabIndex([host, aboveSlots], 0);
+ setTabIndex([belowSlots], 1);
+ // Structure:
+ // <div #host> (delegatesFocus=true) tabindex=0
+ // #shadowRoot
+ // <div #aboveSlots> tabindex=0
+ // <slot #firstSlot>
+ // (slotted) <div #slottedToFirstSlot>
+ // <slot #secondSlot>
+ // (slotted) <div #slottedToSecondSlot>
+ // <div #belowSlots> tabindex=1
+ // <div #outside>
+ // First focusable = #aboveSlots
+ host.focus();
+ assert_equals(shadowRoot.activeElement, aboveSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus & tabindex=0, #aboveSlots with tabindex=0 and #belowSlots with tabindex=1");
+
+test(() => {
+ resetTabIndexAndFocus();
+ setTabIndex([host, slottedToFirstSlot, slottedToSecondSlot, belowSlots], 0);
+ // Structure:
+ // <div #host> (delegatesFocus=true) tabindex=0
+ // #shadowRoot
+ // <div #aboveSlots>
+ // <slot #firstSlot>
+ // (slotted) <div #slottedToFirstSlot> tabindex=0
+ // <slot #secondSlot>
+ // (slotted) <div #slottedToSecondSlot> tabindex=0
+ // <div #belowSlots> tabindex=0
+ // <div #outside>
+ // First focusable = #slottedToFirstSlot
+ host.focus();
+ assert_equals(shadowRoot.activeElement, belowSlots);
+ assert_equals(document.activeElement, host);
+}, "focus() on host with delegatesFocus & tabindex=0, #slottedToFirstSlot, #slottedToSecondSlot, #belowSlots with tabindex=0");
+
+test(() => {
+ resetTabIndexAndFocus();
+ setTabIndex([aboveSlots, belowSlots], 0);
+ belowSlots.focus();
+ host.focus();
+ assert_equals(shadowRoot.activeElement, belowSlots);
+}, "focus() on host with delegatesFocus and already-focused non-first shadow descendant");
+
+function createNestedHosts(innerDelegatesFocus) {
+ // Structure:
+ // <div> outerHost
+ // <input> outerLightChild
+ // #shadowRoot outerShadow delegatesFocus=true
+ // <span> innerHost
+ // #shadowRoot inneShadow delegatesFocus=true/false
+ // <input> innerShadowChild
+ // <input> outerShadowChild
+ const outerHost = document.createElement('div');
+ const outerLightChild = document.createElement('input');
+ outerHost.appendChild(outerLightChild);
+ const innerHost = document.createElement('span');
+ const outerShadow = outerHost.attachShadow({mode: 'closed', delegatesFocus:true});
+ outerShadow.appendChild(innerHost);
+ const outerShadowChild = document.createElement('input');
+ outerShadow.appendChild(outerShadowChild);
+
+ const innerShadow = innerHost.attachShadow({mode: 'closed', delegatesFocus:innerDelegatesFocus});
+ const innerShadowChild = document.createElement('input');
+ innerShadow.appendChild(innerShadowChild);
+
+ document.body.insertBefore(outerHost, document.body.firstChild);
+ return {outerHost: outerHost,
+ outerLightChild: outerLightChild,
+ outerShadow: outerShadow,
+ outerShadowChild: outerShadowChild,
+ innerHost: innerHost,
+ innerShadow: innerShadow,
+ innerShadowChild: innerShadowChild};
+}
+
+test(() => {
+ const dom = createNestedHosts(false);
+ dom.outerHost.focus();
+ assert_equals(document.activeElement, dom.outerHost);
+ assert_equals(dom.outerShadow.activeElement, dom.outerShadowChild);
+}, 'focus() on host with delegatesFocus with another host with no delegatesFocus and a focusable child');
+
+test(() => {
+ const dom = createNestedHosts(true);
+ dom.outerHost.focus();
+ assert_equals(document.activeElement, dom.outerHost);
+ assert_equals(dom.outerShadow.activeElement, dom.innerHost);
+ assert_equals(dom.innerShadow.activeElement, dom.innerShadowChild);
+}, 'focus() on host with delegatesFocus with another host with delegatesFocus and a focusable child');
+
+test(() => {
+ // Structure:
+ // <div> host
+ // #shadowRoot root delegatesFocus=true
+ // <slot>
+ // (slotted) <div>
+ // <input>
+ // <input #firstFocusable>
+ const host = document.createElement("div");
+ const slotted = document.createElement("div");
+ slotted.appendChild(document.createElement("input"));
+ host.appendChild(slotted);
+
+ const root = host.attachShadow({mode: "open", delegatesFocus: true});
+
+ const firstFocusable = document.createElement("input");
+ root.innerHTML = "<slot>";
+ root.appendChild(firstFocusable);
+
+ document.body.appendChild(host);
+
+ host.focus();
+ assert_equals(document.activeElement, host);
+ assert_equals(root.activeElement, firstFocusable);
+}, "focus() on host with delegatesFocus and slotted focusable children");
+</script>
+