tor-browser

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

browser_events_textchange.js (3415B)


      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 function checkTextChangeEvent(
      8  event,
      9  id,
     10  text,
     11  start,
     12  end,
     13  isInserted,
     14  isFromUserInput
     15 ) {
     16  let tcEvent = event.QueryInterface(nsIAccessibleTextChangeEvent);
     17  is(tcEvent.start, start, `Correct start offset for ${prettyName(id)}`);
     18  is(tcEvent.length, end - start, `Correct length for ${prettyName(id)}`);
     19  is(
     20    tcEvent.isInserted,
     21    isInserted,
     22    `Correct isInserted flag for ${prettyName(id)}`
     23  );
     24  is(tcEvent.modifiedText, text, `Correct text for ${prettyName(id)}`);
     25  is(
     26    tcEvent.isFromUserInput,
     27    isFromUserInput,
     28    `Correct value of isFromUserInput for ${prettyName(id)}`
     29  );
     30  ok(
     31    tcEvent.accessibleDocument instanceof nsIAccessibleDocument,
     32    "Accessible document not present."
     33  );
     34 }
     35 
     36 async function changeText(browser, id, value, events) {
     37  let onEvents = waitForOrderedEvents(
     38    events.map(({ isInserted }) => {
     39      let eventType = isInserted ? EVENT_TEXT_INSERTED : EVENT_TEXT_REMOVED;
     40      return [eventType, id];
     41    })
     42  );
     43  // Change text in the subtree.
     44  await invokeContentTask(browser, [id, value], (contentId, contentValue) => {
     45    content.document.getElementById(contentId).firstChild.textContent =
     46      contentValue;
     47  });
     48  let resolvedEvents = await onEvents;
     49 
     50  events.forEach(({ isInserted, str, offset }, idx) =>
     51    checkTextChangeEvent(
     52      resolvedEvents[idx],
     53      id,
     54      str,
     55      offset,
     56      offset + str.length,
     57      isInserted,
     58      false
     59    )
     60  );
     61 }
     62 
     63 async function removeTextFromInput(browser, id, value, start, end) {
     64  let onTextRemoved = waitForEvent(EVENT_TEXT_REMOVED, id);
     65  // Select text and delete it.
     66  await invokeContentTask(
     67    browser,
     68    [id, start, end],
     69    (contentId, contentStart, contentEnd) => {
     70      let el = content.document.getElementById(contentId);
     71      el.focus();
     72      el.setSelectionRange(contentStart, contentEnd);
     73    }
     74  );
     75  await invokeContentTask(browser, [], () => {
     76    const { ContentTaskUtils } = ChromeUtils.importESModule(
     77      "resource://testing-common/ContentTaskUtils.sys.mjs"
     78    );
     79    const EventUtils = ContentTaskUtils.getEventUtils(content);
     80    EventUtils.sendChar("VK_DELETE", content);
     81  });
     82 
     83  let event = await onTextRemoved;
     84  checkTextChangeEvent(event, id, value, start, end, false, true);
     85 }
     86 
     87 /**
     88 * Test text change event and its interface:
     89 *   - start
     90 *   - length
     91 *   - isInserted
     92 *   - modifiedText
     93 *   - isFromUserInput
     94 */
     95 addAccessibleTask(
     96  `
     97  <p id="p">abc</p>
     98  <input id="input" value="input" />`,
     99  async function (browser) {
    100    let events = [
    101      { isInserted: false, str: "abc", offset: 0 },
    102      { isInserted: true, str: "def", offset: 0 },
    103    ];
    104    await changeText(browser, "p", "def", events);
    105 
    106    // Adding text should not send events with diffs for non-editable text.
    107    // We do this to avoid screen readers reading out confusing diffs for
    108    // live regions.
    109    events = [
    110      { isInserted: false, str: "def", offset: 0 },
    111      { isInserted: true, str: "deDEFf", offset: 0 },
    112    ];
    113    await changeText(browser, "p", "deDEFf", events);
    114 
    115    // Test isFromUserInput property.
    116    await removeTextFromInput(browser, "input", "n", 1, 2);
    117  },
    118  { iframe: true, remoteIframe: true }
    119 );