<!DOCTYPE html>
<meta charset="utf-8">
<title>HTML Test: click 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="slotted">slotted</div>
</div>
<div id="outside">outside</div>
</body>

<script>
const host = document.getElementById("host");
const slotted = document.getElementById("slotted");

const shadowRoot = host.attachShadow({ mode: "open", delegatesFocus: true });
const aboveSlot = document.createElement("div");
aboveSlot.innerText = "aboveSlot";
const slot = document.createElement("slot");
shadowRoot.appendChild(aboveSlot);
shadowRoot.appendChild(slot);

const elementsInFlatTreeOrder = [host, aboveSlot, slot, slotted, outside];

// Final structure:
// <div #host> (delegatesFocus=true)
//    #shadowRoot
//      <div #aboveSlot>
//      <slot #slot>
//        (slotted) <div #slotted>
// <div #outside>

function setAllTabIndex(value) {
  setTabIndex(elementsInFlatTreeOrder, value);
}

function removeAllTabIndex() {
  removeTabIndex(elementsInFlatTreeOrder);
}

function resetTabIndexAndFocus() {
  removeAllTabIndex();
  resetFocus(document);
  resetFocus(shadowRoot);
}

test(() => {
  resetTabIndexAndFocus();
  setAllTabIndex(0);
  host.click();
  assert_equals(shadowRoot.activeElement, null);
  assert_equals(document.activeElement, document.body);
}, "call click() on host with delegatesFocus, all tabindex=0");

test(() => {
  resetTabIndexAndFocus();
  setAllTabIndex(0);
  slotted.click();
  assert_equals(shadowRoot.activeElement, null);
  assert_equals(document.activeElement, document.body);
}, "call click() on slotted element in delegatesFocus shadow tree, all tabindex=0");

function createNestedHosts(outerDelegatesFocus, innerDelegatesFocus) {
  // Structure:
  // <div> outerHost
  //   <input> outerLightChild
  //   #shadowRoot outerShadow delegatesFocus=true
  //     <div> spacer
  //     <span> innerHost
  //       #shadowRoot innerShadow 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:outerDelegatesFocus});

  const spacer = document.createElement("div");
  spacer.style = "height: 1000px;";
  outerShadow.appendChild(spacer);

  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};
}

promise_test(async function() {
  const dom = createNestedHosts(true, true);
  await test_driver.click(dom.outerHost);
  assert_equals(document.activeElement, dom.outerHost);
  assert_equals(dom.outerShadow.activeElement, dom.innerHost);
  assert_equals(dom.innerShadow.activeElement, dom.innerShadowChild);
}, "click on the host with delegatesFocus with another host with delegatesFocus and a focusable child");

promise_test(async function() {
  const dom = createNestedHosts(true, false);
  await test_driver.click(dom.outerHost);
  assert_equals(document.activeElement, dom.outerHost);
  assert_equals(dom.outerShadow.activeElement, dom.outerShadowChild);
  assert_equals(dom.innerShadow.activeElement, null);
}, "click on the host with delegatesFocus with another host with no delegatesFocus and a focusable child");

promise_test(async function() {
  const dom = createNestedHosts(false, true);
  await test_driver.click(dom.outerHost);
  assert_equals(document.activeElement, document.body);
  assert_equals(dom.outerShadow.activeElement, null);
  assert_equals(dom.innerShadow.activeElement, null);
}, "click on the host with no delegatesFocus with another host with delegatesFocus and a focusable child");

promise_test(async function() {
  const dom = createNestedHosts(false, false);
  await test_driver.click(dom.outerHost);
  assert_equals(document.activeElement, document.body);
  assert_equals(dom.outerShadow.activeElement, null);
  assert_equals(dom.innerShadow.activeElement, null);
}, "click on the host with no delegatesFocus with another host with no delegatesFocus and a focusable child");

</script>
