tor-browser

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

fire-focusin-focusout.html (4447B)


      1 <!DOCTYPE html>
      2 <title>moveBefore should not fire focus events</title>
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <body>
      6 <section id="old_parent">
      7 <button id="button" tabindex="1">Button</button>
      8 </section>
      9 <section id="new_parent">
     10 </section>
     11 <section id="inert_parent" inert>
     12 </section>
     13 <section id="inert_when_not_empty_parent">
     14 </section>
     15 
     16 <style>
     17    #inert_when_not_empty_parent:has(button) {
     18        display: none;
     19    }
     20 </style>
     21 
     22 <script>
     23 function collect_focusinout_events(t) {
     24    const collected = [];
     25    const listener = event => { collected.push(event); };
     26    document.addEventListener("focusin", listener);
     27    document.addEventListener("focusout", listener);
     28    t.add_cleanup(() => document.removeEventListener("focusin", listener));
     29    t.add_cleanup(() => document.removeEventListener("focusout", listener));
     30    return collected;
     31 }
     32 
     33 function assert_collected_events_equals(a, b) {
     34    const eventToString = event => `${event.target.id || event.target.nodeName}.on${event.type}`;
     35    return assert_array_equals(a.map(eventToString), b.map(eventToString));
     36 }
     37 
     38 test(t => {
     39    const collected_events = collect_focusinout_events(t);
     40    const old_parent = document.querySelector("#old_parent");
     41    const button = document.querySelector("#button");
     42    t.add_cleanup(() => old_parent.append(button));
     43    button.focus();
     44    assert_collected_events_equals(collected_events, [
     45        {type: "focusin", target: button},
     46    ]);
     47    assert_equals(document.activeElement, button);
     48    new_parent.moveBefore(button, null);
     49    assert_collected_events_equals(collected_events, [
     50        {type: "focusin", target: button},
     51    ]);
     52 }, "Don't fire focusin/out when reparenting focused element directly");
     53 
     54 test(t => {
     55    const collected_events = collect_focusinout_events(t);
     56    const old_parent = document.querySelector("#old_parent");
     57    const button = document.querySelector("#button");
     58    t.add_cleanup(() => document.body.append(old_parent));
     59    button.focus();
     60    new_parent.moveBefore(old_parent, null);
     61    assert_collected_events_equals(collected_events, [
     62        {type: "focusin", target: button},
     63    ]);
     64 }, "Don't fire focusin/out when reparenting an element that has focus within");
     65 
     66 test(t => {
     67    const collected_events = collect_focusinout_events(t);
     68    const old_parent = document.querySelector("#old_parent");
     69    const button = document.querySelector("#button");
     70    t.add_cleanup(() => old_parent.append(button));
     71    button.focus();
     72    old_parent.moveBefore(button, null);
     73    assert_collected_events_equals(collected_events, [
     74        {type: "focusin", target: button},
     75    ]);
     76 }, "Don't fire focusin/out when moving to the same parent");
     77 
     78 promise_test(async t => {
     79    const collected_events = collect_focusinout_events(t);
     80    const old_parent = document.querySelector("#old_parent");
     81    const inert_parent= document.querySelector("#inert_parent");
     82    const button = document.querySelector("#button");
     83    t.add_cleanup(() => old_parent.append(button));
     84    button.focus();
     85    inert_parent.moveBefore(button, null);
     86    assert_collected_events_equals(collected_events, [
     87        {type: "focusin", target: button}]);
     88    await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
     89    assert_collected_events_equals(collected_events, [
     90        {type: "focusin", target: button},
     91        {type: "focusout", target: button},
     92    ]);
     93 }, "Don't fire focusin and then correct when moving to an inert subtree");
     94 
     95 promise_test(async t => {
     96    const collected_events = collect_focusinout_events(t);
     97    const old_parent = document.querySelector("#old_parent");
     98    const inert_when_not_empty_parent = document.querySelector("#inert_when_not_empty_parent");
     99    const button = document.querySelector("#button");
    100    t.add_cleanup(() => old_parent.append(button));
    101    button.focus();
    102    inert_when_not_empty_parent.moveBefore(button, null);
    103    assert_collected_events_equals(collected_events, [
    104        {type: "focusin", target: button},
    105    ]);
    106    await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
    107    assert_collected_events_equals(collected_events, [
    108        {type: "focusin", target: button},
    109        {type: "focusout", target: button},
    110    ]);
    111 }, "Don't fire focusin and then correct when moving to a tree that is made inert using style");
    112 
    113 </script>