tor-browser

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

browser_popover_and_command.js (13418B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /**
      8 * Test details relations for the popovertarget content attribute.
      9 */
     10 addAccessibleTask(
     11  `
     12 <button id="hide" popovertarget="popover" popovertargetaction="hide">hide</button>
     13 <button id="toggle1" popovertarget="popover">toggle1</button>
     14 <button id="toggle2">toggle2</button>
     15 <button id="toggleSibling">toggleSibling</button>
     16 <div id="popover" popover>popover</div>
     17 <div id="details">details</div>
     18  `,
     19  async function testPopoverContent(browser, docAcc) {
     20    // The popover is hidden, so nothing should be referring to it.
     21    const hide = findAccessibleChildByID(docAcc, "hide");
     22    await testCachedRelation(hide, RELATION_DETAILS, []);
     23    const toggle1 = findAccessibleChildByID(docAcc, "toggle1");
     24    await testCachedRelation(toggle1, RELATION_DETAILS, []);
     25    const toggle2 = findAccessibleChildByID(docAcc, "toggle2");
     26    await testCachedRelation(toggle2, RELATION_DETAILS, []);
     27    const toggleSibling = findAccessibleChildByID(docAcc, "toggleSibling");
     28    await testCachedRelation(toggleSibling, RELATION_DETAILS, []);
     29 
     30    info("Showing popover");
     31    let shown = waitForEvent(EVENT_SHOW, "popover");
     32    toggle1.doAction(0);
     33    const popover = (await shown).accessible;
     34    await testCachedRelation(toggle1, RELATION_DETAILS, popover);
     35    // toggle2 shouldn't have a details relation because it doesn't have a
     36    // popovertarget.
     37    await testCachedRelation(toggle2, RELATION_DETAILS, []);
     38    // hide shouldn't have a details relation because its action is hide.
     39    await testCachedRelation(hide, RELATION_DETAILS, []);
     40    // toggleSibling shouldn't have a details relation because it is a sibling
     41    // of the popover.
     42    await testCachedRelation(toggleSibling, RELATION_DETAILS, []);
     43    await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1);
     44 
     45    is(
     46      toggle1.attributes.getStringProperty("details-from"),
     47      "popover-target",
     48      "Correct details-from attribute"
     49    );
     50 
     51    info("Setting toggle2 popovertarget");
     52    await invokeSetAttribute(browser, "toggle2", "popovertarget", "popover");
     53    await testCachedRelation(toggle2, RELATION_DETAILS, popover);
     54    await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, toggle2]);
     55 
     56    info("Removing toggle2 popovertarget");
     57    await invokeSetAttribute(browser, "toggle2", "popovertarget", null);
     58    await testCachedRelation(toggle2, RELATION_DETAILS, []);
     59    await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1);
     60 
     61    info("Setting aria-details on toggle1");
     62    await invokeSetAttribute(browser, "toggle1", "aria-details", "details");
     63    const details = findAccessibleChildByID(docAcc, "details");
     64    // aria-details overrides popover.
     65    await testCachedRelation(toggle1, RELATION_DETAILS, details);
     66    await testCachedRelation(popover, RELATION_DETAILS_FOR, []);
     67 
     68    info("Removing aria-details from toggle1");
     69    await invokeSetAttribute(browser, "toggle1", "aria-details", null);
     70    await testCachedRelation(toggle1, RELATION_DETAILS, popover);
     71    await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1);
     72 
     73    info("Hiding popover");
     74    let hidden = waitForEvent(EVENT_HIDE, popover);
     75    toggle1.doAction(0);
     76    // The relations between toggle1 and popover are removed when popover shuts
     77    // down. However, this doesn't cause a cache update notification. Therefore,
     78    // to avoid timing out in testCachedRelation, we must wait for a hide event
     79    // first.
     80    await hidden;
     81    await testCachedRelation(toggle1, RELATION_DETAILS, []);
     82  },
     83  { chrome: false, topLevel: true }
     84 );
     85 
     86 /**
     87 * Test details relations for the commandfor content attribute.
     88 */
     89 addAccessibleTask(
     90  `
     91 <button id="hide" commandfor="popover" command="hide-popover">hide</button>
     92 <button id="toggle1" commandfor="popover" command="toggle-popover">toggle1</button>
     93 <button id="show" commandfor="popover" command="show-popover">show</button>
     94 <button id="showModal" commandfor="popover" command="show-modal">show-modal</button>
     95 <button id="invalid" commandfor="popover" command="invalid">invalid</button>
     96 <button id="custom" commandfor="popover" command="--custom">custom</button>
     97 <button id="toggle2" command="toggle-popover">toggle2</button>
     98 <button id="toggleSibling" commandfor="popover" command="toggle-popover">toggleSibling</button>
     99 <dialog id="popover" popover>popover</dialog>
    100 <div id="details">details</div>
    101  `,
    102  async function testPopoverContent(browser, docAcc) {
    103    // The popover is hidden, so nothing should be referring to it.
    104    const hide = findAccessibleChildByID(docAcc, "hide");
    105    await testCachedRelation(hide, RELATION_DETAILS, []);
    106    const toggle1 = findAccessibleChildByID(docAcc, "toggle1");
    107    await testCachedRelation(toggle1, RELATION_DETAILS, []);
    108    const show = findAccessibleChildByID(docAcc, "show");
    109    await testCachedRelation(show, RELATION_DETAILS, []);
    110    const toggle2 = findAccessibleChildByID(docAcc, "toggle2");
    111    await testCachedRelation(toggle2, RELATION_DETAILS, []);
    112    const showModal = findAccessibleChildByID(docAcc, "showModal");
    113    await testCachedRelation(showModal, RELATION_DETAILS, []);
    114    const invalid = findAccessibleChildByID(docAcc, "invalid");
    115    await testCachedRelation(invalid, RELATION_DETAILS, []);
    116    const custom = findAccessibleChildByID(docAcc, "custom");
    117    await testCachedRelation(custom, RELATION_DETAILS, []);
    118    const toggleSibling = findAccessibleChildByID(docAcc, "toggleSibling");
    119    await testCachedRelation(toggleSibling, RELATION_DETAILS, []);
    120 
    121    info("Showing popover");
    122    let shown = waitForEvent(EVENT_SHOW, "popover");
    123    toggle1.doAction(0);
    124    const popover = (await shown).accessible;
    125    await testCachedRelation(toggle1, RELATION_DETAILS, popover);
    126    await testCachedRelation(show, RELATION_DETAILS, popover);
    127    // toggle2 shouldn't have a details relation because it doesn't have a
    128    // commandfor.
    129    await testCachedRelation(toggle2, RELATION_DETAILS, []);
    130    // hide shouldn't have a details relation because its action is hide-popover.
    131    await testCachedRelation(hide, RELATION_DETAILS, []);
    132    // showModal shouldn't have a details relation because it is executing a
    133    // non-popover command.
    134    await testCachedRelation(showModal, RELATION_DETAILS, []);
    135    // invalid shouldn't have a details relation because it has an invalid command.
    136    await testCachedRelation(invalid, RELATION_DETAILS, []);
    137    // custom shouldn't have a details relation because it has a custom command.
    138    await testCachedRelation(invalid, RELATION_DETAILS, []);
    139    // toggleSibling shouldn't have a details relation because it is a sibling
    140    // of the popover.
    141    await testCachedRelation(toggleSibling, RELATION_DETAILS, []);
    142    await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, show]);
    143    is(
    144      toggle1.attributes.getStringProperty("details-from"),
    145      "command-for",
    146      "Correct details-from attribute"
    147    );
    148 
    149    info("Setting toggle2 commandfor");
    150    await invokeSetAttribute(browser, "toggle2", "commandfor", "popover");
    151    await testCachedRelation(toggle2, RELATION_DETAILS, popover);
    152 
    153    await testCachedRelation(popover, RELATION_DETAILS_FOR, [
    154      toggle1,
    155      show,
    156      toggle2,
    157    ]);
    158 
    159    info("Removing toggle2 commandfor");
    160    await invokeSetAttribute(browser, "toggle2", "commandfor", null);
    161    await testCachedRelation(toggle2, RELATION_DETAILS, []);
    162    await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, show]);
    163 
    164    info("Setting aria-details on toggle1");
    165    await invokeSetAttribute(browser, "toggle1", "aria-details", "details");
    166    const details = findAccessibleChildByID(docAcc, "details");
    167    // aria-details overrides popover.
    168    await testCachedRelation(toggle1, RELATION_DETAILS, details);
    169    is(
    170      toggle1.attributes.getStringProperty("details-from"),
    171      "aria-details",
    172      "Correct details-from attribute"
    173    );
    174 
    175    await testCachedRelation(popover, RELATION_DETAILS_FOR, [show]);
    176 
    177    info("Removing aria-details from toggle1");
    178    await invokeSetAttribute(browser, "toggle1", "aria-details", null);
    179    await testCachedRelation(toggle1, RELATION_DETAILS, popover);
    180    await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, show]);
    181 
    182    is(
    183      toggle1.attributes.getStringProperty("details-from"),
    184      "command-for",
    185      "Correct details-from attribute"
    186    );
    187 
    188    info("Hiding popover");
    189    let hidden = waitForEvent(EVENT_HIDE, popover);
    190    toggle1.doAction(0);
    191    // The relations between toggle1 and popover are removed when popover shuts
    192    // down. However, this doesn't cause a cache update notification. Therefore,
    193    // to avoid timing out in testCachedRelation, we must wait for a hide event
    194    // first.
    195    await hidden;
    196    await testCachedRelation(toggle1, RELATION_DETAILS, []);
    197    await testCachedRelation(show, RELATION_DETAILS, []);
    198  },
    199  { chrome: false, topLevel: true }
    200 );
    201 
    202 /**
    203 * Test details relations for the popoverTargetElement WebIDL attribute.
    204 */
    205 addAccessibleTask(
    206  `
    207 <button id="toggle1">toggle1</button>
    208 <button id="toggle2">toggle2</button>
    209 between
    210 <div id="popover1" popover>popover1</div>
    211 <button id="toggle3">toggle3</button>
    212 <div id="shadowHost"><template shadowrootmode="open">
    213  <button id="toggle4">toggle4</button>
    214  between
    215  <div id="popover2" popover>popover2</div>
    216  <button id="toggle5">toggle5</button>
    217 </template></div>
    218  `,
    219  async function testPopoverIdl(browser, docAcc) {
    220    // No popover is showing, so there shouldn't be any details relations.
    221    const toggle1 = findAccessibleChildByID(docAcc, "toggle1");
    222    await testCachedRelation(toggle1, RELATION_DETAILS, []);
    223    const toggle2 = findAccessibleChildByID(docAcc, "toggle2");
    224    await testCachedRelation(toggle2, RELATION_DETAILS, []);
    225    const toggle3 = findAccessibleChildByID(docAcc, "toggle3");
    226    await testCachedRelation(toggle3, RELATION_DETAILS, []);
    227    const toggle4 = findAccessibleChildByID(docAcc, "toggle4");
    228    await testCachedRelation(toggle4, RELATION_DETAILS, []);
    229    const toggle5 = findAccessibleChildByID(docAcc, "toggle5");
    230    await testCachedRelation(toggle5, RELATION_DETAILS, []);
    231 
    232    info("Showing popover1");
    233    let shown = waitForEvent(EVENT_SHOW, "popover1");
    234    toggle1.doAction(0);
    235    const popover1 = (await shown).accessible;
    236    await testCachedRelation(toggle1, RELATION_DETAILS, popover1);
    237    // toggle5 is inside the shadow DOM and popover1 is outside, so the target
    238    // is valid.
    239    await testCachedRelation(toggle5, RELATION_DETAILS, popover1);
    240    await testCachedRelation(popover1, RELATION_DETAILS_FOR, [
    241      toggle1,
    242      toggle5,
    243    ]);
    244    info("Setting toggle2's popover target to popover1");
    245    await invokeContentTask(browser, [], () => {
    246      const toggle2Dom = content.document.getElementById("toggle2");
    247      const popover1Dom = content.document.getElementById("popover1");
    248      toggle2Dom.popoverTargetElement = popover1Dom;
    249    });
    250    await testCachedRelation(toggle2, RELATION_DETAILS, popover1);
    251    await testCachedRelation(popover1, RELATION_DETAILS_FOR, [
    252      toggle1,
    253      toggle2,
    254      toggle5,
    255    ]);
    256    info("Clearing toggle2's popover target");
    257    await invokeContentTask(browser, [], () => {
    258      const toggle2Dom = content.document.getElementById("toggle2");
    259      toggle2Dom.popoverTargetElement = null;
    260    });
    261    await testCachedRelation(toggle2, RELATION_DETAILS, []);
    262    await testCachedRelation(popover1, RELATION_DETAILS_FOR, [
    263      toggle1,
    264      toggle5,
    265    ]);
    266    info("Hiding popover1");
    267    let hidden = waitForEvent(EVENT_HIDE, popover1);
    268    toggle1.doAction(0);
    269    await hidden;
    270    await testCachedRelation(toggle1, RELATION_DETAILS, []);
    271    await testCachedRelation(toggle2, RELATION_DETAILS, []);
    272    await testCachedRelation(toggle5, RELATION_DETAILS, []);
    273 
    274    info("Showing popover2");
    275    shown = waitForEvent(EVENT_SHOW, "popover2");
    276    toggle4.doAction(0);
    277    const popover2 = (await shown).accessible;
    278    // toggle4 is in the same shadow DOM as popover2.
    279    await testCachedRelation(toggle4, RELATION_DETAILS, popover2);
    280    // toggle3 is outside popover2's shadow DOM, so the target isn't valid.
    281    await testCachedRelation(toggle3, RELATION_DETAILS, []);
    282    await testCachedRelation(popover2, RELATION_DETAILS_FOR, [toggle4]);
    283    info("Hiding popover2");
    284    hidden = waitForEvent(EVENT_HIDE, popover2);
    285    toggle4.doAction(0);
    286    await hidden;
    287    await testCachedRelation(toggle4, RELATION_DETAILS, []);
    288  },
    289  {
    290    chrome: true,
    291    topLevel: true,
    292    contentSetup: async function contentSetup() {
    293      const toggle1 = content.document.getElementById("toggle1");
    294      const popover1 = content.document.getElementById("popover1");
    295      toggle1.popoverTargetElement = popover1;
    296      const toggle3 = content.document.getElementById("toggle3");
    297      const shadow = content.document.getElementById("shadowHost").shadowRoot;
    298      const toggle4 = shadow.getElementById("toggle4");
    299      const popover2 = shadow.getElementById("popover2");
    300      toggle3.popoverTargetElement = popover2;
    301      toggle4.popoverTargetElement = popover2;
    302      const toggle5 = shadow.getElementById("toggle5");
    303      toggle5.popoverTargetElement = popover1;
    304    },
    305  }
    306 );