tor-browser

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

test_tree_14.html (9846B)


      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 <!DOCTYPE HTML>
      5 <html>
      6 <!--
      7 Test that Tree component has working keyboard interactions.
      8 -->
      9 <head>
     10  <meta charset="utf-8">
     11  <title>Tree component keyboard test</title>
     12  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
     13  <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
     14  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
     15 </head>
     16 <body>
     17 <pre id="test">
     18 <script src="head.js" type="application/javascript"></script>
     19 <script type="application/javascript">
     20 
     21 "use strict";
     22 
     23 window.onload = async function() {
     24  try {
     25    const { a, button, div } =
     26      require("devtools/client/shared/vendor/react-dom-factories");
     27    const { createFactory } = browserRequire("devtools/client/shared/vendor/react");
     28    const {
     29      Simulate,
     30      findRenderedDOMComponentWithClass,
     31      findRenderedDOMComponentWithTag,
     32    } = browserRequire("devtools/client/shared/vendor/react-dom-test-utils");
     33    const Tree = createFactory(
     34      browserRequire("devtools/client/shared/components/VirtualizedTree"));
     35 
     36    let gTree, gFocused, gActive;
     37    function renderTree(props = {}) {
     38      let toggle = true;
     39      const treeProps = {
     40        ...TEST_TREE_INTERFACE,
     41        onFocus: x => {
     42          gFocused = x;
     43          renderTree({ focused: gFocused, active: gActive });
     44        },
     45        onActivate: x => {
     46          gActive = x;
     47          renderTree({ focused: gFocused, active: gActive });
     48        },
     49        renderItem: (x, depth, focused) => {
     50          toggle = !toggle;
     51          return toggle ?
     52            (div(
     53              {},
     54                `${"-".repeat(depth)}${x}:${focused}`,
     55                a({ href: "#" }, "Focusable 1"),
     56                button({ }, "Focusable 2"),
     57                "\n",
     58              )
     59            ) : `${"-".repeat(depth)}${x}:${focused}`;
     60        },
     61        ...props
     62      };
     63 
     64      gTree = ReactDOM.render(Tree(treeProps), document.body);
     65    }
     66 
     67    renderTree();
     68    const els = {
     69      get tree() {
     70        // React will replace the tree via renderTree.
     71        return findRenderedDOMComponentWithClass(gTree, "tree");
     72      },
     73      get anchor() {
     74        // When tree node becomes active/inactive, it is replaced with a newly rendered
     75        // one.
     76        return findRenderedDOMComponentWithTag(gTree, "a");
     77      },
     78      get button() {
     79        // When tree node becomes active/inactive, it is replaced with a newly rendered
     80        // one.
     81        return findRenderedDOMComponentWithTag(gTree, "button");
     82      },
     83    };
     84 
     85    function getExpectedActiveElementForFinalShiftTab() {
     86      // When tab focus mode is applied, the "Run Chrome Tests" button is not
     87      // focusable, so this Shift+Tab moves the focus to a Chrome UI element
     88      // instead of the "Run Chrome Tests" button, which makes the focus to
     89      // move to a browsing context that has a different top level browsing context
     90      // than the current browsing context. Since top level browsing contexts are
     91      // different, the activeElement in the old document is not cleared. Also
     92      // this is only the case when e10s is enabled.
     93      if (SpecialPowers.getBoolPref("accessibility.tabfocus_applies_to_xul") &&
     94          SpecialPowers.Services.appinfo.browserTabsRemoteAutostart) {
     95        return "tree";
     96      }
     97 
     98      return document.body;
     99    }
    100 
    101    const tests = [{
    102      name: "Test default Tree props. Keyboard focus is set to document body by default.",
    103      props: { focused: undefined, active: undefined },
    104      activeElement: document.body,
    105    }, {
    106      name: "Focused props must be set to the first node on initial focus. " +
    107            "Keyboard focus should be set on the tree.",
    108      action: () => els.tree.focus(),
    109      activeElement: "tree",
    110      props: { focused: "A" },
    111    }, {
    112      name: "Focused node should remain set even when the tree is blured. " +
    113            "Keyboard focus should be set back to document body.",
    114      action: () => els.tree.blur(),
    115      props: { focused: "A" },
    116      activeElement: document.body,
    117    }, {
    118      name: "Unset tree's focused prop.",
    119      action: () => renderTree({ focused: null }),
    120      props: { focused: null },
    121    }, {
    122      name: "Focused node must be re-set again to the first tree node on initial " +
    123            "focus. Keyboard focus should be set on tree's conatiner.",
    124      action: () => els.tree.focus(),
    125      activeElement: "tree",
    126      props: { focused: "A" },
    127    }, {
    128      name: "Focused node should be set as active on Enter.",
    129      event: { type: "keyDown", el: "tree", options: { key: "Enter" }},
    130      props: { focused: "A", active: "A" },
    131      activeElement: "tree",
    132    }, {
    133      name: "Active node should be unset on Escape.",
    134      event: { type: "keyDown", el: "tree", options: { key: "Escape" }},
    135      props: { focused: "A", active: null },
    136    }, {
    137      name: "Focused node should be set as active on Space.",
    138      event: { type: "keyDown", el: "tree", options: { key: " " }},
    139      props: { focused: "A", active: "A" },
    140      activeElement: "tree",
    141    }, {
    142      name: "Active node should unset when focus leaves the tree.",
    143      action: () => els.tree.blur(),
    144      props: { focused: "A", active: null },
    145      activeElement: document.body,
    146    }, {
    147      name: "Keyboard focus should be set on tree's conatiner on focus.",
    148      action: () => els.tree.focus(),
    149      activeElement: "tree",
    150    }, {
    151      name: "Focused node should be updated to next on ArrowDown.",
    152      event: { type: "keyDown", el: "tree", options: { key: "ArrowDown" }},
    153      props: { focused: "M", active: null },
    154    }, {
    155      name: "Focused item should be set as active on Enter. Keyboard focus should be " +
    156            "set on the first focusable element inside the tree node, if available.",
    157      event: { type: "keyDown", el: "tree", options: { key: "Enter" }},
    158      props: { focused: "M", active: "M" },
    159      activeElement: "anchor",
    160    }, {
    161      name: "Keyboard focus should be set to next tabbable element inside the active " +
    162            "node on Tab.",
    163      action() {
    164        synthesizeKey("KEY_Tab");
    165      },
    166      props: { focused: "M", active: "M" },
    167      activeElement: "button",
    168    }, {
    169      name: "Keyboard focus should wrap inside the tree node when focused on last " +
    170            "tabbable element.",
    171      action() {
    172        synthesizeKey("KEY_Tab");
    173      },
    174      props: { focused: "M", active: "M" },
    175      activeElement: "anchor",
    176    }, {
    177      name: "Keyboard focus should wrap inside the tree node when focused on first " +
    178            "tabbable element.",
    179      action() {
    180        synthesizeKey("KEY_Tab", { shiftKey: true });
    181      },
    182      props: { focused: "M", active: "M" },
    183      activeElement: "button",
    184    }, {
    185      name: "Active tree node should be unset on Escape. Focus should move back to the " +
    186            "tree container.",
    187      event: { type: "keyDown", el: "tree", options: { key: "Escape" }},
    188      props: { focused: "M", active: null },
    189      activeElement: "tree",
    190    }, {
    191      name: "Focused node should be set as active on Space. Keyboard focus should be " +
    192            "set on the first focusable element inside the tree node, if available.",
    193      event: { type: "keyDown", el: "tree", options: { key: " " }},
    194      props: { focused: "M", active: "M" },
    195      activeElement: "anchor",
    196    }, {
    197      name: "Focused tree node should remain set even when the tree is blured. " +
    198            "Keyboard focus should be set back to document body.",
    199      action: () => document.activeElement.blur(),
    200      props: { focused: "M", active: null, },
    201      activeElement: document.body,
    202    }, {
    203      name: "Keyboard focus should be set on tree's conatiner on focus.",
    204      action: () => els.tree.focus(),
    205      props: { focused: "M", active: null },
    206      activeElement: "tree",
    207    }, {
    208      name: "Focused tree node should be updated to previous on ArrowUp.",
    209      event: { type: "keyDown", el: "tree", options: { key: "ArrowUp" }},
    210      props: { focused: "A", active: null },
    211    }, {
    212      name: "Focused item should be set as active on Enter.",
    213      event: { type: "keyDown", el: "tree", options: { key: "Enter" }},
    214      props: { focused: "A", active: "A" },
    215      activeElement: "tree",
    216    }, {
    217      name: "Keyboard focus should move to another focusable element outside of the " +
    218            "tree when there's nothing to focus on inside the tree node.",
    219      action() {
    220        synthesizeKey("KEY_Tab", { shiftKey: true });
    221      },
    222      props: { focused: "A", active: null },
    223      activeElement: getExpectedActiveElementForFinalShiftTab(),
    224    }];
    225 
    226    for (const test of tests) {
    227      const { action, event, props, name } = test;
    228 
    229      info(name);
    230      if (event) {
    231        const { type, options, el } = event;
    232        const target = typeof el === "string" ? els[el] : el;
    233        Simulate[type](target, options);
    234      } else if (action) {
    235        action();
    236      }
    237 
    238      await forceRender(gTree);
    239 
    240      if (test.activeElement) {
    241        const expected = typeof test.activeElement === "string" ?
    242          els[test.activeElement] : test.activeElement;
    243        // eslint-disable-next-line no-debugger
    244        if (document.activeElement!==expected) {debugger;}
    245        is(document.activeElement, expected, "Focus is set correctly.");
    246      }
    247 
    248      for (const key in props) {
    249        is(gTree.props[key], props[key], `${key} prop is correct.`);
    250      }
    251    }
    252  } catch (e) {
    253    ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
    254  } finally {
    255    SimpleTest.finish();
    256  }
    257 };
    258 </script>
    259 </pre>
    260 </body>
    261 </html>