tor-browser

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

test_ariaowns.html (25639B)


      1 <!DOCTYPE html>
      2 <html>
      3 
      4 <head>
      5  <title>@aria-owns attribute testing</title>
      6 
      7  <link rel="stylesheet" type="text/css"
      8        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
      9 
     10  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
     11 
     12  <script type="application/javascript"
     13          src="../common.js"></script>
     14  <script type="application/javascript"
     15          src="../role.js"></script>
     16  <script type="application/javascript"
     17          src="../events.js"></script>
     18 
     19  <script type="application/javascript">
     20 
     21    // //////////////////////////////////////////////////////////////////////////
     22    // Invokers
     23    // //////////////////////////////////////////////////////////////////////////
     24 
     25    function changeARIAOwns() {
     26      this.eventSeq = [
     27        new invokerChecker(EVENT_HIDE, getNode("t1_button")),
     28        // no hide for t1_subdiv because it is contained by hidden t1_checkbox
     29        new invokerChecker(EVENT_HIDE, getNode("t1_checkbox")),
     30        new invokerChecker(EVENT_SHOW, getNode("t1_checkbox")),
     31        new invokerChecker(EVENT_SHOW, getNode("t1_button")),
     32        new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
     33        new invokerChecker(EVENT_REORDER, getNode("t1_container")),
     34      ];
     35 
     36      this.invoke = function setARIAOwns_invoke() {
     37        // children are swapped by ARIA owns
     38        var tree =
     39          { SECTION: [
     40              { CHECKBUTTON: [
     41                { SECTION: [] },
     42              ] },
     43              { PUSHBUTTON: [ ] },
     44          ] };
     45        testAccessibleTree("t1_container", tree);
     46 
     47        getNode("t1_container").
     48          setAttribute("aria-owns", "t1_button t1_subdiv");
     49      };
     50 
     51      this.finalCheck = function setARIAOwns_finalCheck() {
     52        // children are swapped again, button and subdiv are appended to
     53        // the children.
     54        var tree =
     55          { SECTION: [
     56              { CHECKBUTTON: [ ] }, // checkbox, native order
     57              { PUSHBUTTON: [ ] }, // button, rearranged by ARIA own
     58              { SECTION: [ ] }, // subdiv from the subtree, ARIA owned
     59          ] };
     60        testAccessibleTree("t1_container", tree);
     61      };
     62 
     63      this.getID = function setARIAOwns_getID() {
     64        return "Change @aria-owns attribute";
     65      };
     66    }
     67 
     68    function removeARIAOwns() {
     69      this.eventSeq = [
     70        new invokerChecker(EVENT_HIDE, getNode("t1_button")),
     71        new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
     72        new orderChecker(),
     73        new asyncInvokerChecker(EVENT_SHOW, getNode("t1_button")),
     74        new asyncInvokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
     75        new orderChecker(),
     76        new invokerChecker(EVENT_REORDER, getNode("t1_container")),
     77        new unexpectedInvokerChecker(EVENT_REORDER, getNode("t1_checkbox")),
     78      ];
     79 
     80      this.invoke = function removeARIAOwns_invoke() {
     81        getNode("t1_container").removeAttribute("aria-owns");
     82      };
     83 
     84      this.finalCheck = function removeARIAOwns_finalCheck() {
     85        // children follow the DOM order
     86        var tree =
     87          { SECTION: [
     88              { PUSHBUTTON: [ ] },
     89              { CHECKBUTTON: [
     90                  { SECTION: [] },
     91              ] },
     92          ] };
     93        testAccessibleTree("t1_container", tree);
     94      };
     95 
     96      this.getID = function removeARIAOwns_getID() {
     97        return "Remove @aria-owns attribute";
     98      };
     99    }
    100 
    101    function setARIAOwns() {
    102      this.eventSeq = [
    103        new invokerChecker(EVENT_HIDE, getNode("t1_button")),
    104        new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
    105        new invokerChecker(EVENT_SHOW, getNode("t1_button")),
    106        new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
    107        new invokerChecker(EVENT_REORDER, getNode("t1_container")),
    108      ];
    109 
    110      this.invoke = function setARIAOwns_invoke() {
    111        getNode("t1_container").
    112          setAttribute("aria-owns", "t1_button t1_subdiv");
    113      };
    114 
    115      this.finalCheck = function setARIAOwns_finalCheck() {
    116        // children are swapped again, button and subdiv are appended to
    117        // the children.
    118        var tree =
    119          { SECTION: [
    120              { CHECKBUTTON: [ ] }, // checkbox
    121              { PUSHBUTTON: [ ] }, // button, rearranged by ARIA own
    122              { SECTION: [ ] }, // subdiv from the subtree, ARIA owned
    123          ] };
    124        testAccessibleTree("t1_container", tree);
    125      };
    126 
    127      this.getID = function setARIAOwns_getID() {
    128        return "Set @aria-owns attribute";
    129      };
    130    }
    131 
    132    function addIdToARIAOwns() {
    133      this.eventSeq = [
    134        new invokerChecker(EVENT_HIDE, getNode("t1_group")),
    135        new invokerChecker(EVENT_SHOW, getNode("t1_group")),
    136        new invokerChecker(EVENT_REORDER, document),
    137      ];
    138 
    139      this.invoke = function addIdToARIAOwns_invoke() {
    140        getNode("t1_container").
    141          setAttribute("aria-owns", "t1_button t1_subdiv t1_group");
    142      };
    143 
    144      this.finalCheck = function addIdToARIAOwns_finalCheck() {
    145        // children are swapped again, button and subdiv are appended to
    146        // the children.
    147        var tree =
    148          { SECTION: [
    149              { CHECKBUTTON: [ ] }, // t1_checkbox
    150              { PUSHBUTTON: [ ] }, // button, t1_button
    151              { SECTION: [ ] }, // subdiv from the subtree, t1_subdiv
    152              { GROUPING: [ ] }, // group from outside, t1_group
    153          ] };
    154        testAccessibleTree("t1_container", tree);
    155      };
    156 
    157      this.getID = function addIdToARIAOwns_getID() {
    158        return "Add id to @aria-owns attribute value";
    159      };
    160    }
    161 
    162    function appendEl() {
    163      this.eventSeq = [
    164        new invokerChecker(EVENT_SHOW, getNode, "t1_child3"),
    165        new invokerChecker(EVENT_REORDER, getNode("t1_container")),
    166      ];
    167 
    168      this.invoke = function appendEl_invoke() {
    169        var div = document.createElement("div");
    170        div.setAttribute("id", "t1_child3");
    171        div.setAttribute("role", "radio");
    172        getNode("t1_container").appendChild(div);
    173      };
    174 
    175      this.finalCheck = function appendEl_finalCheck() {
    176        // children are invalidated, they includes aria-owns swapped kids and
    177        // newly inserted child.
    178        var tree =
    179          { SECTION: [
    180              { CHECKBUTTON: [ ] }, // existing explicit, t1_checkbox
    181              { RADIOBUTTON: [ ] }, // new explicit, t1_child3
    182              { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
    183              { SECTION: [ ] }, // ARIA owned, t1_subdiv
    184              { GROUPING: [ ] }, // ARIA owned, t1_group
    185          ] };
    186        testAccessibleTree("t1_container", tree);
    187      };
    188 
    189      this.getID = function appendEl_getID() {
    190        return "Append child under @aria-owns element";
    191      };
    192    }
    193 
    194    function removeEl() {
    195      this.eventSeq = [
    196        new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
    197        new invokerChecker(EVENT_REORDER, getNode("t1_container")),
    198      ];
    199 
    200      this.invoke = function removeEl_invoke() {
    201        // remove a container of t1_subdiv
    202        getNode("t1_span").remove();
    203      };
    204 
    205      this.finalCheck = function removeEl_finalCheck() {
    206        // subdiv should go away
    207        var tree =
    208          { SECTION: [
    209              { CHECKBUTTON: [ ] }, // explicit, t1_checkbox
    210              { RADIOBUTTON: [ ] }, // explicit, t1_child3
    211              { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
    212              { GROUPING: [ ] }, // ARIA owned, t1_group
    213          ] };
    214        testAccessibleTree("t1_container", tree);
    215      };
    216 
    217      this.getID = function removeEl_getID() {
    218        return "Remove a container of ARIA owned element";
    219      };
    220    }
    221 
    222    function removeId() {
    223      this.eventSeq = [
    224        new invokerChecker(EVENT_HIDE, getNode("t1_group")),
    225        new invokerChecker(EVENT_SHOW, getNode("t1_group")),
    226        new invokerChecker(EVENT_REORDER, document),
    227      ];
    228 
    229      this.invoke = function removeId_invoke() {
    230        getNode("t1_group").removeAttribute("id");
    231      };
    232 
    233      this.finalCheck = function removeId_finalCheck() {
    234        var tree =
    235          { SECTION: [
    236              { CHECKBUTTON: [ ] },
    237              { RADIOBUTTON: [ ] },
    238              { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
    239          ] };
    240        testAccessibleTree("t1_container", tree);
    241      };
    242 
    243      this.getID = function removeId_getID() {
    244        return "Remove ID from ARIA owned element";
    245      };
    246    }
    247 
    248    function setId() {
    249      this.eventSeq = [
    250        new invokerChecker(EVENT_HIDE, getNode("t1_grouptmp")),
    251        new invokerChecker(EVENT_SHOW, getNode("t1_grouptmp")),
    252        new invokerChecker(EVENT_REORDER, document),
    253      ];
    254 
    255      this.invoke = function setId_invoke() {
    256        getNode("t1_grouptmp").setAttribute("id", "t1_group");
    257      };
    258 
    259      this.finalCheck = function setId_finalCheck() {
    260        var tree =
    261          { SECTION: [
    262              { CHECKBUTTON: [ ] },
    263              { RADIOBUTTON: [ ] },
    264              { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
    265              { GROUPING: [ ] }, // ARIA owned, t1_group, previously t1_grouptmp
    266          ] };
    267        testAccessibleTree("t1_container", tree);
    268      };
    269 
    270      this.getID = function setId_getID() {
    271        return "Set ID that is referred by ARIA owns";
    272      };
    273    }
    274 
    275    /**
    276     * Remove an accessible DOM element containing an element referred by
    277     * ARIA owns.
    278     */
    279    function removeA11eteiner() {
    280      this.eventSeq = [
    281        new invokerChecker(EVENT_REORDER, getNode("t2_container1")),
    282      ];
    283 
    284      this.invoke = function removeA11eteiner_invoke() {
    285        var tree =
    286          { SECTION: [
    287              { CHECKBUTTON: [ ] }, // ARIA owned, 't2_owned'
    288          ] };
    289        testAccessibleTree("t2_container1", tree);
    290 
    291        getNode("t2_container2").removeChild(getNode("t2_container3"));
    292      };
    293 
    294      this.finalCheck = function removeA11eteiner_finalCheck() {
    295        var tree =
    296          { SECTION: [
    297          ] };
    298        testAccessibleTree("t2_container1", tree);
    299      };
    300 
    301      this.getID = function removeA11eteiner_getID() {
    302        return "Remove an accessible DOM element containing an element referred by ARIA owns";
    303      };
    304    }
    305 
    306    /**
    307     * Attempt to steal an element from other ARIA owns element. This should
    308     * not be possible. The only child that will get owned into this
    309     * container is a previously not aria-owned one.
    310     */
    311    function stealFromOtherARIAOwns() {
    312      this.eventSeq = [
    313        new invokerChecker(EVENT_REORDER, getNode("t3_container3")),
    314      ];
    315 
    316      this.invoke = function stealFromOtherARIAOwns_invoke() {
    317        getNode("t3_container3").setAttribute("aria-owns", "t3_child t3_child2");
    318      };
    319 
    320      this.finalCheck = function stealFromOtherARIAOwns_finalCheck() {
    321        var tree =
    322          { SECTION: [
    323            { CHECKBUTTON: [
    324            ] },
    325          ] };
    326        testAccessibleTree("t3_container1", tree);
    327 
    328        tree =
    329          { SECTION: [
    330          ] };
    331        testAccessibleTree("t3_container2", tree);
    332 
    333        tree =
    334          { SECTION: [
    335            { CHECKBUTTON: [
    336            ] },
    337          ] };
    338        testAccessibleTree("t3_container3", tree);
    339      };
    340 
    341      this.getID = function stealFromOtherARIAOwns_getID() {
    342        return "Steal an element from other ARIA owns element";
    343      };
    344    }
    345 
    346    function appendElToRecacheChildren() {
    347      this.eventSeq = [
    348        new invokerChecker(EVENT_REORDER, getNode("t3_container3")),
    349      ];
    350 
    351      this.invoke = function appendElToRecacheChildren_invoke() {
    352        var div = document.createElement("div");
    353        div.setAttribute("role", "radio");
    354        getNode("t3_container3").appendChild(div);
    355      };
    356 
    357      this.finalCheck = function appendElToRecacheChildren_finalCheck() {
    358        var tree =
    359          { SECTION: [
    360          ] };
    361        testAccessibleTree("t3_container2", tree);
    362 
    363        tree =
    364          { SECTION: [
    365            { RADIOBUTTON: [ ] },
    366            { CHECKBUTTON: [ ] }, // ARIA owned
    367          ] };
    368        testAccessibleTree("t3_container3", tree);
    369      };
    370 
    371      this.getID = function appendElToRecacheChildren_getID() {
    372        return "Append a child under @aria-owns element to trigger children recache";
    373      };
    374    }
    375 
    376    function showHiddenElement() {
    377      this.eventSeq = [
    378        new invokerChecker(EVENT_REORDER, getNode("t4_container1")),
    379      ];
    380 
    381      this.invoke = function showHiddenElement_invoke() {
    382        var tree =
    383          { SECTION: [
    384            { RADIOBUTTON: [] },
    385          ] };
    386        testAccessibleTree("t4_container1", tree);
    387 
    388        getNode("t4_child1").style.display = "block";
    389      };
    390 
    391      this.finalCheck = function showHiddenElement_finalCheck() {
    392        var tree =
    393          { SECTION: [
    394            { CHECKBUTTON: [] },
    395            { RADIOBUTTON: [] },
    396          ] };
    397        testAccessibleTree("t4_container1", tree);
    398      };
    399 
    400      this.getID = function showHiddenElement_getID() {
    401        return "Show hidden ARIA owns referred element";
    402      };
    403    }
    404 
    405    function rearrangeARIAOwns(aContainer, aAttr, aIdList, aRoleList) {
    406      this.eventSeq = [];
    407      for (let id of aIdList) {
    408        this.eventSeq.push(new invokerChecker(EVENT_HIDE, getNode(id)));
    409      }
    410 
    411      for (let id of aIdList) {
    412        this.eventSeq.push(new invokerChecker(EVENT_SHOW, getNode(id)));
    413      }
    414      this.eventSeq.push(new invokerChecker(EVENT_REORDER, getNode(aContainer)));
    415 
    416      this.invoke = function rearrangeARIAOwns_invoke() {
    417        getNode(aContainer).setAttribute("aria-owns", aAttr);
    418      };
    419 
    420      this.finalCheck = function rearrangeARIAOwns_finalCheck() {
    421        var tree = { SECTION: [ ] };
    422        for (var role of aRoleList) {
    423          var ch = {};
    424          ch[role] = [];
    425          tree.SECTION.push(ch);
    426        }
    427        testAccessibleTree(aContainer, tree);
    428      };
    429 
    430      this.getID = function rearrangeARIAOwns_getID() {
    431        return `Rearrange @aria-owns attribute to '${aAttr}'`;
    432      };
    433    }
    434 
    435    function removeNotARIAOwnedEl(aContainer, aChild) {
    436      this.eventSeq = [
    437        new invokerChecker(EVENT_REORDER, aContainer),
    438      ];
    439 
    440      this.invoke = function removeNotARIAOwnedEl_invoke() {
    441        var tree = {
    442          SECTION: [
    443            { TEXT_LEAF: [ ] },
    444            { GROUPING: [ ] },
    445          ],
    446        };
    447        testAccessibleTree(aContainer, tree);
    448 
    449        getNode(aContainer).removeChild(getNode(aChild));
    450      };
    451 
    452      this.finalCheck = function removeNotARIAOwnedEl_finalCheck() {
    453        var tree = {
    454          SECTION: [
    455            { GROUPING: [ ] },
    456          ],
    457        };
    458        testAccessibleTree(aContainer, tree);
    459      };
    460 
    461      this.getID = function removeNotARIAOwnedEl_getID() {
    462        return `remove not ARIA owned child`;
    463      };
    464    }
    465 
    466    function setARIAOwnsOnElToRemove(aParent, aChild) {
    467      this.eventSeq = [
    468        new invokerChecker(EVENT_HIDE, getAccessible(aParent)),
    469      ];
    470 
    471      this.invoke = function setARIAOwnsOnElToRemove_invoke() {
    472        getNode(aChild).setAttribute("aria-owns", "no_id");
    473        getNode(aParent).removeChild(getNode(aChild));
    474        getNode(aParent).remove();
    475      };
    476 
    477      this.getID = function setARIAOwnsOnElToRemove_getID() {
    478        return `set ARIA owns on an element, and then remove it, and then remove its parent`;
    479      };
    480    }
    481 
    482    /**
    483     * Set ARIA owns on inaccessible span element that contains
    484     * accessible children. This will move children from the container for
    485     * the span.
    486     */
    487    function test8() {
    488      this.eventSeq = [
    489        new invokerChecker(EVENT_REORDER, "t8_container"),
    490      ];
    491 
    492      this.invoke = function test8_invoke() {
    493        var tree =
    494          { SECTION: [
    495            { PUSHBUTTON: [] },
    496            { ENTRY: [] },
    497            { ENTRY: [] },
    498            { ENTRY: [] },
    499          ] };
    500        testAccessibleTree("t8_container", tree);
    501 
    502        getNode(t8_container).setAttribute("aria-owns", "t8_span t8_button");
    503      };
    504 
    505      this.finalCheck = function test8_finalCheck() {
    506        var tree =
    507          { SECTION: [
    508            { TEXT: [
    509              { ENTRY: [] },
    510              { ENTRY: [] },
    511              { ENTRY: [] },
    512            ] },
    513            { PUSHBUTTON: [] },
    514          ] };
    515        testAccessibleTree("t8_container", tree);
    516      };
    517 
    518      this.getID = function test8_getID() {
    519        return `Set ARIA owns on inaccessible span element that contains accessible children`;
    520      };
    521    }
    522 
    523    function test9_prepare() {
    524      this.eventSeq = [
    525        new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, () => {
    526          return getNode("t9_container").contentDocument;
    527        }),
    528      ];
    529 
    530      this.invoke = () => {
    531        // The \ before the final /script avoids the script from being terminated
    532        // by the html parser.
    533        getNode("t9_container").src = `data:text/html,
    534          <html><body></body>
    535          <script>
    536            let el = document.createElement('div');
    537            el.id = 'container';
    538            el.innerHTML = "<input id='input'>";
    539            document.documentElement.appendChild(el);
    540          <\/script></html>`;
    541      };
    542 
    543      this.finalCheck = () => {
    544        var tree =
    545          { INTERNAL_FRAME: [
    546            { DOCUMENT: [
    547              { SECTION: [
    548                { ENTRY: [] },
    549              ] },
    550            ] },
    551          ] };
    552        testAccessibleTree("t9_container", tree);
    553      };
    554 
    555      this.getID = () => {
    556        return `Set ARIA owns on a document (part1)`;
    557      };
    558    }
    559 
    560    function test9_setARIAOwns() {
    561      this.eventSeq = [
    562        new invokerChecker(EVENT_SHOW, () => {
    563          let doc = getNode("t9_container").contentDocument;
    564          return doc && doc.getElementById("input");
    565        }),
    566      ];
    567 
    568      this.invoke = () => {
    569        let doc = getNode("t9_container").contentDocument;
    570        doc.body.setAttribute("aria-owns", "input");
    571      };
    572 
    573      this.finalCheck = () => {
    574        var tree =
    575          { INTERNAL_FRAME: [
    576            { DOCUMENT: [
    577              { SECTION: [] },
    578              { ENTRY: [] },
    579            ] },
    580          ] };
    581        testAccessibleTree("t9_container", tree);
    582      };
    583 
    584      this.getID = () => {
    585        return `Set ARIA owns on a document (part2)`;
    586      };
    587    }
    588 
    589    function test9_finish() {
    590      this.eventSeq = [
    591        new invokerChecker(EVENT_REORDER, () => {
    592          return getNode("t9_container").contentDocument;
    593        }),
    594      ];
    595 
    596      this.invoke = () => {
    597        // trigger a tree update.
    598        let doc = getNode("t9_container").contentDocument;
    599        doc.body.appendChild(doc.createElement("p"));
    600      };
    601 
    602      this.finalCheck = () => {
    603        var tree =
    604          { INTERNAL_FRAME: [
    605            { DOCUMENT: [
    606              { PARAGRAPH: [] },
    607              { SECTION: [] },
    608              { ENTRY: [] },
    609            ] },
    610          ] };
    611        testAccessibleTree("t9_container", tree);
    612      };
    613 
    614      this.getID = () => {
    615        return `Set ARIA owns on a document (part3)`;
    616      };
    617    }
    618 
    619    /**
    620     * Put ARIA owned child back when ARIA owner removed.
    621     */
    622    function test10_removeARIAOwner() {
    623      this.eventSeq = [
    624        new invokerChecker(EVENT_HIDE, getAccessible("t10_owner")),
    625      ];
    626 
    627      this.invoke = () => {
    628        let tree =
    629          { SECTION: [ // t10_container
    630            { SECTION: [ // t10_owner
    631              { ENTRY: [] }, // t10_child
    632            ] },
    633          ] };
    634        testAccessibleTree("t10_container", tree);
    635 
    636        getNode("t10_owner").remove();
    637      };
    638 
    639      this.getID = () => {
    640        return "Put aria owned child back when aria owner removed";
    641      };
    642    }
    643 
    644    function test10_finishTest() {
    645      this.eventSeq = [
    646        new invokerChecker(EVENT_REORDER, "t10_container"),
    647      ];
    648 
    649      this.invoke = () => {
    650        // trigger a tree update.
    651        getNode("t10_container").append(document.createElement("p"));
    652      };
    653 
    654      this.finalCheck = () => {
    655        let tree =
    656          { SECTION: [ // t10_container
    657            { ENTRY: [] }, // t10_child
    658            { PARAGRAPH: [] },
    659          ] };
    660        testAccessibleTree("t10_container", tree);
    661        todo(false, "Input accessible has be moved back in the tree");
    662      };
    663 
    664      this.getID = () => {
    665        return `Put aria owned child back when aria owner removed (finish test)`;
    666      };
    667    }
    668 
    669    // //////////////////////////////////////////////////////////////////////////
    670    // Test
    671    // //////////////////////////////////////////////////////////////////////////
    672 
    673    // gA11yEventDumpToConsole = true;
    674    // enableLogging("tree,eventTree,verbose"); // debug stuff
    675 
    676    var gQueue = null;
    677 
    678    async function doTest() {
    679      let PromEvents = {};
    680      Services.scriptloader.loadSubScript(
    681      "chrome://mochitests/content/a11y/accessible/tests/mochitest/promisified-events.js",
    682      PromEvents);
    683 
    684      gQueue = new eventQueue();
    685      let queueFinished = new Promise(resolve => {
    686        gQueue.onFinish = function() {
    687          resolve();
    688          return DO_NOT_FINISH_TEST;
    689        };
    690      });
    691 
    692      // test1
    693      gQueue.push(new changeARIAOwns());
    694      gQueue.push(new removeARIAOwns());
    695      gQueue.push(new setARIAOwns());
    696      gQueue.push(new addIdToARIAOwns());
    697      gQueue.push(new appendEl());
    698      gQueue.push(new removeEl());
    699      gQueue.push(new removeId());
    700      gQueue.push(new setId());
    701 
    702      // test2
    703      gQueue.push(new removeA11eteiner());
    704 
    705      // test3
    706      gQueue.push(new stealFromOtherARIAOwns());
    707      gQueue.push(new appendElToRecacheChildren());
    708 
    709      // test4
    710      gQueue.push(new showHiddenElement());
    711 
    712      // test5
    713      gQueue.push(new rearrangeARIAOwns(
    714        "t5_container", "t5_checkbox t5_radio t5_button",
    715        [ "t5_checkbox", "t5_radio", "t5_button" ],
    716        [ "CHECKBUTTON", "RADIOBUTTON", "PUSHBUTTON" ]));
    717      gQueue.push(new rearrangeARIAOwns(
    718        "t5_container", "t5_radio t5_button t5_checkbox",
    719        [ "t5_radio", "t5_button" ],
    720        [ "RADIOBUTTON", "PUSHBUTTON", "CHECKBUTTON" ]));
    721 
    722      gQueue.push(new removeNotARIAOwnedEl("t6_container", "t6_span"));
    723 
    724      gQueue.push(new setARIAOwnsOnElToRemove("t7_parent", "t7_child"));
    725 
    726      gQueue.push(new test8());
    727      gQueue.push(new test9_prepare());
    728      gQueue.push(new test9_setARIAOwns());
    729      gQueue.push(new test9_finish());
    730 
    731      gQueue.push(new test10_removeARIAOwner());
    732      gQueue.push(new test10_finishTest());
    733 
    734      gQueue.invoke();
    735      await queueFinished;
    736 
    737      let owned = document.createElement('div');
    738      owned.id = 't11_child';
    739      owned.textContent = 'owned';
    740      let evtPromise = PromEvents.waitForEvent(EVENT_SHOW, "t11_child");
    741      getNode("t11_container").append(owned);
    742      let evt = await evtPromise;
    743      is(evt.accessible.parent.name, "t11_owner");
    744 
    745      // Test owning an ancestor which isn't created yet.
    746      testAccessibleTree("t12_container", { SECTION: [ // t12_container
    747        { SECTION: [ // t12b
    748          { SECTION: [] }, // t12c
    749        ] },
    750        { SECTION: [] }, // t12d
    751      ] });
    752      // Owning t12a would create a cycle, so we expect it to do nothing.
    753      // We own t12d so we get an event when aria-owns relocation is complete.
    754      evtPromise = PromEvents.waitForEvent(EVENT_SHOW, "t12d");
    755      getNode("t12c").setAttribute("aria-owns", "t12a t12d");
    756      await evtPromise;
    757      testAccessibleTree("t12_container", { SECTION: [ // t12_container
    758        { SECTION: [ // t12b
    759          { SECTION: [ // t12c
    760            { SECTION: [] }, // t12d
    761          ] },
    762        ] },
    763      ] });
    764 
    765      SimpleTest.finish();
    766    }
    767 
    768    SimpleTest.waitForExplicitFinish();
    769    addA11yLoadEvent(doTest);
    770 
    771  </script>
    772 </head>
    773 
    774 <body>
    775 
    776  <p id="display"></p>
    777  <div id="content" style="display: none"></div>
    778  <pre id="test">
    779  </pre>
    780 
    781  <div id="t1_container" aria-owns="t1_checkbox t1_button">
    782    <div role="button" id="t1_button"></div>
    783    <div role="checkbox" id="t1_checkbox">
    784      <span id="t1_span">
    785        <div id="t1_subdiv"></div>
    786      </span>
    787    </div>
    788  </div>
    789  <div id="t1_group" role="group"></div>
    790  <div id="t1_grouptmp" role="group"></div>
    791 
    792  <div id="t2_container1" aria-owns="t2_owned"></div>
    793  <div id="t2_container2">
    794    <div id="t2_container3"><div id="t2_owned" role="checkbox"></div></div>
    795  </div>
    796 
    797  <div id="t3_container1" aria-owns="t3_child"></div>
    798  <div id="t3_child" role="checkbox"></div>
    799  <div id="t3_container2">
    800    <div id="t3_child2" role="checkbox"></div>
    801  </div>
    802  <div id="t3_container3"></div>
    803 
    804  <div id="t4_container1" aria-owns="t4_child1 t4_child2"></div>
    805  <div id="t4_container2">
    806    <div id="t4_child1" style="display:none" role="checkbox"></div>
    807    <div id="t4_child2" role="radio"></div>
    808  </div>
    809 
    810  <div id="t5_container">
    811    <div role="button" id="t5_button"></div>
    812    <div role="checkbox" id="t5_checkbox"></div>
    813    <div role="radio" id="t5_radio"></div>
    814  </div>
    815 
    816  <div id="t6_container" aria-owns="t6_fake">
    817    <span id="t6_span">hey</span>
    818  </div>
    819  <div id="t6_fake" role="group"></div>
    820 
    821  <div id="t7_container">
    822    <div id="t7_parent">
    823      <div id="t7_child"></div>
    824    </div>
    825  </div>
    826 
    827  <div id="t8_container">
    828    <input id="t8_button" type="button"><span id="t8_span"><input><input><input></span>
    829  </div>
    830 
    831  <iframe id="t9_container"></iframe>
    832 
    833  <div id="t10_container">
    834    <div id="t10_owner" aria-owns="t10_child"></div>
    835    <input id="t10_child">
    836  </div>
    837 
    838  <div id="t11_container" aria-label="t11_container">
    839    <div aria-owns="t11_child" aria-label="t11_owner"></div>
    840  </div>
    841 
    842  <div  id="t12_container">
    843    <span id="t12a">
    844      <div id="t12b" aria-owns="t12c"></div>
    845    </span>
    846    <div id="t12c"></div>
    847    <div id="t12d"></div>
    848  </div>
    849 </body>
    850 
    851 </html>