tor-browser

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

table.js (21624B)


      1 /**
      2 * This file provides set of helper functions to test nsIAccessibleTable
      3 * interface.
      4 *
      5 * Required:
      6 *   common.js
      7 *   role.js
      8 *   states.js
      9 */
     10 /* import-globals-from common.js */
     11 /* import-globals-from role.js */
     12 /* import-globals-from states.js */
     13 
     14 /**
     15 * Constants used to describe cells array.
     16 */
     17 const kDataCell = 1; // Indicates the cell is origin data cell
     18 const kRowHeaderCell = 2; // Indicates the cell is row header cell
     19 const kColHeaderCell = 4; // Indicated the cell is column header cell
     20 const kOrigin = kDataCell | kRowHeaderCell | kColHeaderCell;
     21 
     22 const kRowSpanned = 8; // Indicates the cell is not origin and row spanned
     23 const kColSpanned = 16; // Indicates the cell is not origin and column spanned
     24 const kSpanned = kRowSpanned | kColSpanned;
     25 
     26 /**
     27 * Constants to define column header type.
     28 */
     29 const kNoColumnHeader = 0;
     30 const kListboxColumnHeader = 1;
     31 const kTreeColumnHeader = 2;
     32 
     33 /**
     34 * Constants to define table type.
     35 */
     36 const kTable = 0;
     37 const kTreeTable = 1;
     38 const kMathTable = 2;
     39 
     40 /**
     41 * Test table structure and related methods.
     42 *
     43 * @param  aIdentifier     [in] table accessible identifier
     44 * @param  aCellsArray     [in] two dimensional array (row X columns) of
     45 *                          cell types (see constants defined above).
     46 * @param  aColHeaderType  [in] specifies wether column header cells are
     47 *                          arranged into the list.
     48 * @param  aCaption        [in] caption text if any
     49 * @param  aSummary        [in] summary text if any
     50 * @param  aTableType      [in] specifies the table type.
     51 * @param  aRowRoles       [in] array of row roles.
     52 */
     53 function testTableStruct(
     54  aIdentifier,
     55  aCellsArray,
     56  aColHeaderType,
     57  aCaption,
     58  aSummary,
     59  aTableType,
     60  aRowRoles
     61 ) {
     62  var tableNode = getNode(aIdentifier);
     63  var isGrid =
     64    tableNode.getAttribute("role") == "grid" ||
     65    tableNode.getAttribute("role") == "treegrid" ||
     66    tableNode.localName == "tree";
     67 
     68  var rowCount = aCellsArray.length;
     69  var colsCount = aCellsArray[0] ? aCellsArray[0].length : 0;
     70 
     71  // Test table accessible tree.
     72  var tableObj = {
     73    children: [],
     74  };
     75  switch (aTableType) {
     76    case kTable:
     77      tableObj.role = ROLE_TABLE;
     78      break;
     79    case kTreeTable:
     80      tableObj.role = ROLE_TREE_TABLE;
     81      break;
     82    case kMathTable:
     83      tableObj.role = ROLE_MATHML_TABLE;
     84      break;
     85  }
     86 
     87  // caption accessible handling
     88  if (aCaption) {
     89    var captionObj = {
     90      role: ROLE_CAPTION,
     91      children: [
     92        {
     93          role: ROLE_TEXT_LEAF,
     94          name: aCaption,
     95        },
     96      ],
     97    };
     98 
     99    tableObj.children.push(captionObj);
    100  }
    101 
    102  // special types of column headers handling
    103  if (aColHeaderType) {
    104    var headersObj = {
    105      role: ROLE_LIST,
    106      children: [],
    107    };
    108 
    109    for (let idx = 0; idx < colsCount; idx++) {
    110      var headerCellObj = {
    111        role: ROLE_COLUMNHEADER,
    112      };
    113      headersObj.children.push(headerCellObj);
    114    }
    115 
    116    if (aColHeaderType == kTreeColumnHeader) {
    117      headersObj.children.push({
    118        role: ROLE_PUSHBUTTON,
    119      });
    120      headersObj.children.push({
    121        role: ROLE_MENUPOPUP,
    122      });
    123    }
    124 
    125    tableObj.children.push(headersObj);
    126  }
    127 
    128  // rows and cells accessibles
    129  for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    130    let rowObj = {
    131      role: aRowRoles ? aRowRoles[rowIdx] : ROLE_ROW,
    132      children: [],
    133    };
    134 
    135    for (let colIdx = 0; colIdx < colsCount; colIdx++) {
    136      let celltype = aCellsArray[rowIdx][colIdx];
    137 
    138      var role = ROLE_NOTHING;
    139      switch (celltype) {
    140        case kDataCell:
    141          role =
    142            aTableType == kMathTable
    143              ? ROLE_MATHML_CELL
    144              : isGrid
    145                ? ROLE_GRID_CELL
    146                : ROLE_CELL;
    147          break;
    148        case kRowHeaderCell:
    149          role = ROLE_ROWHEADER;
    150          break;
    151        case kColHeaderCell:
    152          role = ROLE_COLUMNHEADER;
    153          break;
    154      }
    155 
    156      if (role != ROLE_NOTHING) {
    157        var cellObj = { role };
    158        rowObj.children.push(cellObj);
    159      }
    160    }
    161 
    162    tableObj.children.push(rowObj);
    163  }
    164 
    165  testAccessibleTree(aIdentifier, tableObj);
    166 
    167  // Test table table interface.
    168  var table = getAccessible(aIdentifier, [nsIAccessibleTable]);
    169 
    170  // summary
    171  if (aSummary) {
    172    is(
    173      table.summary,
    174      aSummary,
    175      "Wrong summary of the table " + prettyName(aIdentifier)
    176    );
    177  }
    178 
    179  // rowCount and columnCount
    180  is(
    181    table.rowCount,
    182    rowCount,
    183    "Wrong rows count of " + prettyName(aIdentifier)
    184  );
    185  is(
    186    table.columnCount,
    187    colsCount,
    188    "Wrong columns count of " + prettyName(aIdentifier)
    189  );
    190 
    191  // rows and columns extents
    192  for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    193    for (let colIdx = 0; colIdx < colsCount; colIdx++) {
    194      let celltype = aCellsArray[rowIdx][colIdx];
    195      if (celltype & kOrigin) {
    196        // table getRowExtentAt
    197        var rowExtent = table.getRowExtentAt(rowIdx, colIdx);
    198        let idx;
    199        /* eslint-disable no-empty */
    200        for (
    201          idx = rowIdx + 1;
    202          idx < rowCount && aCellsArray[idx][colIdx] & kRowSpanned;
    203          idx++
    204        ) {}
    205        /* eslint-enable no-empty */
    206 
    207        var expectedRowExtent = idx - rowIdx;
    208        is(
    209          rowExtent,
    210          expectedRowExtent,
    211          "getRowExtentAt: Wrong number of spanned rows at (" +
    212            rowIdx +
    213            ", " +
    214            colIdx +
    215            ") for " +
    216            prettyName(aIdentifier)
    217        );
    218 
    219        // table getColumnExtentAt
    220        var colExtent = table.getColumnExtentAt(rowIdx, colIdx);
    221        /* eslint-disable no-empty */
    222        for (
    223          idx = colIdx + 1;
    224          idx < colsCount && aCellsArray[rowIdx][idx] & kColSpanned;
    225          idx++
    226        ) {}
    227        /* eslint-enable no-empty */
    228 
    229        var expectedColExtent = idx - colIdx;
    230        is(
    231          colExtent,
    232          expectedColExtent,
    233          "getColumnExtentAt: Wrong number of spanned columns at (" +
    234            rowIdx +
    235            ", " +
    236            colIdx +
    237            ") for " +
    238            prettyName(aIdentifier)
    239        );
    240 
    241        // cell rowExtent and columnExtent
    242        var cell = getAccessible(table.getCellAt(rowIdx, colIdx), [
    243          nsIAccessibleTableCell,
    244        ]);
    245 
    246        is(
    247          cell.rowExtent,
    248          expectedRowExtent,
    249          "rowExtent: Wrong number of spanned rows at (" +
    250            rowIdx +
    251            ", " +
    252            colIdx +
    253            ") for " +
    254            prettyName(aIdentifier)
    255        );
    256 
    257        is(
    258          cell.columnExtent,
    259          expectedColExtent,
    260          "columnExtent: Wrong number of spanned column at (" +
    261            rowIdx +
    262            ", " +
    263            colIdx +
    264            ") for " +
    265            prettyName(aIdentifier)
    266        );
    267      }
    268    }
    269  }
    270 }
    271 
    272 /**
    273 * Test table indexes.
    274 *
    275 * @param  aIdentifier  [in] table accessible identifier
    276 * @param  aIdxes       [in] two dimensional array of cell indexes
    277 */
    278 function testTableIndexes(aIdentifier, aIdxes) {
    279  var tableAcc = getAccessible(aIdentifier, [nsIAccessibleTable]);
    280  if (!tableAcc) {
    281    return;
    282  }
    283 
    284  var obtainedRowIdx, obtainedColIdx, obtainedIdx;
    285  var cellAcc;
    286 
    287  var id = prettyName(aIdentifier);
    288 
    289  var rowCount = aIdxes.length;
    290  for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    291    var colCount = aIdxes[rowIdx].length;
    292    for (var colIdx = 0; colIdx < colCount; colIdx++) {
    293      var idx = aIdxes[rowIdx][colIdx];
    294 
    295      // getCellAt
    296      try {
    297        cellAcc = null;
    298        cellAcc = tableAcc.getCellAt(rowIdx, colIdx);
    299      } catch (e) {}
    300 
    301      ok(
    302        (idx != -1 && cellAcc) || (idx == -1 && !cellAcc),
    303        id +
    304          ": Can't get cell accessible at row = " +
    305          rowIdx +
    306          ", column = " +
    307          colIdx
    308      );
    309 
    310      if (idx != -1) {
    311        // getRowIndexAt
    312        var origRowIdx = rowIdx;
    313        while (
    314          origRowIdx > 0 &&
    315          aIdxes[rowIdx][colIdx] == aIdxes[origRowIdx - 1][colIdx]
    316        ) {
    317          origRowIdx--;
    318        }
    319 
    320        try {
    321          obtainedRowIdx = tableAcc.getRowIndexAt(idx);
    322        } catch (e) {
    323          ok(
    324            false,
    325            id + ": can't get row index for cell index " + idx + "," + e
    326          );
    327        }
    328 
    329        is(
    330          obtainedRowIdx,
    331          origRowIdx,
    332          id + ": row for index " + idx + " is not correct (getRowIndexAt)"
    333        );
    334 
    335        // getColumnIndexAt
    336        var origColIdx = colIdx;
    337        while (
    338          origColIdx > 0 &&
    339          aIdxes[rowIdx][colIdx] == aIdxes[rowIdx][origColIdx - 1]
    340        ) {
    341          origColIdx--;
    342        }
    343 
    344        try {
    345          obtainedColIdx = tableAcc.getColumnIndexAt(idx);
    346        } catch (e) {
    347          ok(
    348            false,
    349            id + ": can't get column index for cell index " + idx + "," + e
    350          );
    351        }
    352 
    353        is(
    354          obtainedColIdx,
    355          origColIdx,
    356          id +
    357            ": column  for index " +
    358            idx +
    359            " is not correct (getColumnIndexAt)"
    360        );
    361 
    362        // getRowAndColumnIndicesAt
    363        var obtainedRowIdxObj = {},
    364          obtainedColIdxObj = {};
    365        try {
    366          tableAcc.getRowAndColumnIndicesAt(
    367            idx,
    368            obtainedRowIdxObj,
    369            obtainedColIdxObj
    370          );
    371        } catch (e) {
    372          ok(
    373            false,
    374            id +
    375              ": can't get row and column indices for cell index " +
    376              idx +
    377              "," +
    378              e
    379          );
    380        }
    381 
    382        is(
    383          obtainedRowIdxObj.value,
    384          origRowIdx,
    385          id +
    386            ": row for index " +
    387            idx +
    388            " is not correct (getRowAndColumnIndicesAt)"
    389        );
    390        is(
    391          obtainedColIdxObj.value,
    392          origColIdx,
    393          id +
    394            ": column  for index " +
    395            idx +
    396            " is not correct (getRowAndColumnIndicesAt)"
    397        );
    398 
    399        if (cellAcc) {
    400          var cellId = prettyName(cellAcc);
    401          cellAcc = getAccessible(cellAcc, [nsIAccessibleTableCell]);
    402 
    403          // cell: 'table-cell-index' attribute
    404          var attrs = cellAcc.attributes;
    405          var strIdx = "";
    406          try {
    407            strIdx = attrs.getStringProperty("table-cell-index");
    408          } catch (e) {
    409            ok(
    410              false,
    411              cellId +
    412                ": no cell index from object attributes on the cell accessible at index " +
    413                idx +
    414                "."
    415            );
    416          }
    417 
    418          if (strIdx) {
    419            is(
    420              parseInt(strIdx),
    421              idx,
    422              cellId +
    423                ": cell index from object attributes of cell accessible isn't corrent."
    424            );
    425          }
    426 
    427          // cell: table
    428          try {
    429            is(
    430              cellAcc.table,
    431              tableAcc,
    432              cellId + ": wrong table accessible for the cell."
    433            );
    434          } catch (e) {
    435            ok(false, cellId + ": can't get table accessible from the cell.");
    436          }
    437 
    438          // cell: getRowIndex
    439          try {
    440            obtainedRowIdx = cellAcc.rowIndex;
    441          } catch (e) {
    442            ok(
    443              false,
    444              cellId +
    445                ": can't get row index of the cell at index " +
    446                idx +
    447                "," +
    448                e
    449            );
    450          }
    451 
    452          is(
    453            obtainedRowIdx,
    454            origRowIdx,
    455            cellId + ": row for the cell at index " + idx + " is not correct"
    456          );
    457 
    458          // cell: getColumnIndex
    459          try {
    460            obtainedColIdx = cellAcc.columnIndex;
    461          } catch (e) {
    462            ok(
    463              false,
    464              cellId +
    465                ": can't get column index of the cell at index " +
    466                idx +
    467                "," +
    468                e
    469            );
    470          }
    471 
    472          is(
    473            obtainedColIdx,
    474            origColIdx,
    475            id + ": column for the cell at index " + idx + " is not correct"
    476          );
    477        }
    478      }
    479 
    480      // getCellIndexAt
    481      try {
    482        obtainedIdx = tableAcc.getCellIndexAt(rowIdx, colIdx);
    483      } catch (e) {
    484        obtainedIdx = -1;
    485      }
    486 
    487      is(
    488        obtainedIdx,
    489        idx,
    490        id +
    491          ": row " +
    492          rowIdx +
    493          " /column " +
    494          colIdx +
    495          " and index " +
    496          obtainedIdx +
    497          " aren't inconsistent."
    498      );
    499    }
    500  }
    501 }
    502 
    503 /**
    504 * Test table getters selection methods.
    505 *
    506 * @param  aIdentifier  [in] table accessible identifier
    507 * @param  aCellsArray  [in] two dimensional array (row X columns) of cells
    508 *                       states (either boolean (selected/unselected) if cell is
    509 *                       origin, otherwise kRowSpanned or kColSpanned constant).
    510 * @param  aMsg         [in] text appended before every message
    511 */
    512 function testTableSelection(aIdentifier, aCellsArray, aMsg) {
    513  var msg = aMsg ? aMsg : "";
    514  var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
    515  if (!acc) {
    516    return;
    517  }
    518 
    519  var rowCount = aCellsArray.length;
    520  var colsCount = aCellsArray[0].length;
    521 
    522  // Columns selection tests.
    523  var selCols = [];
    524 
    525  // isColumnSelected test
    526  for (let colIdx = 0; colIdx < colsCount; colIdx++) {
    527    var isColSelected = true;
    528    for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    529      if (
    530        !aCellsArray[rowIdx][colIdx] ||
    531        aCellsArray[rowIdx][colIdx] == undefined
    532      ) {
    533        isColSelected = false;
    534        break;
    535      }
    536    }
    537 
    538    is(
    539      acc.isColumnSelected(colIdx),
    540      isColSelected,
    541      msg +
    542        "Wrong selection state of " +
    543        colIdx +
    544        " column for " +
    545        prettyName(aIdentifier)
    546    );
    547 
    548    if (isColSelected) {
    549      selCols.push(colIdx);
    550    }
    551  }
    552 
    553  // selectedColsCount test
    554  is(
    555    acc.selectedColumnCount,
    556    selCols.length,
    557    msg + "Wrong count of selected columns for " + prettyName(aIdentifier)
    558  );
    559 
    560  // getSelectedColumns test
    561  var actualSelCols = acc.getSelectedColumnIndices();
    562 
    563  var actualSelColsCount = actualSelCols.length;
    564  is(
    565    actualSelColsCount,
    566    selCols.length,
    567    msg +
    568      "Wrong count of selected columns for " +
    569      prettyName(aIdentifier) +
    570      "from getSelectedColumns."
    571  );
    572 
    573  for (let i = 0; i < actualSelColsCount; i++) {
    574    is(
    575      actualSelCols[i],
    576      selCols[i],
    577      msg + "Column at index " + selCols[i] + " should be selected."
    578    );
    579  }
    580 
    581  // Rows selection tests.
    582  var selRows = [];
    583 
    584  // isRowSelected test
    585  for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    586    var isRowSelected = true;
    587    for (let colIdx = 0; colIdx < colsCount; colIdx++) {
    588      if (
    589        !aCellsArray[rowIdx][colIdx] ||
    590        aCellsArray[rowIdx][colIdx] == undefined
    591      ) {
    592        isRowSelected = false;
    593        break;
    594      }
    595    }
    596 
    597    is(
    598      acc.isRowSelected(rowIdx),
    599      isRowSelected,
    600      msg +
    601        "Wrong selection state of " +
    602        rowIdx +
    603        " row for " +
    604        prettyName(aIdentifier)
    605    );
    606 
    607    if (isRowSelected) {
    608      selRows.push(rowIdx);
    609    }
    610  }
    611 
    612  // selectedRowCount test
    613  is(
    614    acc.selectedRowCount,
    615    selRows.length,
    616    msg + "Wrong count of selected rows for " + prettyName(aIdentifier)
    617  );
    618 
    619  // getSelectedRows test
    620  var actualSelRows = acc.getSelectedRowIndices();
    621 
    622  var actualSelrowCount = actualSelRows.length;
    623  is(
    624    actualSelrowCount,
    625    selRows.length,
    626    msg +
    627      "Wrong count of selected rows for " +
    628      prettyName(aIdentifier) +
    629      "from getSelectedRows."
    630  );
    631 
    632  for (let i = 0; i < actualSelrowCount; i++) {
    633    is(
    634      actualSelRows[i],
    635      selRows[i],
    636      msg + "Row at index " + selRows[i] + " should be selected."
    637    );
    638  }
    639 
    640  // Cells selection tests.
    641  var selCells = [];
    642 
    643  // isCellSelected test
    644  for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    645    for (let colIdx = 0; colIdx < colsCount; colIdx++) {
    646      if (aCellsArray[rowIdx][colIdx] & kSpanned) {
    647        continue;
    648      }
    649 
    650      var isSelected = !!aCellsArray[rowIdx][colIdx];
    651      is(
    652        acc.isCellSelected(rowIdx, colIdx),
    653        isSelected,
    654        msg +
    655          "Wrong selection state of cell at " +
    656          rowIdx +
    657          " row and " +
    658          colIdx +
    659          " column for " +
    660          prettyName(aIdentifier)
    661      );
    662 
    663      if (aCellsArray[rowIdx][colIdx]) {
    664        selCells.push(acc.getCellIndexAt(rowIdx, colIdx));
    665      }
    666    }
    667  }
    668 
    669  // selectedCellCount tests
    670  is(
    671    acc.selectedCellCount,
    672    selCells.length,
    673    msg + "Wrong count of selected cells for " + prettyName(aIdentifier)
    674  );
    675 
    676  // getSelectedCellIndices test
    677  var actualSelCells = acc.getSelectedCellIndices();
    678 
    679  var actualSelCellsCount = actualSelCells.length;
    680  is(
    681    actualSelCellsCount,
    682    selCells.length,
    683    msg +
    684      "Wrong count of selected cells for " +
    685      prettyName(aIdentifier) +
    686      "from getSelectedCells."
    687  );
    688 
    689  for (let i = 0; i < actualSelCellsCount; i++) {
    690    is(
    691      actualSelCells[i],
    692      selCells[i],
    693      msg +
    694        "getSelectedCellIndices: Cell at index " +
    695        selCells[i] +
    696        " should be selected."
    697    );
    698  }
    699 
    700  // selectedCells and isSelected tests
    701  var actualSelCellsArray = acc.selectedCells;
    702  for (let i = 0; i < actualSelCellsCount; i++) {
    703    var actualSelCellAccessible = actualSelCellsArray.queryElementAt(
    704      i,
    705      nsIAccessibleTableCell
    706    );
    707 
    708    let colIdx = acc.getColumnIndexAt(selCells[i]);
    709    let rowIdx = acc.getRowIndexAt(selCells[i]);
    710    var expectedSelCellAccessible = acc.getCellAt(rowIdx, colIdx);
    711 
    712    is(
    713      actualSelCellAccessible,
    714      expectedSelCellAccessible,
    715      msg +
    716        "getSelectedCells: Cell at index " +
    717        selCells[i] +
    718        " should be selected."
    719    );
    720 
    721    ok(
    722      actualSelCellAccessible.isSelected(),
    723      "isSelected: Cell at index " + selCells[i] + " should be selected."
    724    );
    725  }
    726 
    727  // selected states tests
    728  for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    729    for (let colIdx = 0; colIdx < colsCount; colIdx++) {
    730      if (aCellsArray[rowIdx][colIdx] & kSpanned) {
    731        continue;
    732      }
    733 
    734      var cell = acc.getCellAt(rowIdx, colIdx);
    735      var isSel = aCellsArray[rowIdx][colIdx];
    736      if (isSel == undefined) {
    737        testStates(cell, 0, 0, STATE_SELECTABLE | STATE_SELECTED);
    738      } else if (isSel) {
    739        testStates(cell, STATE_SELECTED);
    740      } else {
    741        testStates(cell, STATE_SELECTABLE, 0, STATE_SELECTED);
    742      }
    743    }
    744  }
    745 }
    746 
    747 /**
    748 * Test columnHeaderCells and rowHeaderCells of accessible table.
    749 */
    750 function testHeaderCells(aHeaderInfoMap) {
    751  for (var testIdx = 0; testIdx < aHeaderInfoMap.length; testIdx++) {
    752    var dataCellIdentifier = aHeaderInfoMap[testIdx].cell;
    753    var dataCell = getAccessible(dataCellIdentifier, [nsIAccessibleTableCell]);
    754 
    755    // row header cells
    756    var rowHeaderCells = aHeaderInfoMap[testIdx].rowHeaderCells;
    757    var rowHeaderCellsCount = rowHeaderCells.length;
    758    var actualRowHeaderCells = dataCell.rowHeaderCells;
    759    var actualRowHeaderCellsCount = actualRowHeaderCells.length;
    760 
    761    is(
    762      actualRowHeaderCellsCount,
    763      rowHeaderCellsCount,
    764      "Wrong number of row header cells for the cell " +
    765        prettyName(dataCellIdentifier)
    766    );
    767 
    768    if (actualRowHeaderCellsCount == rowHeaderCellsCount) {
    769      for (let idx = 0; idx < rowHeaderCellsCount; idx++) {
    770        var rowHeaderCell = getAccessible(rowHeaderCells[idx]);
    771        var actualRowHeaderCell = actualRowHeaderCells.queryElementAt(
    772          idx,
    773          nsIAccessible
    774        );
    775        isObject(
    776          actualRowHeaderCell,
    777          rowHeaderCell,
    778          "Wrong row header cell at index " +
    779            idx +
    780            " for the cell " +
    781            dataCellIdentifier
    782        );
    783      }
    784    }
    785 
    786    // column header cells
    787    var colHeaderCells = aHeaderInfoMap[testIdx].columnHeaderCells;
    788    var colHeaderCellsCount = colHeaderCells.length;
    789    var actualColHeaderCells = dataCell.columnHeaderCells;
    790    var actualColHeaderCellsCount = actualColHeaderCells.length;
    791 
    792    is(
    793      actualColHeaderCellsCount,
    794      colHeaderCellsCount,
    795      "Wrong number of column header cells for the cell " +
    796        prettyName(dataCellIdentifier)
    797    );
    798 
    799    if (actualColHeaderCellsCount == colHeaderCellsCount) {
    800      for (let idx = 0; idx < colHeaderCellsCount; idx++) {
    801        var colHeaderCell = getAccessible(colHeaderCells[idx]);
    802        var actualColHeaderCell = actualColHeaderCells.queryElementAt(
    803          idx,
    804          nsIAccessible
    805        );
    806        isObject(
    807          actualColHeaderCell,
    808          colHeaderCell,
    809          "Wrong column header cell at index " +
    810            idx +
    811            " for the cell " +
    812            dataCellIdentifier
    813        );
    814      }
    815    }
    816  }
    817 }
    818 
    819 // //////////////////////////////////////////////////////////////////////////////
    820 // private implementation
    821 
    822 /**
    823 * Return row and column of orig cell for the given spanned cell.
    824 */
    825 function getOrigRowAndColumn(aCellsArray, aRowIdx, aColIdx) {
    826  var cellState = aCellsArray[aRowIdx][aColIdx];
    827 
    828  var origRowIdx = aRowIdx,
    829    origColIdx = aColIdx;
    830  if (cellState & kRowSpanned) {
    831    for (var prevRowIdx = aRowIdx - 1; prevRowIdx >= 0; prevRowIdx--) {
    832      let prevCellState = aCellsArray[prevRowIdx][aColIdx];
    833      if (!(prevCellState & kRowSpanned)) {
    834        origRowIdx = prevRowIdx;
    835        break;
    836      }
    837    }
    838  }
    839 
    840  if (cellState & kColSpanned) {
    841    for (var prevColIdx = aColIdx - 1; prevColIdx >= 0; prevColIdx--) {
    842      let prevCellState = aCellsArray[aRowIdx][prevColIdx];
    843      if (!(prevCellState & kColSpanned)) {
    844        origColIdx = prevColIdx;
    845        break;
    846      }
    847    }
    848  }
    849 
    850  return [origRowIdx, origColIdx];
    851 }