gecko-dev/accessible/tests/mochitest/table.js
Julian Descottes 2fcd6cb020 Bug 1499096 - Update tests using ok() to is();r=Standard8
This changeset updates all the test that were wrongly using ok() and wanted to
use is() AND for which the assert is still passing without any modification
required.

Differential Revision: https://phabricator.services.mozilla.com/D8739

--HG--
extra : moz-landing-system : lando
2018-10-23 07:12:23 +00:00

767 lines
24 KiB
JavaScript

/**
* This file provides set of helper functions to test nsIAccessibleTable
* interface.
*
* Required:
* common.js
* role.js
* states.js
*/
/**
* Constants used to describe cells array.
*/
const kDataCell = 1; // Indicates the cell is origin data cell
const kRowHeaderCell = 2; // Indicates the cell is row header cell
const kColHeaderCell = 4; // Indicated the cell is column header cell
const kOrigin = kDataCell | kRowHeaderCell | kColHeaderCell;
const kRowSpanned = 8; // Indicates the cell is not origin and row spanned
const kColSpanned = 16; // Indicates the cell is not origin and column spanned
const kSpanned = kRowSpanned | kColSpanned;
/**
* Constants to define column header type.
*/
const kNoColumnHeader = 0;
const kListboxColumnHeader = 1;
const kTreeColumnHeader = 2;
/**
* Constants to define table type.
*/
const kTable = 0;
const kTreeTable = 1;
const kMathTable = 2;
/**
* Test table structure and related methods.
*
* @param aIdentifier [in] table accessible identifier
* @param aCellsArray [in] two dimensional array (row X columns) of
* cell types (see constants defined above).
* @param aColHeaderType [in] specifies wether column header cells are
* arranged into the list.
* @param aCaption [in] caption text if any
* @param aSummary [in] summary text if any
* @param aTableType [in] specifies the table type.
* @param aRowRoles [in] array of row roles.
*/
function testTableStruct(aIdentifier, aCellsArray, aColHeaderType,
aCaption, aSummary, aTableType, aRowRoles) {
var tableNode = getNode(aIdentifier);
var isGrid = tableNode.getAttribute("role") == "grid" ||
tableNode.getAttribute("role") == "treegrid" ||
tableNode.localName == "tree";
var rowCount = aCellsArray.length;
var colsCount = aCellsArray[0] ? aCellsArray[0].length : 0;
// Test table accessible tree.
var tableObj = {
children: [],
};
switch (aTableType) {
case kTable:
tableObj.role = ROLE_TABLE;
break;
case kTreeTable:
tableObj.role = ROLE_TREE_TABLE;
break;
case kMathTable:
tableObj.role = ROLE_MATHML_TABLE;
break;
}
// caption accessible handling
if (aCaption) {
var captionObj = {
role: ROLE_CAPTION,
children: [
{
role: ROLE_TEXT_LEAF,
name: aCaption,
},
],
};
tableObj.children.push(captionObj);
}
// special types of column headers handling
if (aColHeaderType) {
var headersObj = {
role: ROLE_LIST,
children: [],
};
for (let idx = 0; idx < colsCount; idx++) {
var headerCellObj = {
role: ROLE_COLUMNHEADER,
};
headersObj.children.push(headerCellObj);
}
if (aColHeaderType == kTreeColumnHeader) {
var columnPickerObj = {
role: ROLE_PUSHBUTTON,
};
headersObj.children.push(columnPickerObj);
}
tableObj.children.push(headersObj);
}
// rows and cells accessibles
for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
let rowObj = {
role: aRowRoles ? aRowRoles[rowIdx] : ROLE_ROW,
children: [],
};
for (let colIdx = 0; colIdx < colsCount; colIdx++) {
let celltype = aCellsArray[rowIdx][colIdx];
var role = ROLE_NOTHING;
switch (celltype) {
case kDataCell:
role = (aTableType == kMathTable ? ROLE_MATHML_CELL :
(isGrid ? ROLE_GRID_CELL : ROLE_CELL));
break;
case kRowHeaderCell:
role = ROLE_ROWHEADER;
break;
case kColHeaderCell:
role = ROLE_COLUMNHEADER;
break;
}
if (role != ROLE_NOTHING) {
var cellObj = { role };
rowObj.children.push(cellObj);
}
}
tableObj.children.push(rowObj);
}
testAccessibleTree(aIdentifier, tableObj);
// Test table table interface.
var table = getAccessible(aIdentifier, [nsIAccessibleTable]);
// summary
if (aSummary)
is(table.summary, aSummary,
"Wrong summary of the table " + prettyName(aIdentifier));
// rowCount and columnCount
is(table.rowCount, rowCount,
"Wrong rows count of " + prettyName(aIdentifier));
is(table.columnCount, colsCount,
"Wrong columns count of " + prettyName(aIdentifier));
// rows and columns extents
for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
for (let colIdx = 0; colIdx < colsCount; colIdx++) {
let celltype = aCellsArray[rowIdx][colIdx];
if (celltype & kOrigin) {
// table getRowExtentAt
var rowExtent = table.getRowExtentAt(rowIdx, colIdx);
let idx;
for (idx = rowIdx + 1;
idx < rowCount && (aCellsArray[idx][colIdx] & kRowSpanned);
idx++);
var expectedRowExtent = idx - rowIdx;
is(rowExtent, expectedRowExtent,
"getRowExtentAt: Wrong number of spanned rows at (" + rowIdx + ", " +
colIdx + ") for " + prettyName(aIdentifier));
// table getColumnExtentAt
var colExtent = table.getColumnExtentAt(rowIdx, colIdx);
for (idx = colIdx + 1;
idx < colsCount && (aCellsArray[rowIdx][idx] & kColSpanned);
idx++);
var expectedColExtent = idx - colIdx;
is(colExtent, expectedColExtent,
"getColumnExtentAt: Wrong number of spanned columns at (" + rowIdx +
", " + colIdx + ") for " + prettyName(aIdentifier));
// cell rowExtent and columnExtent
var cell = getAccessible(table.getCellAt(rowIdx, colIdx),
[nsIAccessibleTableCell]);
is(cell.rowExtent, expectedRowExtent,
"rowExtent: Wrong number of spanned rows at (" + rowIdx + ", " +
colIdx + ") for " + prettyName(aIdentifier));
is(cell.columnExtent, expectedColExtent,
"columnExtent: Wrong number of spanned column at (" + rowIdx + ", " +
colIdx + ") for " + prettyName(aIdentifier));
}
}
}
}
/**
* Test table indexes.
*
* @param aIdentifier [in] table accessible identifier
* @param aIdxes [in] two dimensional array of cell indexes
*/
function testTableIndexes(aIdentifier, aIdxes) {
var tableAcc = getAccessible(aIdentifier, [nsIAccessibleTable]);
if (!tableAcc)
return;
var obtainedRowIdx, obtainedColIdx, obtainedIdx;
var cellAcc;
var id = prettyName(aIdentifier);
var rowCount = aIdxes.length;
for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
var colCount = aIdxes[rowIdx].length;
for (var colIdx = 0; colIdx < colCount; colIdx++) {
var idx = aIdxes[rowIdx][colIdx];
// getCellAt
try {
cellAcc = null;
cellAcc = tableAcc.getCellAt(rowIdx, colIdx);
} catch (e) { }
ok(idx != -1 && cellAcc || idx == -1 && !cellAcc,
id + ": Can't get cell accessible at row = " + rowIdx + ", column = " + colIdx);
if (idx != -1) {
// getRowIndexAt
var origRowIdx = rowIdx;
while (origRowIdx > 0 &&
aIdxes[rowIdx][colIdx] == aIdxes[origRowIdx - 1][colIdx])
origRowIdx--;
try {
obtainedRowIdx = tableAcc.getRowIndexAt(idx);
} catch (e) {
ok(false, id + ": can't get row index for cell index " + idx + "," + e);
}
is(obtainedRowIdx, origRowIdx,
id + ": row for index " + idx + " is not correct (getRowIndexAt)");
// getColumnIndexAt
var origColIdx = colIdx;
while (origColIdx > 0 &&
aIdxes[rowIdx][colIdx] == aIdxes[rowIdx][origColIdx - 1])
origColIdx--;
try {
obtainedColIdx = tableAcc.getColumnIndexAt(idx);
} catch (e) {
ok(false, id + ": can't get column index for cell index " + idx + "," + e);
}
is(obtainedColIdx, origColIdx,
id + ": column for index " + idx + " is not correct (getColumnIndexAt)");
// getRowAndColumnIndicesAt
var obtainedRowIdxObj = { }, obtainedColIdxObj = { };
try {
tableAcc.getRowAndColumnIndicesAt(idx, obtainedRowIdxObj,
obtainedColIdxObj);
} catch (e) {
ok(false, id + ": can't get row and column indices for cell index " + idx + "," + e);
}
is(obtainedRowIdxObj.value, origRowIdx,
id + ": row for index " + idx + " is not correct (getRowAndColumnIndicesAt)");
is(obtainedColIdxObj.value, origColIdx,
id + ": column for index " + idx + " is not correct (getRowAndColumnIndicesAt)");
if (cellAcc) {
var cellId = prettyName(cellAcc);
cellAcc = getAccessible(cellAcc, [nsIAccessibleTableCell]);
// cell: 'table-cell-index' attribute
var attrs = cellAcc.attributes;
var strIdx = "";
try {
strIdx = attrs.getStringProperty("table-cell-index");
} catch (e) {
ok(false,
cellId + ": no cell index from object attributes on the cell accessible at index " + idx + ".");
}
if (strIdx) {
is(parseInt(strIdx), idx,
cellId + ": cell index from object attributes of cell accessible isn't corrent.");
}
// cell: table
try {
is(cellAcc.table, tableAcc,
cellId + ": wrong table accessible for the cell.");
} catch (e) {
ok(false,
cellId + ": can't get table accessible from the cell.");
}
// cell: getRowIndex
try {
obtainedRowIdx = cellAcc.rowIndex;
} catch (e) {
ok(false,
cellId + ": can't get row index of the cell at index " + idx + "," + e);
}
is(obtainedRowIdx, origRowIdx,
cellId + ": row for the cell at index " + idx + " is not correct");
// cell: getColumnIndex
try {
obtainedColIdx = cellAcc.columnIndex;
} catch (e) {
ok(false,
cellId + ": can't get column index of the cell at index " + idx + "," + e);
}
is(obtainedColIdx, origColIdx,
id + ": column for the cell at index " + idx + " is not correct");
}
}
// getCellIndexAt
try {
obtainedIdx = tableAcc.getCellIndexAt(rowIdx, colIdx);
} catch (e) {
obtainedIdx = -1;
}
is(obtainedIdx, idx,
id + ": row " + rowIdx + " /column " + colIdx + " and index " + obtainedIdx + " aren't inconsistent.");
}
}
}
/**
* Test table getters selection methods.
*
* @param aIdentifier [in] table accessible identifier
* @param aCellsArray [in] two dimensional array (row X columns) of cells
* states (either boolean (selected/unselected) if cell is
* origin, otherwise kRowSpanned or kColSpanned constant).
* @param aMsg [in] text appended before every message
*/
function testTableSelection(aIdentifier, aCellsArray, aMsg) {
var msg = aMsg ? aMsg : "";
var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
if (!acc)
return;
var rowCount = aCellsArray.length;
var colsCount = aCellsArray[0].length;
// Columns selection tests.
var selCols = [];
// isColumnSelected test
for (let colIdx = 0; colIdx < colsCount; colIdx++) {
var isColSelected = true;
for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
if (!aCellsArray[rowIdx][colIdx] ||
aCellsArray[rowIdx][colIdx] == undefined) {
isColSelected = false;
break;
}
}
is(acc.isColumnSelected(colIdx), isColSelected,
msg + "Wrong selection state of " + colIdx + " column for " +
prettyName(aIdentifier));
if (isColSelected)
selCols.push(colIdx);
}
// selectedColsCount test
is(acc.selectedColumnCount, selCols.length,
msg + "Wrong count of selected columns for " + prettyName(aIdentifier));
// getSelectedColumns test
var actualSelColsCountObj = { value: null };
var actualSelCols = acc.getSelectedColumnIndices(actualSelColsCountObj);
var actualSelColsCount = actualSelColsCountObj.value;
is(actualSelColsCount, selCols.length,
msg + "Wrong count of selected columns for " + prettyName(aIdentifier) +
"from getSelectedColumns.");
for (let i = 0; i < actualSelColsCount; i++) {
is(actualSelCols[i], selCols[i],
msg + "Column at index " + selCols[i] + " should be selected.");
}
// Rows selection tests.
var selRows = [];
// isRowSelected test
for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
var isRowSelected = true;
for (let colIdx = 0; colIdx < colsCount; colIdx++) {
if (!aCellsArray[rowIdx][colIdx] ||
aCellsArray[rowIdx][colIdx] == undefined) {
isRowSelected = false;
break;
}
}
is(acc.isRowSelected(rowIdx), isRowSelected,
msg + "Wrong selection state of " + rowIdx + " row for " +
prettyName(aIdentifier));
if (isRowSelected)
selRows.push(rowIdx);
}
// selectedRowCount test
is(acc.selectedRowCount, selRows.length,
msg + "Wrong count of selected rows for " + prettyName(aIdentifier));
// getSelectedRows test
var actualSelrowCountObj = { value: null };
var actualSelRows = acc.getSelectedRowIndices(actualSelrowCountObj);
var actualSelrowCount = actualSelrowCountObj.value;
is(actualSelrowCount, selRows.length,
msg + "Wrong count of selected rows for " + prettyName(aIdentifier) +
"from getSelectedRows.");
for (let i = 0; i < actualSelrowCount; i++) {
is(actualSelRows[i], selRows[i],
msg + "Row at index " + selRows[i] + " should be selected.");
}
// Cells selection tests.
var selCells = [];
// isCellSelected test
for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
for (let colIdx = 0; colIdx < colsCount; colIdx++) {
if (aCellsArray[rowIdx][colIdx] & kSpanned)
continue;
var isSelected = !!aCellsArray[rowIdx][colIdx];
is(acc.isCellSelected(rowIdx, colIdx), isSelected,
msg + "Wrong selection state of cell at " + rowIdx + " row and " +
colIdx + " column for " + prettyName(aIdentifier));
if (aCellsArray[rowIdx][colIdx])
selCells.push(acc.getCellIndexAt(rowIdx, colIdx));
}
}
// selectedCellCount tests
is(acc.selectedCellCount, selCells.length,
msg + "Wrong count of selected cells for " + prettyName(aIdentifier));
// getSelectedCellIndices test
var actualSelCellsCountObj = { value: null };
var actualSelCells = acc.getSelectedCellIndices(actualSelCellsCountObj);
var actualSelCellsCount = actualSelCellsCountObj.value;
is(actualSelCellsCount, selCells.length,
msg + "Wrong count of selected cells for " + prettyName(aIdentifier) +
"from getSelectedCells.");
for (let i = 0; i < actualSelCellsCount; i++) {
is(actualSelCells[i], selCells[i],
msg + "getSelectedCellIndices: Cell at index " + selCells[i] +
" should be selected.");
}
// selectedCells and isSelected tests
var actualSelCellsArray = acc.selectedCells;
for (let i = 0; i < actualSelCellsCount; i++) {
var actualSelCellAccessible =
actualSelCellsArray.queryElementAt(i, nsIAccessibleTableCell);
let colIdx = acc.getColumnIndexAt(selCells[i]);
let rowIdx = acc.getRowIndexAt(selCells[i]);
var expectedSelCellAccessible = acc.getCellAt(rowIdx, colIdx);
is(actualSelCellAccessible, expectedSelCellAccessible,
msg + "getSelectedCells: Cell at index " + selCells[i] +
" should be selected.");
ok(actualSelCellAccessible.isSelected(),
"isSelected: Cell at index " + selCells[i] + " should be selected.");
}
// selected states tests
for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {
for (let colIdx = 0; colIdx < colsCount; colIdx++) {
if (aCellsArray[rowIdx][colIdx] & kSpanned)
continue;
var cell = acc.getCellAt(rowIdx, colIdx);
var isSel = aCellsArray[rowIdx][colIdx];
if (isSel == undefined)
testStates(cell, 0, 0, STATE_SELECTABLE | STATE_SELECTED);
else if (isSel)
testStates(cell, STATE_SELECTED);
else
testStates(cell, STATE_SELECTABLE, 0, STATE_SELECTED);
}
}
}
/**
* Test unselectColumn method of accessible table.
*/
function testUnselectTableColumn(aIdentifier, aColIdx, aCellsArray) {
var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
if (!acc)
return;
var rowCount = aCellsArray.length;
for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
// Unselect origin cell.
var [origRowIdx, origColIdx] =
getOrigRowAndColumn(aCellsArray, rowIdx, aColIdx);
aCellsArray[origRowIdx][origColIdx] = false;
}
acc.unselectColumn(aColIdx);
testTableSelection(aIdentifier, aCellsArray,
"Unselect " + aColIdx + " column: ");
}
/**
* Test selectColumn method of accessible table.
*/
function testSelectTableColumn(aIdentifier, aColIdx, aCellsArray) {
var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
if (!acc)
return;
var rowCount = aCellsArray.length;
var colsCount = aCellsArray[0].length;
for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
for (var colIdx = 0; colIdx < colsCount; colIdx++) {
var cellState = aCellsArray[rowIdx][colIdx];
if (colIdx == aColIdx) { // select target column
if (!(cellState & kSpanned)) {
// Select the cell if it is origin.
aCellsArray[rowIdx][colIdx] = true;
} else {
// If the cell is spanned then search origin cell and select it.
var [origRowIdx, origColIdx] = getOrigRowAndColumn(aCellsArray,
rowIdx, colIdx);
aCellsArray[origRowIdx][origColIdx] = true;
}
} else if (!(cellState & kSpanned)) { // unselect other columns
if (colIdx > aColIdx) {
// Unselect the cell if traversed column index is greater than column
// index of target cell.
aCellsArray[rowIdx][colIdx] = false;
} else if (!(aCellsArray[rowIdx][aColIdx] & kColSpanned)) {
// Unselect the cell if the target cell is not row spanned.
aCellsArray[rowIdx][colIdx] = false;
} else {
// Unselect the cell if it is not spanned to the target cell.
for (var spannedColIdx = colIdx + 1; spannedColIdx < aColIdx;
spannedColIdx++) {
var spannedCellState = aCellsArray[rowIdx][spannedColIdx];
if (!(spannedCellState & kRowSpanned)) {
aCellsArray[rowIdx][colIdx] = false;
break;
}
}
}
}
}
}
acc.selectColumn(aColIdx);
testTableSelection(aIdentifier, aCellsArray,
"Select " + aColIdx + " column: ");
}
/**
* Test unselectRow method of accessible table.
*/
function testUnselectTableRow(aIdentifier, aRowIdx, aCellsArray) {
var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
if (!acc)
return;
var colsCount = aCellsArray[0].length;
for (var colIdx = 0; colIdx < colsCount; colIdx++) {
// Unselect origin cell.
var [origRowIdx, origColIdx] = getOrigRowAndColumn(aCellsArray,
aRowIdx, colIdx);
aCellsArray[origRowIdx][origColIdx] = false;
}
acc.unselectRow(aRowIdx);
testTableSelection(aIdentifier, aCellsArray,
"Unselect " + aRowIdx + " row: ");
}
/**
* Test selectRow method of accessible table.
*/
function testSelectTableRow(aIdentifier, aRowIdx, aCellsArray) {
var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
if (!acc)
return;
var rowCount = aCellsArray.length;
var colsCount = aCellsArray[0].length;
for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
for (var colIdx = 0; colIdx < colsCount; colIdx++) {
var cellState = aCellsArray[rowIdx][colIdx];
if (rowIdx == aRowIdx) { // select the given row
if (!(cellState & kSpanned)) {
// Select the cell if it is origin.
aCellsArray[rowIdx][colIdx] = true;
} else {
// If the cell is spanned then search origin cell and select it.
var [origRowIdx, origColIdx] = getOrigRowAndColumn(aCellsArray,
rowIdx, colIdx);
aCellsArray[origRowIdx][origColIdx] = true;
}
} else if (!(cellState & kSpanned)) { // unselect other rows
if (rowIdx > aRowIdx) {
// Unselect the cell if traversed row index is greater than row
// index of target cell.
aCellsArray[rowIdx][colIdx] = false;
} else if (!(aCellsArray[aRowIdx][colIdx] & kRowSpanned)) {
// Unselect the cell if the target cell is not row spanned.
aCellsArray[rowIdx][colIdx] = false;
} else {
// Unselect the cell if it is not spanned to the target cell.
for (var spannedRowIdx = rowIdx + 1; spannedRowIdx < aRowIdx;
spannedRowIdx++) {
var spannedCellState = aCellsArray[spannedRowIdx][colIdx];
if (!(spannedCellState & kRowSpanned)) {
aCellsArray[rowIdx][colIdx] = false;
break;
}
}
}
}
}
}
acc.selectRow(aRowIdx);
testTableSelection(aIdentifier, aCellsArray,
"Select " + aRowIdx + " row: ");
}
/**
* Test columnHeaderCells and rowHeaderCells of accessible table.
*/
function testHeaderCells(aHeaderInfoMap) {
for (var testIdx = 0; testIdx < aHeaderInfoMap.length; testIdx++) {
var dataCellIdentifier = aHeaderInfoMap[testIdx].cell;
var dataCell = getAccessible(dataCellIdentifier, [nsIAccessibleTableCell]);
// row header cells
var rowHeaderCells = aHeaderInfoMap[testIdx].rowHeaderCells;
var rowHeaderCellsCount = rowHeaderCells.length;
var actualRowHeaderCells = dataCell.rowHeaderCells;
var actualRowHeaderCellsCount = actualRowHeaderCells.length;
is(actualRowHeaderCellsCount, rowHeaderCellsCount,
"Wrong number of row header cells for the cell " +
prettyName(dataCellIdentifier));
if (actualRowHeaderCellsCount == rowHeaderCellsCount) {
for (let idx = 0; idx < rowHeaderCellsCount; idx++) {
var rowHeaderCell = getAccessible(rowHeaderCells[idx]);
var actualRowHeaderCell =
actualRowHeaderCells.queryElementAt(idx, nsIAccessible);
isObject(actualRowHeaderCell, rowHeaderCell,
"Wrong row header cell at index " + idx + " for the cell " +
dataCellIdentifier);
}
}
// column header cells
var colHeaderCells = aHeaderInfoMap[testIdx].columnHeaderCells;
var colHeaderCellsCount = colHeaderCells.length;
var actualColHeaderCells = dataCell.columnHeaderCells;
var actualColHeaderCellsCount = actualColHeaderCells.length;
is(actualColHeaderCellsCount, colHeaderCellsCount,
"Wrong number of column header cells for the cell " +
prettyName(dataCellIdentifier));
if (actualColHeaderCellsCount == colHeaderCellsCount) {
for (let idx = 0; idx < colHeaderCellsCount; idx++) {
var colHeaderCell = getAccessible(colHeaderCells[idx]);
var actualColHeaderCell =
actualColHeaderCells.queryElementAt(idx, nsIAccessible);
isObject(actualColHeaderCell, colHeaderCell,
"Wrong column header cell at index " + idx + " for the cell " +
dataCellIdentifier);
}
}
}
}
// //////////////////////////////////////////////////////////////////////////////
// private implementation
/**
* Return row and column of orig cell for the given spanned cell.
*/
function getOrigRowAndColumn(aCellsArray, aRowIdx, aColIdx) {
var cellState = aCellsArray[aRowIdx][aColIdx];
var origRowIdx = aRowIdx, origColIdx = aColIdx;
if (cellState & kRowSpanned) {
for (var prevRowIdx = aRowIdx - 1; prevRowIdx >= 0; prevRowIdx--) {
let prevCellState = aCellsArray[prevRowIdx][aColIdx];
if (!(prevCellState & kRowSpanned)) {
origRowIdx = prevRowIdx;
break;
}
}
}
if (cellState & kColSpanned) {
for (var prevColIdx = aColIdx - 1; prevColIdx >= 0; prevColIdx--) {
let prevCellState = aCellsArray[aRowIdx][prevColIdx];
if (!(prevCellState & kColSpanned)) {
origColIdx = prevColIdx;
break;
}
}
}
return [origRowIdx, origColIdx];
}