diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /testing/web-platform/tests/shadow-dom/focus/focus-method-delegatesFocus.html | |
parent | Initial commit. (diff) | |
download | thunderbird-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.html | 312 |
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> + |