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