tor-browser

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

element-internals-aria-element-reflection.html (12941B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <meta charset="utf-8" />
      5  <title>Element Reflection for aria-activedescendant and aria-errormessage on ElementInternals</title>
      6  <link rel=help href="https://whatpr.org/html/3917/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:element">
      7  <link rel="author" title="Alice Boxhall" href="alice@igalia.com">
      8  <script src="/resources/testdriver.js"></script>
      9  <script src="/resources/testdriver-vendor.js"></script>
     10  <script src="/resources/testdriver-actions.js"></script>
     11  <script src="/resources/testharness.js"></script>
     12  <script src="/resources/testharnessreport.js"></script>
     13 </head>
     14 
     15 <body>
     16  <script>
     17    class CustomElement extends HTMLElement {
     18      constructor() {
     19        super();
     20        this.i = this.attachInternals();
     21      }
     22    }
     23    customElements.define('custom-element', CustomElement);
     24  </script>
     25 
     26  <custom-element id="custom1"></custom-element>
     27 
     28  <div id="activedescendant">Active descendant</div>
     29  <div id="controls">Controls</div>
     30  <div id="describedby">Described by</div>
     31  <div id="details">Details</div>
     32  <div id="errormessage">Error message</div>
     33  <div id="flowto">Flow to</div>
     34  <div id="labelledby">Labelled by</div>
     35  <div id="owns">Owns</div>
     36 
     37  <div id="labelledby_content">Labelled by from content attribute</div>
     38  <div id="labelledby_element">Labelled by from IDL attribute</div>
     39 
     40  <div id="shadowhost">
     41    <template shadowrootmode="open">
     42      <div id="labelledby_element_shadow">Invalid labelled by in shadow root</div>
     43    </template>
     44  </div>
     45 
     46  <script>
     47    const element_properties = [
     48      ['ariaActiveDescendantElement', 'activedescendant']];
     49    const array_properties = [
     50      ['ariaControlsElements', 'controls'],
     51      ['ariaDescribedByElements', 'describedby'],
     52      ['ariaDetailsElements', 'details'],
     53      ['ariaErrorMessageElements', 'errormessage'],
     54      ['ariaFlowToElements', 'flowto'],
     55      ['ariaLabelledByElements', 'labelledby'],
     56      ['ariaOwnsElements', 'owns']];
     57 
     58    test(t => {
     59      const custom = document.getElementById('custom1');
     60      for (const [property, id] of element_properties) {
     61        assert_equals(custom.i[property], null);
     62      }
     63      for (const [property, id] of array_properties) {
     64        assert_equals(custom.i[property], null);
     65      }
     66    }, "Getting previously-unset ARIA element reflection properties on ElementInternals should return null.");
     67 
     68    test(t => {
     69      const custom = document.getElementById('custom1');
     70      for (const [property, id] of element_properties) {
     71        const related = document.getElementById(id);
     72        custom.i[property] = related;
     73        assert_equals(custom.i[property], related);
     74      }
     75      for (const [property, id] of array_properties) {
     76        const related = document.getElementById(id);
     77        custom.i[property] = [related];
     78        assert_array_equals(custom.i[property], [related]);
     79      }
     80    }, "Getting ARIA element reflection properties on ElementInternals should return the value that was set.");
     81 
     82    test(t => {
     83      const custom = document.getElementById('custom1');
     84      for (const [property, id] of array_properties) {
     85        custom.i[property] = [];
     86        assert_array_equals(custom.i[property], []);
     87      }
     88    }, "Setting ARIA element reflection properties to an empty array should work as expected.");
     89 
     90    test(t => {
     91      const custom = document.getElementById('custom1');
     92      for (const [property, id] of element_properties) {
     93        const related = document.getElementById(id);
     94        custom.i[property] = related;
     95        assert_equals(custom.i[property], related);
     96 
     97        custom.i[property] = null;
     98        assert_equals(custom.i[property], null);
     99      }
    100      for (const [property, id] of array_properties) {
    101        const related = document.getElementById(id);
    102        custom.i[property] = [related];
    103        assert_array_equals(custom.i[property], [related]);
    104 
    105        custom.i[property] = null;
    106        assert_equals(custom.i[property], null);
    107      }
    108    }, "Setting ARIA element reflection properties on ElementInternals to null should delete any previous value, and not crash");
    109 
    110    promise_test(async t => {
    111      const custom = document.getElementById('custom1');
    112      custom.i.ariaLabelledByElements = null;
    113      const label_before_labelledby_set = await test_driver.get_computed_label(custom);
    114      assert_equals(label_before_labelledby_set, "", "Before ariaLabelledByElements is set, accessible label should be empty.");
    115 
    116      const labelledBy = document.getElementById('labelledby');
    117      custom.i.ariaLabelledByElements = [labelledBy];
    118      const label_after_labelledby_set = await test_driver.get_computed_label(custom);
    119      assert_equals(label_after_labelledby_set, "Labelled by", "After ariaLabelledByElements is set, accessible label should be 'Labelled by'");
    120    }, "Setting ariaLabelledByElements on ElementInternals should change the accessible name of the custom element")
    121 
    122    promise_test(async t => {
    123      const custom = document.getElementById('custom1');
    124      custom.i.ariaLabelledByElements = null;
    125      const label_before_labelledby_set = await test_driver.get_computed_label(custom);
    126      assert_equals(label_before_labelledby_set, "", "Before ariaLabelledByElements is set, accessible label should be empty.");
    127 
    128      const labelledBy = document.getElementById('labelledby');
    129      custom.i.ariaLabelledByElements = [labelledBy];
    130      const label_after_internals_labelledby_set = await test_driver.get_computed_label(custom);
    131      assert_equals(label_after_internals_labelledby_set, "Labelled by", "After ariaLabelledByElements is set, accessible label should be 'Labelled by'");
    132 
    133      custom.setAttribute('aria-labelledby', 'labelledby_content');
    134      const label_after_content_labelledby_set = await test_driver.get_computed_label(custom);
    135      assert_equals(label_after_content_labelledby_set, "Labelled by from content attribute", "aria-labelledby content attribute supersedes ariaLabelledByElements on internals");
    136 
    137      const labelledby_element = document.getElementById('labelledby_element');
    138      custom.ariaLabelledByElements = [labelledby_element];
    139      const label_after_idl_arialabelledbyelements_set = await test_driver.get_computed_label(custom);
    140      assert_equals(label_after_idl_arialabelledbyelements_set, "Labelled by from IDL attribute", "ariaLabelledByElements on element supersedes ariaLabelledByElements on internals");
    141 
    142      custom.setAttribute('aria-labelledby', 'bad_id');
    143      const label_after_content_labelledby_set_to_bad_id = await test_driver.get_computed_label(custom);
    144      assert_equals(label_after_content_labelledby_set_to_bad_id, "", "aria-labelledby content attribute supersedes ariaLabelledByElements on internals even when invalid");
    145 
    146      const shadowhost = document.getElementById('shadowhost');
    147      const labelledby_element_invalid = shadowhost.shadowRoot.getElementById('labelledby_element_shadow');
    148      custom.ariaLabelledByElements = [labelledby_element_invalid];
    149      const label_after_idl_arialabelledbyelements_set_to_invalid_element = await test_driver.get_computed_label(custom);
    150      assert_equals(label_after_idl_arialabelledbyelements_set_to_invalid_element, "", "ariaLabelledByElements on element supersedes ariaLabelledByElements on internals even when invalid");
    151    }, "Setting aria-labelledby or ariaLabelledByElements on the custom element should supersede the value of ariaLabelledByElements on ElementInternals");
    152  </script>
    153 
    154  <custom-element id="cachingInvariantMain"></custom-element>
    155  <div id="cachingInvariantElement1"></div>
    156  <div id="cachingInvariantElement2"></div>
    157  <div id="cachingInvariantElement3"></div>
    158  <div id="cachingInvariantElement4"></div>
    159  <div id="cachingInvariantElement5"></div>
    160 
    161  <script>
    162    test(function(t) {
    163      cachingInvariantMain.i.ariaControlsElements = [cachingInvariantElement1, cachingInvariantElement2];
    164      cachingInvariantMain.i.ariaDescribedByElements = [cachingInvariantElement3, cachingInvariantElement4];
    165      cachingInvariantMain.i.ariaDetailsElements = [cachingInvariantElement5];
    166      cachingInvariantMain.i.ariaFlowToElements = [cachingInvariantElement1, cachingInvariantElement3];
    167      cachingInvariantMain.i.ariaLabelledByElements = [cachingInvariantElement2, cachingInvariantElement4];
    168      cachingInvariantMain.i.ariaOwnsElements = [cachingInvariantElement1, cachingInvariantElement2, cachingInvariantElement3];
    169 
    170      let ariaControlsElementsArray = cachingInvariantMain.i.ariaControlsElements;
    171      let ariaDescribedByElementsArray = cachingInvariantMain.i.ariaDescribedByElements;
    172      let ariaDetailsElementsArray = cachingInvariantMain.i.ariaDetailsElements;
    173      let ariaFlowToElementsArray = cachingInvariantMain.i.ariaFlowToElements;
    174      let ariaLabelledByElementsArray = cachingInvariantMain.i.ariaLabelledByElements;
    175      let ariaOwnsElementsArray = cachingInvariantMain.i.ariaOwnsElements;
    176 
    177      assert_equals(ariaControlsElementsArray, cachingInvariantMain.i.ariaControlsElements, "Caching invariant for ariaControlsElements");
    178      assert_equals(ariaDescribedByElementsArray, cachingInvariantMain.i.ariaDescribedByElements, "Caching invariant for ariaDescribedByElements");
    179      assert_equals(ariaDetailsElementsArray, cachingInvariantMain.i.ariaDetailsElements, "Caching invariant for ariaDetailsElements");
    180      assert_equals(ariaFlowToElementsArray, cachingInvariantMain.i.ariaFlowToElements, "Caching invariant for ariaFlowToElements");
    181      assert_equals(ariaLabelledByElementsArray, cachingInvariantMain.i.ariaLabelledByElements, "Caching invariant for ariaLabelledByElements");
    182      assert_equals(ariaOwnsElementsArray, cachingInvariantMain.i.ariaOwnsElements, "Caching invariant for ariaOwnsElements");
    183 
    184      // Ensure that cached values don't become stale
    185      cachingInvariantMain.i.ariaControlsElements = [cachingInvariantElement4, cachingInvariantElement5];
    186      cachingInvariantMain.i.ariaDescribedByElements = [cachingInvariantElement1, cachingInvariantElement2];
    187      cachingInvariantMain.i.ariaDetailsElements = [cachingInvariantElement3];
    188      cachingInvariantMain.i.ariaFlowToElements = [cachingInvariantElement4, cachingInvariantElement5];
    189      cachingInvariantMain.i.ariaLabelledByElements = [cachingInvariantElement1, cachingInvariantElement2];
    190      cachingInvariantMain.i.ariaOwnsElements = [cachingInvariantElement3, cachingInvariantElement4, cachingInvariantElement1];
    191 
    192      ariaControlsElementsArray = cachingInvariantMain.i.ariaControlsElements;
    193      ariaDescribedByElementsArray = cachingInvariantMain.i.ariaDescribedByElements;
    194      ariaDetailsElementsArray = cachingInvariantMain.i.ariaDetailsElements;
    195      ariaFlowToElementsArray = cachingInvariantMain.i.ariaFlowToElements;
    196      ariaLabelledByElementsArray = cachingInvariantMain.i.ariaLabelledByElements;
    197      ariaOwnsElementsArray = cachingInvariantMain.i.ariaOwnsElements;
    198 
    199      assert_equals(ariaControlsElementsArray, cachingInvariantMain.i.ariaControlsElements, "Caching invariant for ariaControlsElements");
    200      assert_equals(ariaDescribedByElementsArray, cachingInvariantMain.i.ariaDescribedByElements, "Caching invariant for ariaDescribedByElements");
    201      assert_equals(ariaDetailsElementsArray, cachingInvariantMain.i.ariaDetailsElements, "Caching invariant for ariaDetailsElements");
    202      assert_equals(ariaFlowToElementsArray, cachingInvariantMain.i.ariaFlowToElements, "Caching invariant for ariaFlowToElements");
    203      assert_equals(ariaLabelledByElementsArray, cachingInvariantMain.i.ariaLabelledByElements, "Caching invariant for ariaLabelledByElements");
    204      assert_equals(ariaOwnsElementsArray, cachingInvariantMain.i.ariaOwnsElements, "Caching invariant for ariaOwnsElements");
    205 
    206    }, "Caching invariant different attributes.");
    207  </script>
    208 
    209  <custom-element id="cachingInvariantMain1"></custom-element>
    210  <custom-element id="cachingInvariantMain2"></custom-element>
    211 
    212  <script>
    213    test(function(t) {
    214      cachingInvariantMain1.i.ariaDescribedByElements = [cachingInvariantElement1, cachingInvariantElement2];
    215      cachingInvariantMain2.i.ariaDescribedByElements = [cachingInvariantElement1, cachingInvariantElement2];
    216 
    217      let ariaDescribedByElementsArray1 = cachingInvariantMain1.i.ariaDescribedByElements;
    218      let ariaDescribedByElementsArray2 = cachingInvariantMain2.i.ariaDescribedByElements;
    219 
    220      assert_equals(ariaDescribedByElementsArray1, cachingInvariantMain1.i.ariaDescribedByElements, "Caching invariant for ariaDescribedByElements in one elemnt");
    221      assert_equals(ariaDescribedByElementsArray2, cachingInvariantMain2.i.ariaDescribedByElements, "Caching invariant for ariaDescribedByElements in onother elemnt");
    222      assert_not_equals(cachingInvariantMain1.i.ariaDescribedByElements, cachingInvariantMain2.i.ariaDescribedByElements);
    223    }, "Caching invariant different elements.");
    224  </script>
    225 
    226 </body>
    227 </html>