summaryrefslogtreecommitdiffstats
path: root/accessible/tests/mochitest/table.js
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /accessible/tests/mochitest/table.js
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'accessible/tests/mochitest/table.js')
-rw-r--r--accessible/tests/mochitest/table.js778
1 files changed, 778 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/table.js b/accessible/tests/mochitest/table.js
new file mode 100644
index 000000000..e171594d6
--- /dev/null
+++ b/accessible/tests/mochitest/table.js
@@ -0,0 +1,778 @@
+/**
+ * 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 (var 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 (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
+ var rowObj = {
+ role: aRowRoles ? aRowRoles[rowIdx] : ROLE_ROW,
+ children: []
+ };
+
+ for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+ var 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: 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 (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
+ for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+ var celltype = aCellsArray[rowIdx][colIdx];
+ if (celltype & kOrigin) {
+
+ // table getRowExtentAt
+ var rowExtent = table.getRowExtentAt(rowIdx, colIdx);
+ for (var 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 (var 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 = new Array();
+
+ // isColumnSelected test
+ for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+ var isColSelected = true;
+ for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
+ if (aCellsArray[rowIdx][colIdx] == false ||
+ 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 (var i = 0; i < actualSelColsCount; i++) {
+ is (actualSelCols[i], selCols[i],
+ msg + "Column at index " + selCols[i] + " should be selected.");
+ }
+
+ // Rows selection tests.
+ var selRows = new Array();
+
+ // isRowSelected test
+ var selrowCount = 0;
+ for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
+ var isRowSelected = true;
+ for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+ if (aCellsArray[rowIdx][colIdx] == false ||
+ 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 (var i = 0; i < actualSelrowCount; i++) {
+ is (actualSelRows[i], selRows[i],
+ msg + "Row at index " + selRows[i] + " should be selected.");
+ }
+
+ // Cells selection tests.
+ var selCells = new Array();
+
+ // isCellSelected test
+ for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
+ for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+ if (aCellsArray[rowIdx][colIdx] & kSpanned)
+ continue;
+
+ var isSelected = aCellsArray[rowIdx][colIdx] == true;
+ 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 (var 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 (var i = 0; i < actualSelCellsCount; i++) {
+ var actualSelCellAccessible =
+ actualSelCellsArray.queryElementAt(i, nsIAccessibleTableCell);
+
+ var colIdx = acc.getColumnIndexAt(selCells[i]);
+ var rowIdx = acc.getRowIndexAt(selCells[i]);
+ var expectedSelCellAccessible = acc.getCellAt(rowIdx, colIdx);
+
+ ok(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 (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
+ for (var 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 == true)
+ 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++) {
+ var cellState = aCellsArray[rowIdx][aColIdx];
+ // 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 (var 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 (var 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--) {
+ var prevCellState = aCellsArray[prevRowIdx][aColIdx];
+ if (!(prevCellState & kRowSpanned)) {
+ origRowIdx = prevRowIdx;
+ break;
+ }
+ }
+ }
+
+ if (cellState & kColSpanned) {
+ for (var prevColIdx = aColIdx - 1; prevColIdx >= 0; prevColIdx--) {
+ var prevCellState = aCellsArray[aRowIdx][prevColIdx];
+ if (!(prevCellState & kColSpanned)) {
+ origColIdx = prevColIdx;
+ break;
+ }
+ }
+ }
+
+ return [origRowIdx, origColIdx];
+}