tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

focus-selector-delegatesFocus.html (4031B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <meta charset="utf-8" />
      5  <title>CSS Test (Selectors): :focus behavior with shadow hosts & delegatesFocus </title>
      6  <link rel="author" title="Rakina Zata Amni" href="rakina@chromium.org" />
      7  <link rel="help" href="https://html.spec.whatwg.org/multipage/semantics-other.html#selector-focus" />
      8  <script src="/resources/testharness.js"></script>
      9  <script src="/resources/testharnessreport.js"></script>
     10  <script src="resources/shadow-utils.js"></script>
     11 </head>
     12 
     13 <body>
     14 <input>
     15 
     16 <script>
     17 function createFocusableDiv() {
     18  const div = document.createElement("div");
     19  div.innerText = "foo";
     20  div.tabIndex = 0;
     21  return div;
     22 }
     23 
     24 function createShadowHost(delegatesFocus, container) {
     25  const host = document.createElement("div");
     26  host.attachShadow({ mode: "open", delegatesFocus: delegatesFocus });
     27  container.appendChild(host);
     28  return host;
     29 }
     30 
     31 const delegatesFocusValues = [true, false];
     32 
     33 for (const delegatesFocus of delegatesFocusValues) {
     34  test(() => {
     35    resetFocus();
     36    const host = createShadowHost(delegatesFocus, document.body);
     37    const shadowChild = createFocusableDiv();
     38    host.shadowRoot.appendChild(shadowChild);
     39 
     40    shadowChild.focus();
     41    assert_true(shadowChild.matches(":focus"), "element in shadow tree matches :focus");
     42    assert_true(host.matches(":focus"), "host matches :focus");
     43  }, `:focus applies to host with delegatesFocus=${delegatesFocus} when the shadow root's descendant has focus`);
     44 
     45  test(() => {
     46    resetFocus();
     47    const host = createShadowHost(delegatesFocus, document.body);
     48    const slotted = createFocusableDiv();
     49    host.shadowRoot.appendChild(document.createElement("slot"));
     50    host.appendChild(slotted);
     51 
     52    slotted.focus();
     53    assert_true(slotted.matches(":focus"), "slotted element matches :focus");
     54    assert_false(host.matches(":focus"), "host matches :focus");
     55  }, `:focus does not apply to host with delegatesFocus=${delegatesFocus} when slotted element has focus`);
     56 
     57  for (const nestedDelegatesFocus of delegatesFocusValues) {
     58    test(() => {
     59      resetFocus();
     60      const host = createShadowHost(delegatesFocus, document.body);
     61      const nestedHost = createShadowHost(nestedDelegatesFocus, host.shadowRoot);
     62      const nestedShadowChild = createFocusableDiv();
     63      nestedHost.shadowRoot.appendChild(nestedShadowChild);
     64      nestedShadowChild.focus();
     65      assert_true(nestedShadowChild.matches(":focus"), "element in nested shadow tree matches :focus");
     66      assert_true(nestedHost.matches(":focus"), "host of nested shadow tree matches focus");
     67      assert_true(host.matches(":focus"), "topmost host matches focus");
     68    }, `:focus applies to host with delegatesFocus=${delegatesFocus} when an element in a nested shadow tree with delegatesFocus=${nestedDelegatesFocus} is focused`);
     69 
     70    test(() => {
     71      resetFocus();
     72      const host = createShadowHost(delegatesFocus, document.body);
     73      const nestedHost = createShadowHost(nestedDelegatesFocus, host.shadowRoot);
     74      const nestedShadowChild = createFocusableDiv();
     75      nestedHost.shadowRoot.appendChild(nestedShadowChild);
     76      // All nested shadow hosts should has :focus applied
     77      nestedShadowChild.focus();
     78 
     79      const elementOutsideOfShadowDOM = document.querySelector("input");
     80      // Move the focus to an element which is outside of the nested
     81      // shadow DOM trees
     82      elementOutsideOfShadowDOM.focus();
     83 
     84      assert_false(nestedShadowChild.matches(":focus"), "element in nested shadow tree doesn't matche :focus");
     85      assert_false(nestedHost.matches(":focus"), "host of nested shadow tree doesn't match focus");
     86      assert_false(host.matches(":focus"), "topmost host matches focus");
     87      assert_true(elementOutsideOfShadowDOM.matches(":focus"), "The element outside of shadow dom matches :focus");
     88    }, `:focus should be removed from hosts with delegatesFocus=${delegatesFocus} when none of the elements in a nested shadow tree with delegatesFocus=${nestedDelegatesFocus} is focused`);
     89  }
     90 }
     91 </script>
     92 </body>