tor-browser

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

text.js (22877B)


      1 /* import-globals-from common.js */
      2 
      3 // //////////////////////////////////////////////////////////////////////////////
      4 // Public
      5 
      6 const BOUNDARY_CHAR = nsIAccessibleText.BOUNDARY_CHAR;
      7 const BOUNDARY_WORD_START = nsIAccessibleText.BOUNDARY_WORD_START;
      8 const BOUNDARY_WORD_END = nsIAccessibleText.BOUNDARY_WORD_END;
      9 const BOUNDARY_LINE_START = nsIAccessibleText.BOUNDARY_LINE_START;
     10 const BOUNDARY_LINE_END = nsIAccessibleText.BOUNDARY_LINE_END;
     11 const BOUNDARY_PARAGRAPH = nsIAccessibleText.BOUNDARY_PARAGRAPH;
     12 const BOUNDARY_CLUSTER = nsIAccessibleText.BOUNDARY_CLUSTER;
     13 
     14 const kTextEndOffset = nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT;
     15 const kCaretOffset = nsIAccessibleText.TEXT_OFFSET_CARET;
     16 
     17 const EndPoint_Start = nsIAccessibleTextRange.EndPoint_Start;
     18 const EndPoint_End = nsIAccessibleTextRange.EndPoint_End;
     19 
     20 const kTodo = 1; // a test is expected to fail
     21 const kOk = 2; // a test doesn't fail
     22 
     23 /**
     24 * Test characterCount for the given array of accessibles.
     25 *
     26 * @param aCount    [in] the expected character count
     27 * @param aIDs      [in] array of accessible identifiers to test
     28 * @param aTodoFlag [in, optional] either kOk or kTodo
     29 */
     30 function testCharacterCount(aIDs, aCount, aTodoFlag) {
     31  var ids = aIDs instanceof Array ? aIDs : [aIDs];
     32  var isFunc = aTodoFlag == kTodo ? todo_is : is;
     33  for (var i = 0; i < ids.length; i++) {
     34    var textacc = getAccessible(ids[i], [nsIAccessibleText]);
     35    isFunc(
     36      textacc.characterCount,
     37      aCount,
     38      "Wrong character count for " + prettyName(ids[i])
     39    );
     40  }
     41 }
     42 
     43 /**
     44 * Test text between two given offsets.
     45 *
     46 * @param aIDs          [in] an array of accessible IDs to test
     47 * @param aStartOffset  [in] the start offset within the text to test
     48 * @param aEndOffset    [in] the end offset up to which the text is tested
     49 * @param aText         [in] the expected result from the test
     50 * @param aTodoFlag     [in, optional] either kOk or kTodo
     51 */
     52 function testText(aIDs, aStartOffset, aEndOffset, aText, aTodoFlag) {
     53  var ids = aIDs instanceof Array ? aIDs : [aIDs];
     54  var isFunc = aTodoFlag == kTodo ? todo_is : is;
     55  for (var i = 0; i < ids.length; i++) {
     56    var acc = getAccessible(ids[i], nsIAccessibleText);
     57    try {
     58      isFunc(
     59        acc.getText(aStartOffset, aEndOffset),
     60        aText,
     61        "getText: wrong text between start and end offsets '" +
     62          aStartOffset +
     63          "', '" +
     64          aEndOffset +
     65          " for '" +
     66          prettyName(ids[i]) +
     67          "'"
     68      );
     69    } catch (e) {
     70      ok(
     71        false,
     72        "getText fails between start and end offsets '" +
     73          aStartOffset +
     74          "', '" +
     75          aEndOffset +
     76          " for '" +
     77          prettyName(ids[i]) +
     78          "'"
     79      );
     80    }
     81  }
     82 }
     83 
     84 /**
     85 * Test getTextAtOffset for BOUNDARY_CHAR over different elements.
     86 *
     87 * @param aIDs          [in] the accessible identifier or array of accessible
     88 *                        identifiers
     89 * @param aOffset       [in] the offset to get a character at it
     90 * @param aChar         [in] the expected character
     91 * @param aStartOffset  [in] expected start offset of the character
     92 * @param aEndOffset    [in] expected end offset of the character
     93 */
     94 function testCharAtOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset) {
     95  var IDs = aIDs instanceof Array ? aIDs : [aIDs];
     96  for (var i = 0; i < IDs.length; i++) {
     97    var acc = getAccessible(IDs[i], nsIAccessibleText);
     98    testTextHelper(
     99      IDs[i],
    100      aOffset,
    101      BOUNDARY_CHAR,
    102      aChar,
    103      aStartOffset,
    104      aEndOffset,
    105      kOk,
    106      kOk,
    107      kOk,
    108      acc.getTextAtOffset,
    109      "getTextAtOffset "
    110    );
    111  }
    112 }
    113 
    114 /**
    115 * Test getTextAtOffset function over different elements.
    116 *
    117 * @param aIDs            [in] ID or array of IDs
    118 * @param aBoundaryType   [in] boundary type for text to be retrieved
    119 * @param aTestList       [in] array of sets:
    120 *                              offset1 and offset2 defining the offset range
    121 *                              the text in the range
    122 *                              start offset of the text in the range
    123 *                              end offset of the text in the range
    124 *
    125 * or
    126 *
    127 * @param aOffset         [in] the offset to get the text at
    128 * @param aBoundaryType   [in] Boundary type for text to be retrieved
    129 * @param aText           [in] expected return text for getTextAtOffset
    130 * @param aStartOffset    [in] expected return start offset for getTextAtOffset
    131 * @param aEndOffset      [in] expected return end offset for getTextAtOffset
    132 * @param ...             [in] list of ids or list of tuples made of:
    133 *                              element identifier
    134 *                              kTodo or kOk for returned text
    135 *                              kTodo or kOk for returned start offset
    136 *                              kTodo or kOk for returned offset result
    137 */
    138 function testTextAtOffset() {
    139  testTextSuperHelper("getTextAtOffset", arguments);
    140 }
    141 
    142 /**
    143 * Test getTextAfterOffset for BOUNDARY_CHAR over different elements.
    144 *
    145 * @param aIDs          [in] the accessible identifier or array of accessible
    146 *                        identifiers
    147 * @param aOffset       [in] the offset to get a character after it
    148 * @param aChar         [in] the expected character
    149 * @param aStartOffset  [in] expected start offset of the character
    150 * @param aEndOffset    [in] expected end offset of the character
    151 */
    152 function testCharAfterOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset) {
    153  var IDs = aIDs instanceof Array ? aIDs : [aIDs];
    154  for (var i = 0; i < IDs.length; i++) {
    155    var acc = getAccessible(IDs[i], nsIAccessibleText);
    156    testTextHelper(
    157      IDs[i],
    158      aOffset,
    159      BOUNDARY_CHAR,
    160      aChar,
    161      aStartOffset,
    162      aEndOffset,
    163      kOk,
    164      kOk,
    165      kOk,
    166      acc.getTextAfterOffset,
    167      "getTextAfterOffset "
    168    );
    169  }
    170 }
    171 
    172 /**
    173 * Test getTextAfterOffset function over different elements
    174 *
    175 * @param aIDs            [in] ID or array of IDs
    176 * @param aBoundaryType   [in] boundary type for text to be retrieved
    177 * @param aTestList       [in] array of sets:
    178 *                              offset1 and offset2 defining the offset range
    179 *                              the text in the range
    180 *                              start offset of the text in the range
    181 *                              end offset of the text in the range
    182 *
    183 * or
    184 *
    185 * @param aOffset         [in] the offset to get the text after
    186 * @param aBoundaryType   [in] Boundary type for text to be retrieved
    187 * @param aText           [in] expected return text for getTextAfterOffset
    188 * @param aStartOffset    [in] expected return start offset for getTextAfterOffset
    189 * @param aEndOffset      [in] expected return end offset for getTextAfterOffset
    190 * @param ...             [in] list of ids or list of tuples made of:
    191 *                              element identifier
    192 *                              kTodo or kOk for returned text
    193 *                              kTodo or kOk for returned start offset
    194 *                              kTodo or kOk for returned offset result
    195 */
    196 function testTextAfterOffset(
    197  aOffset,
    198  aBoundaryType,
    199  aText,
    200  aStartOffset,
    201  aEndOffset,
    202  ...aArgs
    203 ) {
    204  testTextSuperHelper("getTextAfterOffset", [
    205    aOffset,
    206    aBoundaryType,
    207    aText,
    208    aStartOffset,
    209    aEndOffset,
    210    ...aArgs,
    211  ]);
    212 }
    213 
    214 /**
    215 * Test getTextBeforeOffset for BOUNDARY_CHAR over different elements.
    216 *
    217 * @param aIDs          [in] the accessible identifier or array of accessible
    218 *                        identifiers
    219 * @param aOffset       [in] the offset to get a character before it
    220 * @param aChar         [in] the expected character
    221 * @param aStartOffset  [in] expected start offset of the character
    222 * @param aEndOffset    [in] expected end offset of the character
    223 */
    224 function testCharBeforeOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset) {
    225  var IDs = aIDs instanceof Array ? aIDs : [aIDs];
    226  for (var i = 0; i < IDs.length; i++) {
    227    var acc = getAccessible(IDs[i], nsIAccessibleText);
    228    testTextHelper(
    229      IDs[i],
    230      aOffset,
    231      BOUNDARY_CHAR,
    232      aChar,
    233      aStartOffset,
    234      aEndOffset,
    235      kOk,
    236      kOk,
    237      kOk,
    238      acc.getTextBeforeOffset,
    239      "getTextBeforeOffset "
    240    );
    241  }
    242 }
    243 
    244 /**
    245 * Test getTextBeforeOffset function over different elements
    246 *
    247 * @param aIDs            [in] ID or array of IDs
    248 * @param aBoundaryType   [in] boundary type for text to be retrieved
    249 * @param aTestList       [in] array of sets:
    250 *                              offset1 and offset2 defining the offset range
    251 *                              the text in the range
    252 *                              start offset of the text in the range
    253 *                              end offset of the text in the range
    254 *
    255 * or
    256 *
    257 * @param aOffset         [in] the offset to get the text before
    258 * @param aBoundaryType   [in] Boundary type for text to be retrieved
    259 * @param aText           [in] expected return text for getTextBeforeOffset
    260 * @param aStartOffset    [in] expected return start offset for getTextBeforeOffset
    261 * @param aEndOffset      [in] expected return end offset for getTextBeforeOffset
    262 * @param ...             [in] list of ids or list of tuples made of:
    263 *                              element identifier
    264 *                              kTodo or kOk for returned text
    265 *                              kTodo or kOk for returned start offset
    266 *                              kTodo or kOk for returned offset result
    267 */
    268 function testTextBeforeOffset(
    269  aOffset,
    270  aBoundaryType,
    271  aText,
    272  aStartOffset,
    273  aEndOffset,
    274  ...aArgs
    275 ) {
    276  testTextSuperHelper("getTextBeforeOffset", [
    277    aOffset,
    278    aBoundaryType,
    279    aText,
    280    aStartOffset,
    281    aEndOffset,
    282    ...aArgs,
    283  ]);
    284 }
    285 
    286 /**
    287 * Test word count for an element.
    288 *
    289 * @param aElement   [in] element identifier
    290 * @param aCount     [in] Expected word count
    291 * @param aToDoFlag  [in] kTodo or kOk for returned text
    292 */
    293 function testWordCount(aElement, aCount, aToDoFlag) {
    294  var isFunc = aToDoFlag == kTodo ? todo_is : is;
    295  var acc = getAccessible(aElement, nsIAccessibleText);
    296  var startOffsetObj = {},
    297    endOffsetObj = {};
    298  var length = acc.characterCount;
    299  var offset = 0;
    300  var wordCount = 0;
    301  while (true) {
    302    acc.getTextAtOffset(
    303      offset,
    304      BOUNDARY_WORD_START,
    305      startOffsetObj,
    306      endOffsetObj
    307    );
    308    if (offset >= length) {
    309      break;
    310    }
    311 
    312    wordCount++;
    313    offset = endOffsetObj.value;
    314  }
    315  isFunc(
    316    wordCount,
    317    aCount,
    318    "wrong words count for '" +
    319      acc.getText(0, -1) +
    320      "': " +
    321      wordCount +
    322      " in " +
    323      prettyName(aElement)
    324  );
    325 }
    326 
    327 /**
    328 * Test word at a position for an element.
    329 *
    330 * @param aElement    [in] element identifier
    331 * @param aWordIndex  [in] index of the word to test
    332 * @param aText       [in] expected text for that word
    333 * @param aToDoFlag   [in] kTodo or kOk for returned text
    334 */
    335 function testWordAt(aElement, aWordIndex, aText, aToDoFlag) {
    336  var isFunc = aToDoFlag == kTodo ? todo_is : is;
    337  var acc = getAccessible(aElement, nsIAccessibleText);
    338 
    339  var textLength = acc.characterCount;
    340  var wordIdx = aWordIndex;
    341  var startOffsetObj = { value: 0 },
    342    endOffsetObj = { value: 0 };
    343  for (let offset = 0; offset < textLength; offset = endOffsetObj.value) {
    344    acc.getTextAtOffset(
    345      offset,
    346      BOUNDARY_WORD_START,
    347      startOffsetObj,
    348      endOffsetObj
    349    );
    350 
    351    wordIdx--;
    352    if (wordIdx < 0) {
    353      break;
    354    }
    355  }
    356 
    357  if (wordIdx >= 0) {
    358    ok(
    359      false,
    360      "the given word index '" +
    361        aWordIndex +
    362        "' exceeds words amount in " +
    363        prettyName(aElement)
    364    );
    365 
    366    return;
    367  }
    368 
    369  var startWordOffset = startOffsetObj.value;
    370  var endWordOffset = endOffsetObj.value;
    371 
    372  // Calculate the end word offset.
    373  acc.getTextAtOffset(
    374    endOffsetObj.value,
    375    BOUNDARY_WORD_END,
    376    startOffsetObj,
    377    endOffsetObj
    378  );
    379  if (startOffsetObj.value != textLength) {
    380    endWordOffset = startOffsetObj.value;
    381  }
    382 
    383  if (endWordOffset <= startWordOffset) {
    384    todo(
    385      false,
    386      "wrong start and end offset for word at index '" +
    387        aWordIndex +
    388        "': " +
    389        " of text '" +
    390        acc.getText(0, -1) +
    391        "' in " +
    392        prettyName(aElement)
    393    );
    394 
    395    return;
    396  }
    397 
    398  let text = acc.getText(startWordOffset, endWordOffset);
    399  isFunc(
    400    text,
    401    aText,
    402    "wrong text for word at index '" +
    403      aWordIndex +
    404      "': " +
    405      " of text '" +
    406      acc.getText(0, -1) +
    407      "' in " +
    408      prettyName(aElement)
    409  );
    410 }
    411 
    412 /**
    413 * Test words in a element.
    414 *
    415 * @param aElement   [in]           element identifier
    416 * @param aWords     [in]           array of expected words
    417 * @param aToDoFlag  [in, optional] kTodo or kOk for returned text
    418 */
    419 function testWords(aElement, aWords, aToDoFlag) {
    420  if (aToDoFlag == null) {
    421    aToDoFlag = kOk;
    422  }
    423 
    424  testWordCount(aElement, aWords.length, aToDoFlag);
    425 
    426  for (var i = 0; i < aWords.length; i++) {
    427    testWordAt(aElement, i, aWords[i], aToDoFlag);
    428  }
    429 }
    430 
    431 /**
    432 * Remove all selections.
    433 *
    434 * @param aID  [in] Id, DOM node, or acc obj
    435 */
    436 function cleanTextSelections(aID) {
    437  var acc = getAccessible(aID, [nsIAccessibleText]);
    438 
    439  while (acc.selectionCount > 0) {
    440    acc.removeSelection(0);
    441  }
    442 }
    443 
    444 /**
    445 * Test addSelection method.
    446 *
    447 * @param aID               [in] Id, DOM node, or acc obj
    448 * @param aStartOffset      [in] start offset for the new selection
    449 * @param aEndOffset        [in] end offset for the new selection
    450 * @param aSelectionsCount  [in] expected number of selections after addSelection
    451 */
    452 function testTextAddSelection(aID, aStartOffset, aEndOffset, aSelectionsCount) {
    453  var acc = getAccessible(aID, [nsIAccessibleText]);
    454  var text = acc.getText(0, -1);
    455 
    456  acc.addSelection(aStartOffset, aEndOffset);
    457 
    458  is(
    459    acc.selectionCount,
    460    aSelectionsCount,
    461    text +
    462      ": failed to add selection from offset '" +
    463      aStartOffset +
    464      "' to offset '" +
    465      aEndOffset +
    466      "': selectionCount after"
    467  );
    468 }
    469 
    470 /**
    471 * Test removeSelection method.
    472 *
    473 * @param aID               [in] Id, DOM node, or acc obj
    474 * @param aSelectionIndex   [in] index of the selection to be removed
    475 * @param aSelectionsCount  [in] expected number of selections after
    476 *                               removeSelection
    477 */
    478 function testTextRemoveSelection(aID, aSelectionIndex, aSelectionsCount) {
    479  var acc = getAccessible(aID, [nsIAccessibleText]);
    480  var text = acc.getText(0, -1);
    481 
    482  acc.removeSelection(aSelectionIndex);
    483 
    484  is(
    485    acc.selectionCount,
    486    aSelectionsCount,
    487    text +
    488      ": failed to remove selection at index '" +
    489      aSelectionIndex +
    490      "': selectionCount after"
    491  );
    492 }
    493 
    494 /**
    495 * Test setSelectionBounds method.
    496 *
    497 * @param aID               [in] Id, DOM node, or acc obj
    498 * @param aStartOffset      [in] new start offset for the selection
    499 * @param aEndOffset        [in] new end offset for the selection
    500 * @param aSelectionIndex   [in] index of the selection to set
    501 * @param aSelectionsCount  [in] expected number of selections after
    502 *                               setSelectionBounds
    503 */
    504 function testTextSetSelection(
    505  aID,
    506  aStartOffset,
    507  aEndOffset,
    508  aSelectionIndex,
    509  aSelectionsCount
    510 ) {
    511  var acc = getAccessible(aID, [nsIAccessibleText]);
    512  var text = acc.getText(0, -1);
    513 
    514  acc.setSelectionBounds(aSelectionIndex, aStartOffset, aEndOffset);
    515 
    516  is(
    517    acc.selectionCount,
    518    aSelectionsCount,
    519    text +
    520      ": failed to set selection at index '" +
    521      aSelectionIndex +
    522      "': selectionCount after"
    523  );
    524 }
    525 
    526 /**
    527 * Test selectionCount method.
    528 *
    529 * @param aID        [in] Id, DOM node, or acc obj
    530 * @param aCount     [in] expected selection count
    531 */
    532 function testTextSelectionCount(aID, aCount) {
    533  var acc = getAccessible(aID, [nsIAccessibleText]);
    534  var text = acc.getText(0, -1);
    535 
    536  is(acc.selectionCount, aCount, text + ": wrong selectionCount: ");
    537 }
    538 
    539 /**
    540 * Test getSelectionBounds method.
    541 *
    542 * @param aID              [in] Id, DOM node, or acc obj
    543 * @param aStartOffset     [in] expected start offset for the selection
    544 * @param aEndOffset       [in] expected end offset for the selection
    545 * @param aSelectionIndex  [in] index of the selection to get
    546 */
    547 function testTextGetSelection(aID, aStartOffset, aEndOffset, aSelectionIndex) {
    548  var acc = getAccessible(aID, [nsIAccessibleText]);
    549  var text = acc.getText(0, -1);
    550 
    551  var startObj = {},
    552    endObj = {};
    553  acc.getSelectionBounds(aSelectionIndex, startObj, endObj);
    554 
    555  is(
    556    startObj.value,
    557    aStartOffset,
    558    text + ": wrong start offset for index '" + aSelectionIndex + "'"
    559  );
    560  is(
    561    endObj.value,
    562    aEndOffset,
    563    text + ": wrong end offset for index '" + aSelectionIndex + "'"
    564  );
    565 }
    566 
    567 function testTextRange(
    568  aRange,
    569  aRangeDescr,
    570  aStartContainer,
    571  aStartOffset,
    572  aEndContainer,
    573  aEndOffset,
    574  aText,
    575  aCommonContainer,
    576  aChildren
    577 ) {
    578  isObject(
    579    aRange.startContainer,
    580    getAccessible(aStartContainer),
    581    "Wrong start container of " + aRangeDescr
    582  );
    583  is(aRange.startOffset, aStartOffset, "Wrong start offset of " + aRangeDescr);
    584  isObject(
    585    aRange.endContainer,
    586    getAccessible(aEndContainer),
    587    "Wrong end container of " + aRangeDescr
    588  );
    589  is(aRange.endOffset, aEndOffset, "Wrong end offset of " + aRangeDescr);
    590 
    591  if (aText === undefined) {
    592    return;
    593  }
    594 
    595  is(aRange.text, aText, "Wrong text of " + aRangeDescr);
    596 
    597  var children = aRange.embeddedChildren;
    598  is(
    599    children ? children.length : 0,
    600    aChildren ? aChildren.length : 0,
    601    "Wrong embedded children count of " + aRangeDescr
    602  );
    603 
    604  isObject(
    605    aRange.container,
    606    getAccessible(aCommonContainer),
    607    "Wrong container of " + aRangeDescr
    608  );
    609 
    610  if (aChildren) {
    611    for (var i = 0; i < aChildren.length; i++) {
    612      var expectedChild = getAccessible(aChildren[i]);
    613      var actualChild = children.queryElementAt(i, nsIAccessible);
    614      isObject(
    615        actualChild,
    616        expectedChild,
    617        "Wrong child at index '" + i + "' of " + aRangeDescr
    618      );
    619    }
    620  }
    621 }
    622 
    623 // //////////////////////////////////////////////////////////////////////////////
    624 // Private
    625 
    626 function testTextSuperHelper(aFuncName, aArgs) {
    627  // List of tests.
    628  if (aArgs[2] instanceof Array) {
    629    let ids = aArgs[0] instanceof Array ? aArgs[0] : [aArgs[0]];
    630    let boundaryType = aArgs[1];
    631    let list = aArgs[2];
    632    for (let i = 0; i < list.length; i++) {
    633      let offset1 = list[i][0],
    634        offset2 = list[i][1];
    635      let text = list[i][2],
    636        startOffset = list[i][3],
    637        endOffset = list[i][4];
    638      let failureList = list[i][5];
    639      for (let offset = offset1; offset <= offset2; offset++) {
    640        for (let idIdx = 0; idIdx < ids.length; idIdx++) {
    641          let id = ids[idIdx];
    642 
    643          let flagOk1 = kOk,
    644            flagOk2 = kOk,
    645            flagOk3 = kOk;
    646          if (failureList) {
    647            for (let fIdx = 0; fIdx < failureList.length; fIdx++) {
    648              if (
    649                offset == failureList[fIdx][0] &&
    650                id == failureList[fIdx][1]
    651              ) {
    652                flagOk1 = failureList[fIdx][2];
    653                flagOk2 = failureList[fIdx][3];
    654                flagOk3 = failureList[fIdx][4];
    655                break;
    656              }
    657            }
    658          }
    659 
    660          let acc = getAccessible(id, nsIAccessibleText);
    661          testTextHelper(
    662            id,
    663            offset,
    664            boundaryType,
    665            text,
    666            startOffset,
    667            endOffset,
    668            flagOk1,
    669            flagOk2,
    670            flagOk3,
    671            acc[aFuncName],
    672            aFuncName + " "
    673          );
    674        }
    675      }
    676    }
    677    return;
    678  }
    679 
    680  // Test at single offset. List of IDs.
    681  var offset = aArgs[0];
    682  var boundaryType = aArgs[1];
    683  var text = aArgs[2];
    684  var startOffset = aArgs[3];
    685  var endOffset = aArgs[4];
    686  if (aArgs[5] instanceof Array) {
    687    let ids = aArgs[5];
    688    for (let i = 0; i < ids.length; i++) {
    689      let acc = getAccessible(ids[i], nsIAccessibleText);
    690      testTextHelper(
    691        ids[i],
    692        offset,
    693        boundaryType,
    694        text,
    695        startOffset,
    696        endOffset,
    697        kOk,
    698        kOk,
    699        kOk,
    700        acc[aFuncName],
    701        aFuncName + " "
    702      );
    703    }
    704 
    705    return;
    706  }
    707 
    708  // Each ID is tested separately.
    709  for (let i = 5; i < aArgs.length; i = i + 4) {
    710    let ID = aArgs[i];
    711    let acc = getAccessible(ID, nsIAccessibleText);
    712    let toDoFlag1 = aArgs[i + 1];
    713    let toDoFlag2 = aArgs[i + 2];
    714    let toDoFlag3 = aArgs[i + 3];
    715 
    716    testTextHelper(
    717      ID,
    718      offset,
    719      boundaryType,
    720      text,
    721      startOffset,
    722      endOffset,
    723      toDoFlag1,
    724      toDoFlag2,
    725      toDoFlag3,
    726      acc[aFuncName],
    727      aFuncName + " "
    728    );
    729  }
    730 }
    731 
    732 function testTextHelper(
    733  aID,
    734  aOffset,
    735  aBoundaryType,
    736  aText,
    737  aStartOffset,
    738  aEndOffset,
    739  aToDoFlag1,
    740  aToDoFlag2,
    741  aToDoFlag3,
    742  aTextFunc,
    743  aTextFuncName
    744 ) {
    745  var exceptionFlag =
    746    aToDoFlag1 == undefined ||
    747    aToDoFlag2 == undefined ||
    748    aToDoFlag3 == undefined;
    749 
    750  var startMsg = aTextFuncName + "(" + boundaryToString(aBoundaryType) + "): ";
    751  var endMsg = ", id: " + prettyName(aID) + ";";
    752 
    753  try {
    754    var startOffsetObj = {},
    755      endOffsetObj = {};
    756    var text = aTextFunc(aOffset, aBoundaryType, startOffsetObj, endOffsetObj);
    757 
    758    if (exceptionFlag) {
    759      ok(false, startMsg + "no expected failure at offset " + aOffset + endMsg);
    760      return;
    761    }
    762 
    763    var isFunc1 = aToDoFlag1 == kTodo ? todo : ok;
    764    var isFunc2 = aToDoFlag2 == kTodo ? todo : ok;
    765    var isFunc3 = aToDoFlag3 == kTodo ? todo : ok;
    766 
    767    isFunc1(
    768      text == aText,
    769      startMsg +
    770        "wrong text " +
    771        "(got '" +
    772        text +
    773        "', expected: '" +
    774        aText +
    775        "')" +
    776        ", offset: " +
    777        aOffset +
    778        endMsg
    779    );
    780    isFunc2(
    781      startOffsetObj.value == aStartOffset,
    782      startMsg +
    783        "wrong start offset" +
    784        "(got '" +
    785        startOffsetObj.value +
    786        "', expected: '" +
    787        aStartOffset +
    788        "')" +
    789        ", offset: " +
    790        aOffset +
    791        endMsg
    792    );
    793    isFunc3(
    794      endOffsetObj.value == aEndOffset,
    795      startMsg +
    796        "wrong end offset" +
    797        "(got '" +
    798        endOffsetObj.value +
    799        "', expected: '" +
    800        aEndOffset +
    801        "')" +
    802        ", offset: " +
    803        aOffset +
    804        endMsg
    805    );
    806  } catch (e) {
    807    var okFunc = exceptionFlag ? todo : ok;
    808    okFunc(
    809      false,
    810      startMsg + "failed at offset " + aOffset + endMsg + ", exception: " + e
    811    );
    812  }
    813 }
    814 
    815 function boundaryToString(aBoundaryType) {
    816  switch (aBoundaryType) {
    817    case BOUNDARY_CHAR:
    818      return "char";
    819    case BOUNDARY_WORD_START:
    820      return "word start";
    821    case BOUNDARY_WORD_END:
    822      return "word end";
    823    case BOUNDARY_LINE_START:
    824      return "line start";
    825    case BOUNDARY_LINE_END:
    826      return "line end";
    827    case BOUNDARY_PARAGRAPH:
    828      return "paragraph";
    829    case BOUNDARY_CLUSTER:
    830      return "cluster";
    831  }
    832  return "unknown";
    833 }