diff options
Diffstat (limited to '')
22 files changed, 4965 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/table.js b/accessible/tests/mochitest/table.js new file mode 100644 index 0000000000..dd6b455d3c --- /dev/null +++ b/accessible/tests/mochitest/table.js @@ -0,0 +1,1034 @@ +/** + * This file provides set of helper functions to test nsIAccessibleTable + * interface. + * + * Required: + * common.js + * role.js + * states.js + */ +/* import-globals-from common.js */ +/* import-globals-from role.js */ +/* import-globals-from 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) { + headersObj.children.push({ + role: ROLE_PUSHBUTTON, + }); + headersObj.children.push({ + role: ROLE_MENUPOPUP, + }); + } + + 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; + /* eslint-disable no-empty */ + for ( + idx = rowIdx + 1; + idx < rowCount && aCellsArray[idx][colIdx] & kRowSpanned; + idx++ + ) {} + /* eslint-enable no-empty */ + + 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); + /* eslint-disable no-empty */ + for ( + idx = colIdx + 1; + idx < colsCount && aCellsArray[rowIdx][idx] & kColSpanned; + idx++ + ) {} + /* eslint-enable no-empty */ + + 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 actualSelCols = acc.getSelectedColumnIndices(); + + var actualSelColsCount = actualSelCols.length; + 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 actualSelRows = acc.getSelectedRowIndices(); + + var actualSelrowCount = actualSelRows.length; + 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 actualSelCells = acc.getSelectedCellIndices(); + + var actualSelCellsCount = actualSelCells.length; + 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]; +} diff --git a/accessible/tests/mochitest/table/a11y.ini b/accessible/tests/mochitest/table/a11y.ini new file mode 100644 index 0000000000..550fc54e04 --- /dev/null +++ b/accessible/tests/mochitest/table/a11y.ini @@ -0,0 +1,24 @@ +[DEFAULT] +support-files = + !/accessible/tests/mochitest/*.js + +[test_css_tables.html] +[test_headers_ariagrid.html] +[test_headers_ariatable.html] +[test_headers_table.html] +[test_headers_tree.xhtml] +[test_indexes_ariagrid.html] +[test_indexes_table.html] +[test_indexes_tree.xhtml] +[test_layoutguess.html] +[test_mtable.html] +[test_sels_ariagrid.html] +[test_sels_table.html] +[test_sels_tree.xhtml] +[test_struct_ariagrid.html] +[test_struct_ariatreegrid.html] +[test_struct_table.html] +[test_struct_tree.xhtml] +[test_table_1.html] +[test_table_2.html] +[test_table_mutation.html] diff --git a/accessible/tests/mochitest/table/test_css_tables.html b/accessible/tests/mochitest/table/test_css_tables.html new file mode 100644 index 0000000000..65877564e4 --- /dev/null +++ b/accessible/tests/mochitest/table/test_css_tables.html @@ -0,0 +1,114 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <title>CSS display:table is not a table</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + + <script type="application/javascript"> + + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // elements with display:table + + // only display:table + var accTree = + { SECTION: [ + { TEXT_LEAF: [ ] }, + ] }; + testAccessibleTree("table1", accTree); + + // only display:table and display:table-cell + accTree = + { SECTION: [ + { SECTION: [ + { TEXT_LEAF: [ ] }, + ] }, + ] }; + testAccessibleTree("table2", accTree); + + // display:table, display:table-row, and display:table-cell + accTree = + { SECTION: [ + { SECTION: [ + { TEXT_LEAF: [ ] }, + ] }, + ] }; + testAccessibleTree("table3", accTree); + + // display:table, display:table-row-group, display:table-row, and display:table-cell + accTree = + { SECTION: [ + { SECTION: [ + { TEXT_LEAF: [ ] }, + ] }, + ] }; + testAccessibleTree("table4", accTree); + + // display:inline-table + accTree = + { TEXT_CONTAINER: [ + { TEXT_CONTAINER: [ + { TEXT_LEAF: [ ] }, + ] }, + ] }; + testAccessibleTree("table5", accTree); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <a target="_blank" + title=" div with display:table exposes table semantics" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=1007975">Mozilla Bug 1007975</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <div id="table1" style="display:table"> + table1 + </div> + + <div id="table2" style="display:table"> + <div style="display:table-cell">table2</div> + </div> + + <div id="table3" style="display:table"> + <div style="display:table-row"> + <div style="display:table-cell">table3</div> + </div> + </div> + + <div id="table4" style="display:table"> + <div style="display:table-row-group"> + <div style="display:table-row"> + <div style="display:table-cell">table4</div> + </div> + </div> + </div> + + <div> + <span id="table5" style="display:inline-table"> + <span style="display:table-row"> + <span style="display:table-cell">table5</div> + </span> + </span> + </div> + +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_headers_ariagrid.html b/accessible/tests/mochitest/table/test_headers_ariagrid.html new file mode 100644 index 0000000000..7b2c3f3dbf --- /dev/null +++ b/accessible/tests/mochitest/table/test_headers_ariagrid.html @@ -0,0 +1,183 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <title>Table header information cells for ARIA grid</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // column and row headers from markup + + let headerInfoMap = [ + { + cell: "table_dc_1", + rowHeaderCells: [ "table_rh_1" ], + columnHeaderCells: [ "table_ch_2" ], + }, + { + cell: "table_dc_2", + rowHeaderCells: [ "table_rh_1" ], + columnHeaderCells: [ "table_ch_3" ], + }, + { + cell: "table_dc_3", + rowHeaderCells: [ "table_rh_2" ], + columnHeaderCells: [ "table_ch_2" ], + }, + { + cell: "table_dc_4", + rowHeaderCells: [ "table_rh_2" ], + columnHeaderCells: [ "table_ch_3" ], + }, + { + cell: "table_rh_1", + rowHeaderCells: [], + columnHeaderCells: [ "table_ch_1" ], + }, + { + cell: "table_rh_2", + rowHeaderCells: [], + columnHeaderCells: [ "table_ch_1" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + + // //////////////////////////////////////////////////////////////////////// + // column and row headers from markup for grid. + + headerInfoMap = [ + { + // not focusable cell (ARIAGridCellAccessible is used) + cell: "table2_dc_1", + rowHeaderCells: [], + columnHeaderCells: [ "table2_ch_1" ], + }, + { + // focusable cell (ARIAGridCellAccessible is used) + cell: "table2_dc_2", + rowHeaderCells: [], + columnHeaderCells: [ "table2_ch_2" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + + // //////////////////////////////////////////////////////////////////////// + // column and row headers from markup for one more grid. + + headerInfoMap = [ + { + // ARIAGridCellAccessible is used + cell: "t3_dc_1", + rowHeaderCells: [ "t3_rh_1" ], + columnHeaderCells: [ ], + }, + { + // ARIAGridCellAccessible is used (inside rowgroup) + cell: "t3_dc_2", + rowHeaderCells: [ "t3_rh_2" ], + columnHeaderCells: [ ], + }, + ]; + + testHeaderCells(headerInfoMap); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <a target="_blank" + title="implement IAccessibleTable2" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424">Mozilla Bug 512424</a> + <a target="_blank" + title="nsHTMLTableCellAccessible is used in dojo's ARIA grid" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Mozilla Bug 513848</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <div role="grid"> + <div role="row"> + <span id="table_ch_1" role="columnheader">col_1</span> + <span id="table_ch_2" role="columnheader">col_2</span> + <span id="table_ch_3" role="columnheader">col_3</span> + </div> + <div role="row"> + <span id="table_rh_1" role="rowheader">row_1</span> + <span id="table_dc_1" role="gridcell">cell1</span> + <span id="table_dc_2" role="gridcell">cell2</span> + </div> + <div role="row"> + <span id="table_rh_2" role="rowheader">row_2</span> + <span id="table_dc_3" role="gridcell">cell3</span> + <span id="table_dc_4" role="gridcell">cell4</span> + </div> + </div> + + <div role="grid"> + <div role="row"> + <table role="presentation"> + <tr> + <td id="table2_ch_1" role="columnheader">header1</td> + <td id="table2_ch_2" role="columnheader">header2</td> + </tr> + </table> + </div> + <div role="row"> + <table role="presentation"> + <tr> + <td id="table2_dc_1" role="gridcell">cell1</td> + <td id="table2_dc_2" role="gridcell" tabindex="-1">cell2</td> + </tr> + </table> + </div> + </div> + + <div role="grid"> + <table role="presentation"> + <tbody role="presentation"> + <tr role="row"> + <th id="t3_rh_1" role="rowheader">Row 1</th> + <td id="t3_dc_1" role="gridcell" tabindex="-1"> + Apple Inc. + </td> + </tr> + </tbody> + </table> + <div role="rowgroup" tabindex="0"> + <table role="presentation"> + <tbody role="presentation"> + <tr role="row"> + <th id="t3_rh_2" role="rowheader">Row 2</th> + <td id="t3_dc_2" role="gridcell" tabindex="-1"> + Apple-Shmapple Inc. + </td> + </tr> + </tbody> + </table> + </div> + </div> + +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_headers_ariatable.html b/accessible/tests/mochitest/table/test_headers_ariatable.html new file mode 100644 index 0000000000..1af3813cdc --- /dev/null +++ b/accessible/tests/mochitest/table/test_headers_ariatable.html @@ -0,0 +1,94 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <title>Table header information cells for ARIA table</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // column and row headers from markup + + const headerInfoMap = [ + { + cell: "table_dc_1", + rowHeaderCells: [ "table_rh_1" ], + columnHeaderCells: [ "table_ch_2" ], + }, + { + cell: "table_dc_2", + rowHeaderCells: [ "table_rh_1" ], + columnHeaderCells: [ "table_ch_3" ], + }, + { + cell: "table_dc_3", + rowHeaderCells: [ "table_rh_2" ], + columnHeaderCells: [ "table_ch_2" ], + }, + { + cell: "table_dc_4", + rowHeaderCells: [ "table_rh_2" ], + columnHeaderCells: [ "table_ch_3" ], + }, + { + cell: "table_rh_1", + rowHeaderCells: [], + columnHeaderCells: [ "table_ch_1" ], + }, + { + cell: "table_rh_2", + rowHeaderCells: [], + columnHeaderCells: [ "table_ch_1" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <a target="_blank" + title="support ARIA table and cell roles" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=1173364">Bug 1173364</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <div role="table"> + <div role="row"> + <span id="table_ch_1" role="columnheader">col_1</span> + <span id="table_ch_2" role="columnheader">col_2</span> + <span id="table_ch_3" role="columnheader">col_3</span> + </div> + <div role="row"> + <span id="table_rh_1" role="rowheader">row_1</span> + <span id="table_dc_1" role="cell">cell1</span> + <span id="table_dc_2" role="cell">cell2</span> + </div> + <div role="row"> + <span id="table_rh_2" role="rowheader">row_2</span> + <span id="table_dc_3" role="cell">cell3</span> + <span id="table_dc_4" role="cell">cell4</span> + </div> + </div> + +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_headers_table.html b/accessible/tests/mochitest/table/test_headers_table.html new file mode 100644 index 0000000000..0d7dafff4b --- /dev/null +++ b/accessible/tests/mochitest/table/test_headers_table.html @@ -0,0 +1,756 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <title>Table header information cells for HTML table</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // column header from thead and row header from @scope inside of tfoot + + var headerInfoMap = [ + { + cell: "table1_cell_1", + rowHeaderCells: [], + columnHeaderCells: [ "table1_weekday", "table1_date" ], + }, + { + cell: "table1_cell_2", + rowHeaderCells: [], + columnHeaderCells: [ "table1_day", "table1_date" ], + }, + { + cell: "table1_cell_3", + rowHeaderCells: [], + columnHeaderCells: [ "table1_qty" ], + }, + { + cell: "table1_cell_4", + rowHeaderCells: [], + columnHeaderCells: [ "table1_weekday", "table1_date" ], + }, + { + cell: "table1_cell_5", + rowHeaderCells: [], + columnHeaderCells: [ "table1_day", "table1_date" ], + }, + { + cell: "table1_cell_6", + rowHeaderCells: [], + columnHeaderCells: [ "table1_qty" ], + }, + { + cell: "table1_cell_7", + rowHeaderCells: [ "table1_total" ], + columnHeaderCells: [ "table1_qty" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // column and row headers from thead and @scope + + headerInfoMap = [ + { + cell: "table2_cell_2", + rowHeaderCells: [ "table2_rh_1" ], + columnHeaderCells: [ "table2_ch_2" ], + }, + { + cell: "table2_cell_3", + rowHeaderCells: [ "table2_rh_1" ], + columnHeaderCells: [ "table2_ch_3" ], + }, + { + cell: "table2_cell_5", + rowHeaderCells: [ "table2_rh_2" ], + columnHeaderCells: [ "table2_ch_2" ], + }, + { + cell: "table2_cell_6", + rowHeaderCells: [ "table2_rh_2" ], + columnHeaderCells: [ "table2_ch_3" ], + }, + { + cell: "table2_rh_1", + rowHeaderCells: [], + columnHeaderCells: [ "table2_ch_1" ], + }, + { + cell: "table2_rh_2", + rowHeaderCells: [], + columnHeaderCells: [ "table2_ch_1" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // column headers from @headers + + headerInfoMap = [ + { + cell: "table3_cell_1", + rowHeaderCells: [], + columnHeaderCells: [ "table3_ch_1" ], + }, + { + cell: "table3_cell_2", + rowHeaderCells: [], + columnHeaderCells: [ "table3_ch_2" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // table consisted of one column + + headerInfoMap = [ + { + cell: "table4_cell", + rowHeaderCells: [], + columnHeaderCells: [ "table4_ch" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // table consisted of one row + + headerInfoMap = [ + { + cell: "table5_cell", + rowHeaderCells: [ "table5_rh" ], + columnHeaderCells: [ ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // @headers points to table cells + + headerInfoMap = [ + { + cell: "table6_cell", + rowHeaderCells: [ "table6_rh" ], + columnHeaderCells: [ "table6_ch" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // @scope="rowgroup" and @scope="row" + + headerInfoMap = [ + { + cell: "t7_r1c1", + rowHeaderCells: [ "t7_Mary", "t7_Females" ], + columnHeaderCells: [ "t7_1km" ], + }, + { + cell: "t7_r1c2", + rowHeaderCells: [ "t7_Mary", "t7_Females" ], + columnHeaderCells: [ "t7_5km" ], + }, + { + cell: "t7_r1c3", + rowHeaderCells: [ "t7_Mary", "t7_Females" ], + columnHeaderCells: [ "t7_10km" ], + }, + { + cell: "t7_r2c1", + rowHeaderCells: [ "t7_Betsy", "t7_Females" ], + columnHeaderCells: [ "t7_1km" ], + }, + { + cell: "t7_r2c2", + rowHeaderCells: [ "t7_Betsy", "t7_Females" ], + columnHeaderCells: [ "t7_5km" ], + }, + { + cell: "t7_r2c3", + rowHeaderCells: [ "t7_Betsy", "t7_Females" ], + columnHeaderCells: [ "t7_10km" ], + }, + { + cell: "t7_r3c1", + rowHeaderCells: [ "t7_Matt", "t7_Males" ], + columnHeaderCells: [ "t7_1km" ], + }, + { + cell: "t7_r3c2", + rowHeaderCells: [ "t7_Matt", "t7_Males" ], + columnHeaderCells: [ "t7_5km" ], + }, + { + cell: "t7_r3c3", + rowHeaderCells: [ "t7_Matt", "t7_Males" ], + columnHeaderCells: [ "t7_10km" ], + }, + { + cell: "t7_r4c1", + rowHeaderCells: [ "t7_Todd", "t7_Males" ], + columnHeaderCells: [ "t7_1km" ], + }, + { + cell: "t7_r4c2", + rowHeaderCells: [ "t7_Todd", "t7_Males" ], + columnHeaderCells: [ "t7_5km" ], + }, + { + cell: "t7_r4c3", + rowHeaderCells: [ "t7_Todd", "t7_Males" ], + columnHeaderCells: [ "t7_10km" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // @scope="colgroup" and @scope="col" + + headerInfoMap = [ + { + cell: "t8_r1c1", + rowHeaderCells: [ "t8_1km" ], + columnHeaderCells: [ "t8_Mary", "t8_Females" ], + }, + { + cell: "t8_r1c2", + rowHeaderCells: [ "t8_1km" ], + columnHeaderCells: [ "t8_Betsy", "t8_Females" ], + }, + { + cell: "t8_r1c3", + rowHeaderCells: [ "t8_1km" ], + columnHeaderCells: [ "t8_Matt", "t8_Males" ], + }, + { + cell: "t8_r1c4", + rowHeaderCells: [ "t8_1km" ], + columnHeaderCells: [ "t8_Todd", "t8_Males" ], + }, + { + cell: "t8_r2c1", + rowHeaderCells: [ "t8_5km" ], + columnHeaderCells: [ "t8_Mary", "t8_Females" ], + }, + { + cell: "t8_r2c2", + rowHeaderCells: [ "t8_5km" ], + columnHeaderCells: [ "t8_Betsy", "t8_Females" ], + }, + { + cell: "t8_r2c3", + rowHeaderCells: [ "t8_5km" ], + columnHeaderCells: [ "t8_Matt", "t8_Males" ], + }, + { + cell: "t8_r2c4", + rowHeaderCells: [ "t8_5km" ], + columnHeaderCells: [ "t8_Todd", "t8_Males" ], + }, + { + cell: "t8_r3c1", + rowHeaderCells: [ "t8_10km" ], + columnHeaderCells: [ "t8_Mary", "t8_Females" ], + }, + { + cell: "t8_r3c2", + rowHeaderCells: [ "t8_10km" ], + columnHeaderCells: [ "t8_Betsy", "t8_Females" ], + }, + { + cell: "t8_r3c3", + rowHeaderCells: [ "t8_10km" ], + columnHeaderCells: [ "t8_Matt", "t8_Males" ], + }, + { + cell: "t8_r3c4", + rowHeaderCells: [ "t8_10km" ], + columnHeaderCells: [ "t8_Todd", "t8_Males" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // spanned table header cells (v1), @headers define header order + + headerInfoMap = [ + { + cell: "t9_r1c1", + rowHeaderCells: [ "t9_females", "t9_mary" ], + columnHeaderCells: [ "t9_1km" ], + }, + { + cell: "t9_r1c2", + rowHeaderCells: [ "t9_females", "t9_mary" ], + columnHeaderCells: [ "t9_5km" ], + }, + { + cell: "t9_r1c3", + rowHeaderCells: [ "t9_females", "t9_mary" ], + columnHeaderCells: [ "t9_10km" ], + }, + { + cell: "t9_r2c1", + rowHeaderCells: [ "t9_females", "t9_betsy" ], + columnHeaderCells: [ "t9_1km" ], + }, + { + cell: "t9_r2c2", + rowHeaderCells: [ "t9_females", "t9_betsy" ], + columnHeaderCells: [ "t9_5km" ], + }, + { + cell: "t9_r2c3", + rowHeaderCells: [ "t9_females", "t9_betsy" ], + columnHeaderCells: [ "t9_10km" ], + }, + { + cell: "t9_r3c1", + rowHeaderCells: [ "t9_males", "t9_matt" ], + columnHeaderCells: [ "t9_1km" ], + }, + { + cell: "t9_r3c2", + rowHeaderCells: [ "t9_males", "t9_matt" ], + columnHeaderCells: [ "t9_5km" ], + }, + { + cell: "t9_r3c3", + rowHeaderCells: [ "t9_males", "t9_matt" ], + columnHeaderCells: [ "t9_10km" ], + }, + { + cell: "t9_r4c1", + rowHeaderCells: [ "t9_males", "t9_todd" ], + columnHeaderCells: [ "t9_1km" ], + }, + { + cell: "t9_r4c2", + rowHeaderCells: [ "t9_males", "t9_todd" ], + columnHeaderCells: [ "t9_5km" ], + }, + { + cell: "t9_r4c3", + rowHeaderCells: [ "t9_males", "t9_todd" ], + columnHeaderCells: [ "t9_10km" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // spanned table header cells (v2), @headers define header order + + headerInfoMap = [ + { + cell: "t10_r1c1", + rowHeaderCells: [ "t10_1km" ], + columnHeaderCells: [ "t10_females", "t10_mary" ], + }, + { + cell: "t10_r1c2", + rowHeaderCells: [ "t10_1km" ], + columnHeaderCells: [ "t10_females", "t10_betsy" ], + }, + { + cell: "t10_r1c3", + rowHeaderCells: [ "t10_1km" ], + columnHeaderCells: [ "t10_males", "t10_matt" ], + }, + { + cell: "t10_r1c4", + rowHeaderCells: [ "t10_1km" ], + columnHeaderCells: [ "t10_males", "t10_todd" ], + }, + { + cell: "t10_r2c1", + rowHeaderCells: [ "t10_5km" ], + columnHeaderCells: [ "t10_females", "t10_mary" ], + }, + { + cell: "t10_r2c2", + rowHeaderCells: [ "t10_5km" ], + columnHeaderCells: [ "t10_females", "t10_betsy" ], + }, + { + cell: "t10_r2c3", + rowHeaderCells: [ "t10_5km" ], + columnHeaderCells: [ "t10_males", "t10_matt" ], + }, + { + cell: "t10_r2c4", + rowHeaderCells: [ "t10_5km" ], + columnHeaderCells: [ "t10_males", "t10_todd" ], + }, + { + cell: "t10_r3c1", + rowHeaderCells: [ "t10_10km" ], + columnHeaderCells: [ "t10_females", "t10_mary" ], + }, + { + cell: "t10_r3c2", + rowHeaderCells: [ "t10_10km" ], + columnHeaderCells: [ "t10_females", "t10_betsy" ], + }, + { + cell: "t10_r3c3", + rowHeaderCells: [ "t10_10km" ], + columnHeaderCells: [ "t10_males", "t10_matt" ], + }, + { + cell: "t10_r3c4", + rowHeaderCells: [ "t10_10km" ], + columnHeaderCells: [ "t10_males", "t10_todd" ], + }, + ]; + + testHeaderCells(headerInfoMap); + + // //////////////////////////////////////////////////////////////////////// + // Ensure correct column headers after colspan in a previous row. + headerInfoMap = [ + { + cell: "t11r1c1", + columnHeaderCells: [], + rowHeaderCells: [], + }, + { + cell: "t11r1c2", + columnHeaderCells: [], + rowHeaderCells: [], + }, + { + cell: "t11r2c1_2", + columnHeaderCells: ["t11r1c1"], + rowHeaderCells: [], + }, + { + cell: "t11r3c1", + columnHeaderCells: ["t11r1c1"], + rowHeaderCells: [], + }, + { + cell: "t11r3c2", + columnHeaderCells: ["t11r1c2"], + rowHeaderCells: [], + }, + ]; + testHeaderCells(headerInfoMap); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <a target="_blank" + title="implement IAccessibleTable2" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424"> + Bug 512424 + </a> + <a target="_blank" + title="Table headers not associated when header is a td element with no scope" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=704465"> + Bug 704465 + </a> + <a target="_blank" + title="Support rowgroup and colgroup HTML scope" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=1141978"> + Bug 1141978 + </a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <table id="table1" border="1"> + <thead> + <tr> + <th id="table1_date" colspan="2">Date</th> + <th id="table1_qty" rowspan="2">Qty</th> + </tr> + <tr> + <th id="table1_weekday">Weekday</th> + <th id="table1_day">Day</th> + </tr> + </thead> + <tbody> + <tr> + <td id="table1_cell_1">Mon</td> + <td id="table1_cell_2">1</td> + <td id="table1_cell_3">20</td> + </tr> + <tr> + <td id="table1_cell_4">Thu</td> + <td id="table1_cell_5">2</td> + <td id="table1_cell_6">15</td> + </tr> + </tbody> + <tfoot> + <tr> + <th id="table1_total" scope="row" colspan="2">Total</th> + <td id="table1_cell_7">35</td> + </tr> + </tfoot> + </table> + + <table id="table2" border="1"> + <thead> + <tr> + <th id="table2_ch_1">col1</th> + <th id="table2_ch_2">col2</th> + <td id="table2_ch_3" scope="col">col3</td> + </tr> + </thead> + <tbody> + <tr> + <th id="table2_rh_1">row1</th> + <td id="table2_cell_2">cell1</td> + <td id="table2_cell_3">cell2</td> + </tr> + <tr> + <td id="table2_rh_2" scope="row">row2</td> + <td id="table2_cell_5">cell3</td> + <td id="table2_cell_6">cell4</td> + </tr> + </tbody> + </table> + + <table id="table3" border="1"> + <tr> + <td id="table3_cell_1" headers="table3_ch_1">cell1</td> + <td id="table3_cell_2" headers="table3_ch_2">cell2</td> + </tr> + <tr> + <td id="table3_ch_1" scope="col">col1</td> + <td id="table3_ch_2" scope="col">col2</td> + </tr> + </table> + + <table id="table4"> + <thead> + <tr> + <th id="table4_ch">colheader</th> + </tr> + </thead> + <tbody> + <tr> + <td id="table4_cell">bla</td> + </tr> + </tbody> + </table> + + <table id="table5"> + <tr> + <th id="table5_rh">rowheader</th> + <td id="table5_cell">cell</td> + </tr> + </table> + + <table id="table6"> + <tr> + <td>empty cell</th> + <td id="table6_ch">colheader</td> + </tr> + <tr> + <td id="table6_rh">rowheader</th> + <td id="table6_cell" headers="table6_ch table6_rh">cell</td> + </tr> + </table> + + <table id="table7" class="data complex" border="1"> + <caption>Version 1 with rowgroup</caption> + <thead> + <tr> + <td colspan="2"> </td> + <th id="t7_1km" scope="col">1 km</th> + <th id="t7_5km" scope="col">5 km</th> + <th id="t7_10km" scope="col">10 km</th> + </tr> + </thead> + <tbody> + <tr> + <th id="t7_Females" rowspan="2" scope="rowgroup">Females</th> + <th id="t7_Mary" scope="row">Mary</th> + <td id="t7_r1c1">8:32</td> + <td id="t7_r1c2">28:04</td> + <td id="t7_r1c3">1:01:16</td> + </tr> + <tr> + <th id="t7_Betsy" scope="row">Betsy</th> + <td id="t7_r2c1">7:43</td> + <td id="t7_r2c2">26:47</td> + <td id="t7_r2c3">55:38</td> + </tr> + <tr> + <th id="t7_Males" rowspan="2" scope="rowgroup">Males</th> + <th id="t7_Matt" scope="row">Matt</th> + <td id="t7_r3c1">7:55</td> + <td id="t7_r3c2">27:29</td> + <td id="t7_r3c3">57:04</td> + </tr> + <tr> + <th id="t7_Todd" scope="row">Todd</th> + <td id="t7_r4c1">7:01</td> + <td id="t7_r4c2">24:21</td> + <td id="t7_r4c3">50:35</td> + </tr> + </tbody> + </table> + + <table id="table8" class="data complex" border="1"> + <caption>Version 2 with colgroup</caption> + <thead> + <tr> + <td rowspan="2"> </td> + <th id="t8_Females" colspan="2" scope="colgroup">Females</th> + <th id="t8_Males" colspan="2" scope="colgroup">Males</th> + </tr> + <tr> + <th id="t8_Mary" scope="col">Mary</th> + <th id="t8_Betsy" scope="col">Betsy</th> + <th id="t8_Matt" scope="col">Matt</th> + <th id="t8_Todd" scope="col">Todd</th> + </tr> + </thead> + <tbody> + <tr> + <th id="t8_1km" scope="row">1 km</th> + <td id="t8_r1c1">8:32</td> + <td id="t8_r1c2">7:43</td> + <td id="t8_r1c3">7:55</td> + <td id="t8_r1c4">7:01</td> + </tr> + <tr> + <th id="t8_5km" scope="row">5 km</th> + <td id="t8_r2c1">28:04</td> + <td id="t8_r2c2">26:47</td> + <td id="t8_r2c3">27:27</td> + <td id="t8_r2c4">24:21</td> + </tr> + <tr> + <th id="t8_10km" scope="row">10 km</th> + <td id="t8_r3c1">1:01:16</td> + <td id="t8_r3c2">55:38</td> + <td id="t8_r3c3">57:04</td> + <td id="t8_r3c4">50:35</td> + </tr> + + </tbody> + </table> + + <table id="table9" border="1"> + <caption> + Example 1 (row group headers): + </caption> + <tr> + <td colspan="2"><span class="offscreen">empty</span></td> + <th id="t9_1km" width="40">1 km</th> + <th id="t9_5km" width="35">5 km</th> + <th id="t9_10km" width="42">10 km</th> + </tr> + <tr> + <th id="t9_females" width="56" rowspan="2">Females</th> + <th id="t9_mary" width="39">Mary</th> + <td id="t9_r1c1" headers="t9_females t9_mary t9_1km">8:32</td> + <td id="t9_r1c2" headers="t9_females t9_mary t9_5km">28:04</td> + <td id="t9_r1c3" headers="t9_females t9_mary t9_10km">1:01:16</td> + </tr> + <tr> + <th id="t9_betsy">Betsy</th> + <td id="t9_r2c1" headers="t9_females t9_betsy t9_1km">7:43</td> + <td id="t9_r2c2" headers="t9_females t9_betsy t9_5km">26:47</td> + <td id="t9_r2c3" headers="t9_females t9_betsy t9_10km">55:38</td> + </tr> + <tr> + <th id="t9_males" rowspan="2">Males</th> + <th id="t9_matt">Matt</th> + <td id="t9_r3c1" headers="t9_males t9_matt t9_1km">7:55</td> + <td id="t9_r3c2" headers="t9_males t9_matt t9_5km">27:29</td> + <td id="t9_r3c3" headers="t9_males t9_matt t9_10km">57:04</td> + </tr> + <tr> + <th id="t9_todd">Todd</th> + <td id="t9_r4c1" headers="t9_males t9_todd t9_1km">7:01</td> + <td id="t9_r4c2" headers="t9_males t9_todd t9_5km">24:21</td> + <td id="t9_r4c3" headers="t9_males t9_todd t9_10km">50:35</td> + </tr> + </table> + + <table id="table10" border="1"> + <caption> + Example 2 (column group headers): + </caption> + <tr> + <td rowspan="2"><span class="offscreen">empty</span></td> + <th colspan="2" id="t10_females">Females</th> + <th colspan="2" id="t10_males">Males</th> + </tr> + <tr> + <th width="40" id="t10_mary">Mary</th> + <th width="35" id="t10_betsy">Betsy</th> + <th width="42" id="t10_matt">Matt</th> + <th width="42" id="t10_todd">Todd</th> + </tr> + <tr> + <th width="39" id="t10_1km">1 km</th> + <td headers="t10_females t10_mary t10_1km" id="t10_r1c1">8:32</td> + <td headers="t10_females t10_betsy t10_1km" id="t10_r1c2">7:43</td> + <td headers="t10_males t10_matt t10_1km" id="t10_r1c3">7:55</td> + <td headers="t10_males t10_todd t10_1km" id="t10_r1c4">7:01</td> + </tr> + <tr> + <th id="t10_5km">5 km</th> + <td headers="t10_females t10_mary t10_5km" id="t10_r2c1">28:04</td> + <td headers="t10_females t10_betsy t10_5km" id="t10_r2c2">26:47</td> + <td headers="t10_males t10_matt t10_5km" id="t10_r2c3">27:29</td> + <td headers="t10_males t10_todd t10_5km" id="t10_r2c4">24:21</td> + </tr> + <tr> + <th id="t10_10km">10 km</th> + <td headers="t10_females t10_mary t10_10km" id="t10_r3c1">1:01:16</td> + <td headers="t10_females t10_betsy t10_10km" id="t10_r3c2">55:38</td> + <td headers="t10_males t10_matt t10_10km" id="t10_r3c3">57:04</td> + <td headers="t10_males t10_todd t10_10km" id="t10_r3c4">50:35</td> + </tr> + </table> + + <table id="table11"> + <tr> + <th id="t11r1c1">a</th> + <th id="t11r1c2">b</th> + </tr> + <tr> + <td id="t11r2c1_2" colspan="2"></td> + </tr> + <tr> + <td id="t11r3c1">e</td> + <td id="t11r3c2">f</td> + </tr> + </table> +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_headers_tree.xhtml b/accessible/tests/mochitest/table/test_headers_tree.xhtml new file mode 100644 index 0000000000..46e8f43126 --- /dev/null +++ b/accessible/tests/mochitest/table/test_headers_tree.xhtml @@ -0,0 +1,100 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + title="Table header information cells for XUL tree"> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + + <script type="application/javascript" + src="../treeview.js" /> + + <script type="application/javascript" + src="../common.js" /> + <script type="application/javascript" + src="../events.js" /> + <script type="application/javascript" + src="../table.js" /> + + <script type="application/javascript"> + <![CDATA[ + //////////////////////////////////////////////////////////////////////////// + // Test + + // gA11yEventDumpID = "debug"; + + function doTest() + { + var treeAcc = getAccessible("tree", [nsIAccessibleTable]); + + var headerInfoMap = [ + { + cell: treeAcc.getCellAt(0, 0), + rowHeaderCells: [], + columnHeaderCells: [ "col" ] + }, + { + cell: treeAcc.getCellAt(0, 1), + rowHeaderCells: [], + columnHeaderCells: [ "scol" ] + }, + { + cell: treeAcc.getCellAt(1, 0), + rowHeaderCells: [], + columnHeaderCells: [ "col" ] + }, + { + cell: treeAcc.getCellAt(1, 1), + rowHeaderCells: [], + columnHeaderCells: [ "scol" ] + }, + { + cell: treeAcc.getCellAt(2, 0), + rowHeaderCells: [], + columnHeaderCells: [ "col" ] + }, + { + cell: treeAcc.getCellAt(2, 1), + rowHeaderCells: [], + columnHeaderCells: [ "scol" ] + }, + ]; + + testHeaderCells(headerInfoMap); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yXULTreeLoadEvent(doTest, "tree", new nsTableTreeView(3)); + ]]> + </script> + + <hbox flex="1" style="overflow: auto;"> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424" + title="implement IAccessibleTable2"> + Mozilla Bug 512424 + </a><br/> + <p id="display"></p> + <div id="content" style="display: none"> + </div> + <pre id="test"> + </pre> + </body> + + <vbox id="debug"/> + <tree id="tree" flex="1"> + <treecols> + <treecol id="col" flex="1" primary="true" label="column"/> + <treecol id="scol" flex="1" label="column 2"/> + </treecols> + <treechildren id="treechildren"/> + </tree> + </hbox> + +</window> + diff --git a/accessible/tests/mochitest/table/test_indexes_ariagrid.html b/accessible/tests/mochitest/table/test_indexes_ariagrid.html new file mode 100644 index 0000000000..564e141a70 --- /dev/null +++ b/accessible/tests/mochitest/table/test_indexes_ariagrid.html @@ -0,0 +1,159 @@ +<!DOCTYPE html> +<html> +<head> + <title>Table indexes for ARIA grid tests</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../attributes.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // ARIA grid + var idxes = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11], + ]; + testTableIndexes("grid", idxes); + + idxes = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11], + ]; + testTableIndexes("grid-rowgroups", idxes); + + // //////////////////////////////////////////////////////////////////////// + // a bit strange ARIA grid + idxes = [ + [0, 1], + [2, 3], + ]; + testTableIndexes("grid2", idxes); + + // an ARIA grid with div wrapping cell and div wrapping row + idxes = [ + [0, 1], + [2, 3], + [4, 5], + ]; + testTableIndexes("grid3", idxes); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> +<body> + + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=386813" + title="support nsIAccessibleTable on ARIA grid/treegrid">Mozilla Bug 386813</a> + <a target="_blank" + title="nsHTMLTableCellAccessible is used in dojo's ARIA grid" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Mozilla Bug 513848</a> + <a target="_blank" + title="ARIA grid with rowgroup breaks table row/col counting and indices" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=761853">Mozilla Bug 761853</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <div role="grid" id="grid"> + <div role="row"> + <span role="columnheader">column1</span> + <span role="columnheader">column2</span> + <span role="columnheader">column3</span> + </div> + <div role="row"> + <span role="rowheader">row1</span> + <span role="gridcell">cell1</span> + <span role="gridcell">cell2</span> + </div> + <div role="row"> + <span role="rowheader">row2</span> + <span role="gridcell">cell3</span> + <span role="gridcell">cell4</span> + </div> + <div role="row"> + <span role="rowheader">row3</span> + <span role="gridcell">cell5</span> + <span role="gridcell">cell6</span> + </div> + </div> + + <div role="grid" id="grid-rowgroups"> + <div role="row"> + <span role="columnheader">grid-rowgroups-col1</span> + <span role="columnheader">grid-rowgroups-col2</span> + <span role="columnheader">grid-rowgroups-col3</span> + </div> + <div role="rowgroup"> + <div role="row"> + <span role="rowheader">grid-rowgroups-row1</span> + <span role="gridcell">grid-rowgroups-cell1</span> + <span role="gridcell">grid-rowgroups-cell2</span> + </div> + <div role="row"> + <span role="rowheader">grid-rowgroups-row2</span> + <span role="gridcell">grid-rowgroups-cell3</span> + <span role="gridcell">grid-rowgroups-cell4</span> + </div> + </div> + <div role="row"> + <span role="rowheader">grid-rowgroups-row3</span> + <span role="gridcell">grid-rowgroups-cell5</span> + <span role="gridcell">grid-rowgroups-cell6</span> + </div> + </div> + + <div role="grid" id="grid2"> + <div role="row"> + <table role="presentation"> + <tr> + <td role="columnheader">header1</td> + <td role="columnheader">header2</td> + </tr> + </table> + </div> + <div role="row"> + <table role="presentation"> + <tr> + <td role="gridcell">cell1</td> + <td role="gridcell" tabindex="-1">cell2</td> + </tr> + </table> + </div> + </div> + + <div role="grid" id="grid3"> + <div role="row"> + <div role="gridcell">Normal cell</div> + <div role="gridcell">1</div> + </div> + <div role="row"> + <div role="gridcell">Div</div> + <div><div role="gridcell">2</div></div> + </div> + <div tabindex="-1"><div role="row"> + <div role="gridcell">Cell in row in div</div> + <div role="gridcell">3</div> + </div></div> + </div> +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_indexes_table.html b/accessible/tests/mochitest/table/test_indexes_table.html new file mode 100644 index 0000000000..c43dbad8f7 --- /dev/null +++ b/accessible/tests/mochitest/table/test_indexes_table.html @@ -0,0 +1,481 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=410052 +--> +<head> + <title>Table indexes chrome tests</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // table + var idxes = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 7], + [6, 8, 9], + ]; + + testTableIndexes("table", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableborder + idxes = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 7], + [6, 8, 9], + ]; + + testTableIndexes("tableborder", idxes); + + // //////////////////////////////////////////////////////////////////////// + // table + idxes = [ + [ 0, 1, 2, 2, 3, 4, 5, 6], + [ 7, 8, 9, 10, 11, 12, 13, 6], + [14, 15, 15, 16, 17, 18, 19, 6], + [20, 15, 15, 21, 22, 18, 23, 6], + ]; + + testTableIndexes("table2", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableinsane1 (empty row groups) + idxes = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 7], + [6, 8, 9], + ]; + + testTableIndexes("tableinsane1", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableinsane2 (empry rows) + idxes = [ + [-1, -1, -1], + [-1, -1, -1], + [ 0, 1, 2], + ]; + + testTableIndexes("tableinsane2", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableinsane3 (cell holes) + idxes = [ + [0, 1, -1], + [2, 3, 4], + ]; + + testTableIndexes("tableinsane3", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableinsane3.2 (cell holes, row spans, fixed in bug 417912) + idxes = [ + [0, 1, 2], + [3, -1, 2], + [4, 5, 2], + ]; + + testTableIndexes("tableinsane3.2", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableinsane4 (empty row groups/rows and cell holes) + idxes = [ + [ 0, 1, 2], + [-1, -1, -1], + [ 3, 4, 5], + [ 6, 6, 7], + [ 8, -1, 7], + [ 9, 9, 9], + ]; + testTableIndexes("tableinsane4", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableinsane5 (just a strange table) + idxes = [ + [ 0, 1, 2, -1, -1], + [-1, -1, -1, -1, -1], + [ 3, 4, 5, -1, -1], + [ 6, 7, -1, -1, -1], + [ 6, 8, 9, -1, -1], + [ 6, 10, 9, 11, 12], + ]; + testTableIndexes("tableinsane5", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tableinsane6 (overlapping cells, mad table) + idxes = [ + [ 0, 1, 2, -1, -1], + [-1, -1, -1, -1, -1], + [ 3, 4, 5, -1, -1], + [ 6, 6, 7, -1, -1], + [ 8, 9, 7, -1, -1], + [ 10, 9, 7, 11, 12], + ]; + testTableIndexes("tableinsane6", idxes); + + // //////////////////////////////////////////////////////////////////////// + // Table with a cell that has display: block; style + idxes = [ + [0, 1], + ]; + testTableIndexes("tablewithcelldisplayblock", idxes); + + // //////////////////////////////////////////////////////////////////////// + // A table with a cell that has display: block; and a cell with colspan. + // This makes us fall back to the ARIAGridCellAccessible implementation. + idxes = [ + [0, 0, 1], + ]; + testTableIndexes("tablewithcolspanandcelldisplayblock", idxes); + + // //////////////////////////////////////////////////////////////////////// + // A table with all elements being display:block, including a row group. + // This makes us fall back to the ARIAGridRowAccessible, and we must + // make sure the index is 0. Strange example from Gmail. + idxes = [ + [0], + ]; + testTableIndexes("tablealldisplayblock", idxes); + + // //////////////////////////////////////////////////////////////////////// + // Table that has display: block; style + idxes = [ + [0, 1], + ]; + testTableIndexes("tablewithdisplayblock", idxes); + + // //////////////////////////////////////////////////////////////////////// + // tbody that has display: block; style + idxes = [ + [0, 1], + ]; + testTableIndexes("tbodywithdisplayblock", idxes); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> +<body> + + <a target="_blank" + title="GetIndexAt and GetRowAtIndex and GetColumnAtIndex on HTML tables are inconsistent" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052"> + Bug 410052 + </a> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <!-- + If you change the structure of the table please make sure to change + the indexes count in 'for' statement in the script above. + --> + <table border="1" id="table"> + <caption><strong><b><font size="29">this is a caption for this table</font></b></strong></caption> + <thead> + <tr> + <th>col1</th> + <th>col2</th> + <th>col3</th> + </tr> + </thead> + <tbody> + <tr> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + <tr> + <td rowspan="0">4</td> + <td colspan="2">5</td> + </tr> + <tr> + <td>6</td> + <td>7</td> + </tr> + </tbody> + </table> + + <table border="1" id="tableborder" style="border-collapse:collapse"> + <caption><strong><b><font size="29">this is a caption for this bc table</font></b></strong></caption> + <thead> + <tr> + <th>col1</th> + <th>col2</th> + <th>col3</th> + </tr> + </thead> + <tbody> + <tr> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + <tr> + <td rowspan="2">4</td> + <td colspan="2">5</td> + </tr> + <tr> + <td>6</td> + <td>7</td> + </tr> + </tbody> + </table> + + <table cellpadding="2" cellspacing="2" border="1" width="50%" id="table2"> + <caption>column and row spans</caption> + <tbody> + <tr> + <td>0</td> + <td>1</td> + <td rowspan="1" colspan="2">2</td> + <td>3</td> + <td>4</td> + <td>5</td> + <td rowspan="4" colspan="1">6</td> + </tr> + <tr> + <td>7</td> + <td>8</td> + <td>8</td> + <td>10</td> + <td>11</td> + <td>12</td> + <td>13</td> + </tr> + <tr> + <td>14</td> + <td rowspan="2" colspan="2">15</td> + <td>16</td> + <td>17</td> + <td rowspan="2" colspan="1">18</td> + <td>19</td> + </tr> + <tr> + <td>20</td> + <td>21</td> + <td>22</td> + <td>23</td> + </tr> + </tbody> + </table> + + <table border="1" id="tableinsane1"> + <caption>test empty row groups</caption> + <thead> + <tr> + <th>col1</th> + <th>col2</th> + <th>col3</th> + </tr> + </thead> + <tbody></tbody> + <tbody></tbody> + <tbody></tbody> + <tbody> + <tr> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + <tr> + <td rowspan="2">4</td> + <td colspan="2">5</td> + </tr> + <tr> + <td>6</td> + <td>7</td> + </tr> + </tbody> + </table> + + <table border="1" id="tableinsane2"> + <caption>empty rows</caption> + <tbody><tr></tr><tr></tr></tbody> + <tbody></tbody> + <tbody> + <tr> + <td>0</td> + <td>1</td> + <td>2</td> + </tr> + </tbody> + </table> + + <table border="1" id="tableinsane3"> + <caption>missed cell</caption> + <tbody> + <tr> + <td>0</td> + <td>1</td> + </tr> + </tbody> + <tbody> + <tr> + <td>2</td> + <td>3</td> + <td>4</td> + </tr> + </tbody> + </table> + + <table cellpadding="2" cellspacing="2" border="1" id="tableinsane3.2"> + <tr><td>1</td><td>2</td><td rowspan=3>3</td> + <tr><td>4</td> + <tr><td>5</td><td>6</td> + </table> + + <table border="1" id="tableinsane4"> + <caption>test empty rows + cellmap holes</caption> + <thead> + <tr> + <th>col1</th> + <th>col2</th> + <th>col3</th> + </tr> + </thead> + <tbody><tr></tr></tbody> + <tbody></tbody> + <tbody></tbody> + <tbody> + <tr> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + <tr> + <td colspan="2">4</td> + <td rowspan="2">5</td> + </tr> + <tr> + <td>6</td> + </tr> + <tr> + <td colspan="3">7</td> + </tr> + + </tbody> + </table> + + <table border="1" id="tableinsane5"> + <caption>just a strange table</caption> + <thead> + <tr> + <th>col1</th> + <th>col2</th> + <th>col3</th> + </tr> + </thead> + <tbody><tr></tr></tbody> + <tbody></tbody> + <tbody></tbody> + <tbody> + <tr> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + <tr> + <td rowspan="0">4</td> + <td colspan="0">5</td> + </tr> + <tr> + <td>6</td> + <td rowspan="0">7</td> + </tr> + <tr> + <td>8</td> + <td>9</td> + <td>10</td> + </tr> + + </tbody> + </table> + + <table border="1" id="tableinsane6" > + <caption>overlapping cells</caption> + <thead> + <tr> + <th>header cell 0</th> + <th>header cell 1</th> + <th>header cell 2</th> + </tr> + </thead> + <tbody><tr></tr></tbody> + <tbody></tbody> + <tbody></tbody> + <tbody> + <tr> + <td>3</td> + <td>4</td> + <td>5</td> + </tr> + <tr> + <td colspan="2">6</td> + <td rowspan="0">7</td> + </tr> + <tr> + <td>8</td> + <td rowspan="0">9</td> + </tr> + <tr> + <td colspan="3">10</td> + <td>11</td> + <td>12</td> + </tr> + </tbody> + </table> + + <table id="tablewithcelldisplayblock"> + <tr> + <th>a</th> + <td style="display: block;">b</td> + </tr> + </table> + + <table id="tablewithcolspanandcelldisplayblock"> + <tr> + <th colspan="2">a</th> + <td style="display: block;" >b</td> + </tr> + </table> + + <table id="tablealldisplayblock" style="display:block;"> + <tbody style="display:block;"> + <tr style="display:block;"> + <td style="display:block;">text</td> + </tr> + </tbody> + </table> + + <table id="tablewithdisplayblock" style="display: block;"> + <tr><th>a</th><td>b</td></tr> + </table> + + <table id="tbodywithdisplayblock"> + <tbody style="display: block;"> + <tr> + <th>a</th> + <td>b</td> + </tr> + </tbody> + </table> +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_indexes_tree.xhtml b/accessible/tests/mochitest/table/test_indexes_tree.xhtml new file mode 100644 index 0000000000..0b1b6b2625 --- /dev/null +++ b/accessible/tests/mochitest/table/test_indexes_tree.xhtml @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + title="Accessible Table indexes tests"> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + + <script type="application/javascript" + src="../treeview.js" /> + + <script type="application/javascript" + src="../common.js" /> + <script type="application/javascript" + src="../events.js" /> + <script type="application/javascript" + src="../table.js" /> + + <script type="application/javascript"> + <![CDATA[ + //////////////////////////////////////////////////////////////////////////// + // Test + + // gA11yEventDumpID = "debug"; + + function doTest() + { + var idxes = [ + [0, 1], + [2, 3], + [4, 5] + ]; + testTableIndexes("tree", idxes); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yXULTreeLoadEvent(doTest, "tree", new nsTableTreeView(3)); + ]]> + </script> + + <hbox flex="1" style="overflow: auto;"> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727" + title="Reorganize implementation of XUL tree accessibility"> + Mozilla Bug 503727 + </a><br/> + <p id="display"></p> + <div id="content" style="display: none"> + </div> + <pre id="test"> + </pre> + </body> + + <vbox id="debug"/> + <tree id="tree" flex="1"> + <treecols> + <treecol id="col" flex="1" primary="true" label="column"/> + <treecol id="scol" flex="1" label="column 2"/> + </treecols> + <treechildren id="treechildren"/> + </tree> + </hbox> + +</window> + diff --git a/accessible/tests/mochitest/table/test_layoutguess.html b/accessible/tests/mochitest/table/test_layoutguess.html new file mode 100644 index 0000000000..f3e94c5a78 --- /dev/null +++ b/accessible/tests/mochitest/table/test_layoutguess.html @@ -0,0 +1,554 @@ +<html> +<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=495388 --> +<head> + <title>test HTMLTableAccessible::IsProbablyForLayout implementation</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../attributes.js"></script> + + <script type="application/javascript"> + function isLayoutTable(id) { + // This helps us know if the absence of layout-guess is simply because + // it is not a table. + ok(isAccessible(id, nsIAccessibleTable), `${id} has table interface`); + testAttrs(id, { "layout-guess": "true" }, true); + } + function isDataTable(id) { + testAbsentAttrs(id, { "layout-guess": "true" }); + } + + function doTest() { + // table with role of grid + isDataTable("table1"); + // table with role of grid and datatable="0" + isDataTable("table1.1"); + + // table with landmark role + isDataTable("table2"); + + // table with summary + isDataTable("table3"); + + // table with caption + isDataTable("table4"); + + // layout table with empty caption + isLayoutTable("table4.2"); + + // table with thead element + isDataTable("table5"); + + // table with tfoot element + isDataTable("table5.1"); + + // table with colgroup or col elements + isDataTable("table5.2"); + isDataTable("table5.3"); + + // table with th element + isDataTable("table6"); + + // table with headers attribute + isDataTable("table6.2"); + + // table with scope attribute + isDataTable("table6.2.2"); + + // table with abbr attribute + isDataTable("table6.2.3"); + + // table with abbr element + isDataTable("table6.3"); + + // table with abbr element having empty text node + isDataTable("table6.4"); + + // table with abbr element and non-empty text node + isLayoutTable("table6.5"); + + // layout table with nested table + isLayoutTable("table9"); + + // layout table with 1 column + isLayoutTable("table10"); + + // layout table with 1 row + isLayoutTable("table11"); + + // table with 5 columns + isDataTable("table12"); + + // table with a bordered cell + isDataTable("table13"); + + // table with alternating row background colors + isDataTable("table14"); + + // table with 3 columns and 21 rows + isDataTable("table15"); + + // layout table that has a 100% width + isLayoutTable("table16"); + + // layout table that has a 95% width in pixels + isLayoutTable("table17"); + + // layout table with less than 10 columns + isLayoutTable("table18"); + + // layout table with embedded iframe + isLayoutTable("table19"); + + // tree grid, no layout table + isDataTable("table20"); + + // layout table containing nested data table (having data structures) + isLayoutTable("table21"); + isLayoutTable("table21.2"); + isLayoutTable("table21.3"); + isLayoutTable("table21.4"); + isLayoutTable("table21.5"); + isLayoutTable("table21.6"); + + // layout table having datatable="0" attribute and containing data table structure (tfoot element) + isLayoutTable("table22"); + + // repurposed table for tabbed UI + isLayoutTable("table23"); + + // layout display:block table with 1 column + isLayoutTable("displayblock_table1"); + + // matrix + isDataTable("mtable1"); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> +<body> + + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=495388" + title="Don't treat tables that have a landmark role as layout table"> + Mozilla Bug 495388 + </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=690222" + title="Data table elements used to determine layout-guess attribute shouldn't be picked from nested tables"> + Mozilla Bug 690222 + </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=696975" + title="Extend the list of legitimate data table structures"> + Mozilla Bug 696975 + </a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <!-- Table with role of grid --> + <table id="table1" role="grid"> + <tr> + <th>Sender</th> + <th>Subject</th> + <th>Date</th> + </tr> + <tr> + <td>Marco</td> + <td>Test</td> + <td>June 12</td> + </tr> + <tr> + <td>David</td> + <td>Another test</td> + <td>June 12</td> + </tr> + <tr> + <td>Alex</td> + <td>Third test</td> + <td>June 12</td> + </tr> + </table> + <!-- table with role of grid and datatable="0"--> + <table id="table1.1" role="grid" datatable="0"> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </table> + + <!-- table with landmark role --> + <table id="table2" role="main"> + <tr> + <th>Sender</th> + <th>Subject</th> + <th>Date</th> + </tr> + <tr> + <td>Marco</td> + <td>Test</td> + <td>June 12</td> + </tr> + <tr> + <td>David</td> + <td>Another test</td> + <td>June 12</td> + </tr> + <tr> + <td>Alex</td> + <td>Third test</td> + <td>June 12</td> + </tr> + </table> + + <!-- table with summary --> + <table id="table3" summary="This is a table"> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </table> + + <!-- table with caption --> + <table id="table4"> + <caption>This is a table</caption> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </table> + + <!-- layout table with empty caption --> + <table id="table4.2"> + <caption> </caption> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </table> + + <!-- table with thead element --> + <table id="table5"> + <thead> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </thead> + </table> + + <!-- table with tfoot element --> + <table id="table5.1"> + <tfoot> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </tfoot> + </table> + + <!-- table with colgroup and col elements --> + <table id="table5.2"> + <colgroup width="20"></colgroup> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </table> + <table id="table5.3"> + <col width="20"> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </table> + + <!-- table with th element --> + <table id="table6"> + <tr> + <th>Cell1</th><th>cell2</th> + </tr> + </table> + + <!-- table with headers attribute --> + <table id="table6.2"> + <tr> + <td headers="a">table6.2 cell</td> + </tr> + </table> + + <!-- table with scope attribute --> + <table id="table6.2.2"> + <tr> + <td scope="a">table6.2.2 cell</td> + </tr> + </table> + + <!-- table with abbr attribute --> + <table id="table6.2.3"> + <tr> + <td abbr="table6.2.3">table6.2.3 cell1</td> + </tr> + </table> + + <!-- table with abbr element --> + <table id="table6.3"> + <tr> + <td>table6.3 cell1</td> + <td><abbr>table6.3 cell2</abbr></td> + </tr> + </table> + + <!-- table with abbr element having empty text node --> + <table id="table6.4"> + <tr> + <td> + <abbr>abbr</abbr> + </td> + </tr> + </table> + + <!-- table with abbr element and non-empty text node --> + <table id="table6.5"> + <tr> + <td> + This is a really long text (<abbr>tiarlt</abbr>) inside layout table + </td> + </tr> + </table> + + <!-- layout table with nested table --> + <table id="table9"> + <tr> + <td><table><tr><td>Cell</td></tr></table></td> + </tr> + </table> + + <!-- layout table with 1 column --> + <table id="table10"> + <tr><td>Row1</td></tr> + <tr><td>Row2</td></tr> + </table> + + <!-- layout table with 1 row and purposely many columns --> + <table id="table11"> + <tr><td>Col1</td><td>Col2</td><td>Col3</td><td>Col4</td><td>Col5</td></tr> + </table> + + <!-- table with 5 columns --> + <table id="table12"> + <tr><td>Col1</td><td>Col2</td><td>Col3</td><td>Col4</td><td>Col5</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td><td>Col4</td><td>Col5</td></tr> + </table> + + <!-- table with a bordered cell --> + <table id="table13" border="1" width="100%" bordercolor="#0000FF"> + <tr> + <td bordercolor="#000000">Â </td> + <td bordercolor="#000000">Â </td> + <td bordercolor="#000000">Â </td> + </tr> + <tr> + <td bordercolor="#000000">Â </td> + <td bordercolor="#000000">Â </td> + <td bordercolor="#000000">Â </td> + </tr> + </table> + + <!-- table with alternating row background colors --> + <table id="table14" width="100%"> + <tr style="background-color: #0000FF;"> + <td>Â </td> + <td>Â </td> + <td>Â </td> + </tr> + <tr style="background-color: #00FF00;"> + <td>Â </td> + <td>Â </td> + <td>Â </td> + </tr> + </table> + + <!-- table with 3 columns and 21 rows --> + <table id="table15" border="0"> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + </table> + + <!-- layout table that has a 100% width --> + <table id="table16" width="100%"> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + </table> + + <!-- layout table that has a 95% width in pixels --> + <table id="table17" width="98%"> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr> + </table> + + <!-- layout table with less than 10 columns --> + <table id="table18"> + <tr> + <td>Marco</td> + <td>Test</td> + <td>June 12</td> + </tr> + <tr> + <td>David</td> + <td>Another test</td> + <td>June 12</td> + </tr> + <tr> + <td>Alex</td> + <td>Third test</td> + <td>June 12</td> + </tr> + </table> + + <!-- layout table with embedded iframe --> + <table id="table19"> + <tr><td><iframe id="frame"></iframe></td><td> </td><td> </td></tr> + <tr><td> </td><td> </td><td> </td></tr> + <tr><td> </td><td> </td><td> </td></tr> + <tr><td> </td><td> </td><td> </td></tr> + </table> + + <!-- tree grid, no layout table --> + <table id="table20" role="treegrid"> + <tr role="treeitem"><td>Cell1</td><td>Cell2</td></tr> + </table> + + <!-- layout table with nested data table containing data table elements --> + <table id="table21"> + <tr> + <td> + <table> + <caption>table</caption> + <tr><td>Cell</td></tr> + </table> + </td> + </tr> + </table> + <table id="table21.2"> + <tr> + <td> + <table> + <colgroup width="20"></colgroup> + <tr><th>Cell</th></tr> + </table> + </td> + </tr> + </table> + <table id="table21.3"> + <tr> + <td> + <table> + <col width="20"></col> + <tr><th>Cell</th></tr> + </table> + </td> + </tr> + </table> + <table id="table21.4"> + <tr> + <td> + <table> + <tr><th>Cell</th></tr> + </table> + </td> + </tr> + </table> + <table id="table21.5"> + <tr> + <td> + <table> + <thead> + <tr><td>Cell</td></tr> + </thead> + </table> + </td> + </tr> + </table> + <table id="table21.6"> + <tr> + <td> + <table> + <tfoot> + <tr><td>Cell</td></tr> + </tfoot> + </table> + </td> + </tr> + </table> + + <!-- layout table with datatable="0" and tfoot element--> + <table id="table22" datatable="0"> + <tfoot> + <tr> + <td>Cell1</td><td>cell2</td> + </tr> + </tfoot> + </table> + + <table id="table23" border="1"> + <tr role="tablist"> + <td role="tab">Tab 1</td><td role="tab">Tab 2</td> + </tr> + <tr> + <td role="tabpanel" colspan="2">Hello</td> + </tr> + </table> + + <!-- display:block table --> + <table id="displayblock_table1" style="display:block"> + <tr><td>Row1</td></tr> + <tr><td>Row2</td></tr> + </table> + + <!-- MathML matrix --> + <math> + <mtable id="mtable1"> + <mtr> + <mtd> + <mn>1</mn> + </mtd> + <mtd> + <mn>0</mn> + </mtd> + </mtr> + <mtr> + <mtd> + <mn>0</mn> + </mtd> + <mtd> + <mn>1</mn> + </mtd> + </mtr> + </mtable> + </math> +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_mtable.html b/accessible/tests/mochitest/table/test_mtable.html new file mode 100644 index 0000000000..aa79b3b98c --- /dev/null +++ b/accessible/tests/mochitest/table/test_mtable.html @@ -0,0 +1,160 @@ +<!DOCTYPE html> +<html> +<head> + <title>MathML table tests</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + function doTest() { + // 'Simple' table + var idxes = [ + [0, 1], + [2, 3], + ]; + testTableIndexes("simple", idxes); + var cellsArray = [ + [kDataCell, kDataCell], + [kDataCell, kDataCell], + ]; + var rowsArray = [ROLE_MATHML_TABLE_ROW, ROLE_MATHML_TABLE_ROW]; + testTableStruct("simple", cellsArray, kNoColumnHeader, + "", "", kMathTable, rowsArray); + + // 'Complex' table + idxes = [ + [0, 0, 0], + [1, 1, 2], + [1, 1, 3], + ]; + testTableIndexes("complex", idxes); + cellsArray = [ + [kDataCell, kColSpanned, kColSpanned], + [kDataCell, kColSpanned, kDataCell], + [kRowSpanned, kSpanned, kDataCell], + ]; + rowsArray = [ + ROLE_MATHML_TABLE_ROW, + ROLE_MATHML_TABLE_ROW, + ROLE_MATHML_TABLE_ROW, + ]; + testTableStruct("complex", cellsArray, kNoColumnHeader, + "", "", kMathTable, rowsArray); + + // 'Simple' table with mlabeledtr + // At the moment we do not implement mlabeledtr but just hide the label + // with display: none. Thus we just test the role for now. See bug 689641. + idxes = [[0]]; + testTableIndexes("simple_label", idxes); + cellsArray = [[kDataCell]]; + rowsArray = [ROLE_MATHML_LABELED_ROW]; + testTableStruct("simple_label", cellsArray, kNoColumnHeader, + "", "", kMathTable, rowsArray); + + // Test that a non-table display style still generates the proper + // roles in the accessibility tree. + const table_tree = { + MATHML_TABLE: [{
+ MATHML_TABLE_ROW: [{ MATHML_CELL: [{ TEXT_LEAF: [] }] }]
+ }], + }; + testAccessibleTree("table_with_display_block_mtd", table_tree); + + // Equivalent to the above test but with display: block mtr. + testAccessibleTree("table_with_display_block_mtr", table_tree); + + // Equivalent to the above test but with display: block mtable. + testAccessibleTree("table_with_display_block", table_tree); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> +<body> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <math> + <mtable id="simple"> + <mtr> + <mtd> + <mn>1</mn> + </mtd> + <mtd> + <mn>0</mn> + </mtd> + </mtr> + <mtr> + <mtd> + <mn>0</mn> + </mtd> + <mtd> + <mn>1</mn> + </mtd> + </mtr> + </mtable> + + <mtable id="complex"> + <mtr> + <mtd columnspan="3"> + <mtext>1 x 3</mtext> + </mtd> + </mtr> + <mtr> + <mtd rowspan="2" columnspan="2"> + <mtext>2 x 2</mtext> + </mtd> + <mtd> + <mtext>1 x 1</mtext> + </mtd> + </mtr> + <mtr> + <mtd> + <mtext>1 x 1</mtext> + </mtd> + </mtr> + </mtable> + + <mtable id="simple_label"> + <mlabeledtr> + <mtd><mtext>1</mtext></mtd> + <mtd><mtext>label</mtext></mtd> + </mlabeledtr> + </mtable> + + <mtable id="table_with_display_block_mtd"> + <mtr> + <mtd style="display: block">test</mtd> + </mtr> + </mtable> + + <mtable id="table_with_display_block_mtr"> + <mtr style="display: block"> + <mtd>test</mtd> + </mtr> + </mtable> + + <mtable id="table_with_display_block" style="display: block"> + <mtr> + <mtd>test</mtd> + </mtr> + </mtable> + + </math> + +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_sels_ariagrid.html b/accessible/tests/mochitest/table/test_sels_ariagrid.html new file mode 100644 index 0000000000..784939bf03 --- /dev/null +++ b/accessible/tests/mochitest/table/test_sels_ariagrid.html @@ -0,0 +1,159 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=410052 +--> +<head> + <title>nsIAccesible selection methods testing for ARIA grid</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" + src="../states.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // ARIA grid + var cellsArray = + [ + [ true, true, false, true], + [ true, false, true, true], + [ true, false, false, true], + [ true, true, true, true], + [ true, true, true, true], + ]; + + testTableSelection("table", cellsArray); + testUnselectTableColumn("table", 3, cellsArray); + testUnselectTableRow("table", 3, cellsArray); + testSelectTableColumn("table", 0, cellsArray); + testSelectTableRow("table", 0, cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // a bit strange ARIA grid + cellsArray = + [ + [ false, false], + [ false, false], + ]; + + testTableSelection("grid2", cellsArray); + testSelectTableColumn("grid2", 0, cellsArray); + testSelectTableRow("grid2", 0, cellsArray); + testUnselectTableColumn("grid2", 0, cellsArray); + testUnselectTableRow("grid2", 0, cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // ARIA grid (column and row headers) + + cellsArray = + [ + [ undefined, true, false], + [ undefined, true, false], + ]; + + testTableSelection("grid3", cellsArray); + testSelectTableColumn("grid3", 0, cellsArray); + testSelectTableRow("grid3", 0, cellsArray); + testUnselectTableColumn("grid3", 0, cellsArray); + testUnselectTableRow("grid3", 0, cellsArray); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> +<body> + + <a target="_blank" + title="implement nsIAccessibleTable selection methods for ARIA grids" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Bug 410052</a> + <a target="_blank" + title="nsHTMLTableCellAccessible is used in dojo's ARIA grid" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Bug 513848</a> + <a target="_blank" + title="ARIA columnheader/rowheader shouldn't be selectable by default" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=888247">Bug 888247</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <div role="grid" id="table"> + <div role="row"> + <span role="gridcell" aria-selected="true">cell1</span> + <span role="gridcell" aria-selected="true">cell2</span> + <span role="gridcell">cell3</span> + <span role="gridcell" aria-selected="true">cell4</span> + </div> + <div role="row"> + <span role="gridcell" aria-selected="true">cell5</span> + <span role="gridcell">cell6</span> + <span role="gridcell" aria-selected="true">cell7</span> + <span role="gridcell" aria-selected="true">cell8</span> + </div> + <div role="row"> + <span role="gridcell" aria-selected="true">cell9</span> + <span role="gridcell">cell10</span> + <span role="gridcell">cell11</span> + <span role="gridcell" aria-selected="true">cell12</span> + </div> + <div role="row" aria-selected="true"> + <span role="gridcell">cell13</span> + <span role="gridcell">cell14</span> + <span role="gridcell">cell15</span> + <span role="gridcell">cell16</span> + </div> + <div role="row"> + <span role="gridcell" aria-selected="true">cell17</span> + <span role="gridcell" aria-selected="true">cell18</span> + <span role="gridcell" aria-selected="true">cell19</span> + <span role="gridcell" aria-selected="true">cell20</span> + </div> + </div> + + <div role="grid" id="grid2"> + <div role="row"> + <table role="presentation"> + <tr> + <td role="columnheader" aria-selected="false">header1</td> + <td role="columnheader" aria-selected="false">header2</td> + </tr> + </table> + </div> + <div role="row"> + <table role="presentation"> + <tr> + <td role="gridcell">cell1</td> + <td role="gridcell" tabindex="-1">cell2</td> + </tr> + </table> + </div> + </div> + + <div role="grid" id="grid3"> + <div role="row"> + <div role="columnheader" id="colheader_default">col header1</div> + <div role="columnheader" id="colheader_selected" aria-selected="true">col header2</div> + <div role="columnheader" id="colheader_notselected" aria-selected="false">col header3</div> + </div> + <div role="row"> + <div role="rowheader" id="rowheader_default">row header1</div> + <div role="rowheader" id="rowheader_selected" aria-selected="true">row header2</div> + <div role="rowheader" id="rowheader_notselected" aria-selected="false">row header3</div> + </div> + </div> +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_sels_table.html b/accessible/tests/mochitest/table/test_sels_table.html new file mode 100644 index 0000000000..0c87112d17 --- /dev/null +++ b/accessible/tests/mochitest/table/test_sels_table.html @@ -0,0 +1,178 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> + <head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <title>nsIAccesible selection methods testing for HTML table</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" + src="../states.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="text/javascript"> + + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // table + + var cellsArray = + [ + [false, false, false, kColSpanned, false, false, false, false], + [false, false, false, false, false, false, false, kRowSpanned], + [false, false, kColSpanned, false, false, false, false, kRowSpanned], + [false, kRowSpanned, kSpanned, false, false, kRowSpanned, false, kRowSpanned], + ]; + + testTableSelection("table", cellsArray); + + var rowCount = 4; + for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) + testSelectTableRow("table", rowIdx, cellsArray); + + for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) { + testSelectTableRow("table", rowIdx, cellsArray); + testUnselectTableRow("table", rowIdx, cellsArray); + } + + var columsCount = 8; + for (let colIdx = 0; colIdx < columsCount; colIdx++) + testSelectTableColumn("table", colIdx, cellsArray); + + for (let colIdx = 0; colIdx < columsCount; colIdx++) { + testSelectTableColumn("table", colIdx, cellsArray); + testUnselectTableColumn("table", colIdx, cellsArray); + } + + var accTable = getAccessible("table", [nsIAccessibleTable]); + ok(!accTable.isProbablyForLayout(), "table is not for layout"); + + // //////////////////////////////////////////////////////////////////////// + // table instane + + cellsArray = + [ + [false, false, false, -1, -1], + [false, false, false, -1, -1], + [false, false, kColSpanned, kColSpanned, -1], + [kRowSpanned, false, false, -1, -1], + [kRowSpanned, false, kRowSpanned, false, false], + ]; + + testTableSelection("tableinsane", cellsArray); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> + </head> + <body> + + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052" + title="Fix our nsHTMLAccessibleTable class so GetIndexAt and GetRowAtIndex and GetColumnAtIndex behave consistently"> + Mozilla Bug 410052 + </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=501635" + title="nsHTMLTableAccessible::GetSelectedCells contains index duplicates for spanned rows or columns"> + Mozilla Bug 501635 + </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=417929" + title="nsIAccessiblTable selectRows does not unselect previously selected rows"> + Mozilla Bug 417929 + </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=501659" + title="HTML table's isRowSelected/isColumnSelected shouldn't fail if row or column has cell holes"> + Mozilla Bug 501659 + </a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <!-- Test Table --> + <br><br><b> Testing Table:</b><br><br> + <center> + <table cellpadding="2" cellspacing="2" border="1" width="50%" id="table"> + <tbody> + <tr> + <td><br></td> + <td><br></td> + <td rowspan="1" colspan="2"><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td rowspan="4" colspan="1"><br></td> + </tr> + <tr> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + </tr> + <tr> + <td><br></td> + <td rowspan="2" colspan="2">c1</td> + <td><br></td> + <td><br></td> + <td rowspan="2" colspan="1"><br></td> + <td><br></td> + </tr> + <tr> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + </tr> + </tbody> + </table> + + <table border="1" id="tableinsane"> + <thead> + <tr> + <th>col1</th> + <th>col2</th> + <th>col3</th> + </tr> + </thead> + <tbody> + <tr> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + <tr> + <td rowspan="3">4</td> + <td colspan="4">5</td> + </tr> + <tr> + <td>6</td> + <td rowspan="2">7</td> + </tr> + <tr> + <td>8</td> + <td>9</td> + <td>10</td> + </tr> + </tbody> + </table> + + </center> + </body> +</html> diff --git a/accessible/tests/mochitest/table/test_sels_tree.xhtml b/accessible/tests/mochitest/table/test_sels_tree.xhtml new file mode 100644 index 0000000000..254377b342 --- /dev/null +++ b/accessible/tests/mochitest/table/test_sels_tree.xhtml @@ -0,0 +1,78 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + title="Accessible Table selection tests"> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + + <script type="application/javascript" + src="../treeview.js" /> + + <script type="application/javascript" + src="../common.js" /> + <script type="application/javascript" + src="../events.js" /> + <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" + src="../states.js" /> + <script type="application/javascript" + src="../table.js" /> + + <script type="application/javascript"> + <![CDATA[ + //////////////////////////////////////////////////////////////////////////// + // Test + + // gA11yEventDumpID = "debug"; + + function doTest() + { + var cellsArray = + [ + [false, false], + [false, false], + [false, false] + ]; + + testTableSelection("tree", cellsArray); + testSelectTableRow("tree", 0, cellsArray); + testUnselectTableRow("tree", 0, cellsArray); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yXULTreeLoadEvent(doTest, "tree", new nsTableTreeView(3)); + ]]> + </script> + + <hbox flex="1" style="overflow: auto;"> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727" + title="Reorganize implementation of XUL tree accessibility"> + Mozilla Bug 503727 + </a><br/> + <p id="display"></p> + <div id="content" style="display: none"> + </div> + <pre id="test"> + </pre> + </body> + + <vbox id="debug"/> + <tree id="tree" flex="1"> + <treecols> + <treecol id="col" flex="1" primary="true" label="column"/> + <treecol id="scol" flex="1" label="column 2"/> + </treecols> + <treechildren id="treechildren"/> + </tree> + </hbox> + +</window> + diff --git a/accessible/tests/mochitest/table/test_struct_ariagrid.html b/accessible/tests/mochitest/table/test_struct_ariagrid.html new file mode 100644 index 0000000000..92821e19c2 --- /dev/null +++ b/accessible/tests/mochitest/table/test_struct_ariagrid.html @@ -0,0 +1,163 @@ +<!DOCTYPE html> +<html> + +<head> + <title>Table accessible tree and table interface tests for ARIA grid</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // Pure ARIA grid + var cellsArray = [ + [kColHeaderCell, kColHeaderCell, kColHeaderCell], + [kRowHeaderCell, kDataCell, kDataCell], + [kRowHeaderCell, kDataCell, kDataCell], + ]; + + testTableStruct("table", cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // HTML table based ARIA grid + cellsArray = [ + [kColHeaderCell, kColHeaderCell, kColHeaderCell], + [kDataCell, kDataCell, kDataCell], + [kDataCell, kDataCell, kDataCell], + ]; + + testTableStruct("grid", cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // ARIA grid with HTML table elements + cellsArray = [ + [kColHeaderCell, kColHeaderCell], + [kDataCell, kDataCell], + ]; + + testTableStruct("grid2", cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // ARIA grid of wrong markup + cellsArray = [ ]; + testTableStruct("grid3", cellsArray); + + cellsArray = [ [] ]; + testTableStruct("grid4", cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // ARIA table with tr inside a shadow root (bug 1698097). + testTableStruct("tableShadow", [ [ kDataCell ] ]); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <a target="_blank" + title="ARIA grid based on HTML table" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=491683">Mozilla Bug 491683</a> + <a target="_blank" + title="implement IAccessibleTable2" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424">Mozilla Bug 512424</a> + <a target="_blank" + title="nsHTMLTableCellAccessible is used in dojo's ARIA grid" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Mozilla Bug 513848</a> + <a target="_blank" + title="Crash [@ AccIterator::GetNext()]" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=675861">Mozilla Bug 675861</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <!-- Not usual markup to avoid text accessible between cell accessibles --> + <div id="table" role="grid"> + <div role="row"><span + id="table_ch_1" role="columnheader">col_1</span><span + id="table_ch_2" role="columnheader">col_2</span><span + id="table_ch_3" role="columnheader">col_3</span></div> + <div role="row"><span + id="table_rh_1" role="rowheader">row_1</span><span + id="table_dc_1" role="gridcell">cell1</span><span + id="table_dc_2" role="gridcell">cell2</span></div> + <div role="row"><span + id="table_rh_2" role="rowheader">row_2</span><span + id="table_dc_3" role="gridcell">cell3</span><span + id="table_dc_4" role="gridcell">cell4</span></div> + </div> + + <table role="grid" id="grid" border="1" cellpadding="10" cellspacing="0"> + <thead> + <tr role="row"> + <th role="columnheader">subject</td> + <th role="columnheader">sender</th> + <th role="columnheader">date</th> + </tr> + </thead> + <tbody> + <tr role="row"> + <td role="gridcell" tabindex="0">about everything</td> + <td role="gridcell">president</td> + <td role="gridcell">today</td> + </tr> + <tr role="row"> + <td role="gridcell">new bugs</td> + <td role="gridcell">mozilla team</td> + <td role="gridcell">today</td> + </tr> + </tbody> + </table> + + <!-- ARIA grid containing presentational HTML:table with HTML:td used as ARIA + grid cells (focusable and not focusable cells) --> + <div role="grid" id="grid2"> + <div role="row"> + <table role="presentation"> + <tr> + <td role="columnheader">header1</td> + <td role="columnheader">header2</td> + </tr> + </table> + </div> + <div role="row"> + <table role="presentation"> + <tr> + <td role="gridcell">cell1</td> + <td role="gridcell" tabindex="-1">cell2</td> + </tr> + </table> + </div> + </div> + + <!-- Wrong markup ARIA grid --> + <div role="grid" id="grid3"></div> + <div role="grid" id="grid4"><div role="row"></div></div> + + <div id="tableShadow" role="table"></div> + <script> + let host = document.getElementById("tableShadow"); + let shadow = host.attachShadow({mode: "open"}); + let tr = document.createElement("tr"); + shadow.append(tr); + tr.setAttribute("role", "row"); + let td = document.createElement("td"); + tr.append(td); + td.textContent = "test"; + </script> +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_struct_ariatreegrid.html b/accessible/tests/mochitest/table/test_struct_ariatreegrid.html new file mode 100644 index 0000000000..8d36a2b350 --- /dev/null +++ b/accessible/tests/mochitest/table/test_struct_ariatreegrid.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html> + +<head> + <title>Table accessible tree and table interface tests for ARIA tree grid</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // HTML based ARIA tree grid + + var cellsArray = [ + [kColHeaderCell, kColHeaderCell, kColHeaderCell], + [kDataCell, kDataCell, kDataCell], + [kDataCell, kDataCell, kDataCell], + ]; + + testTableStruct("treegrid", cellsArray, kNoColumnHeader, "", "", + kTreeTable); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <a target="_blank" + title="ARIA treegrid role on HTML:table makes thead/tbody accessible" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=491683">Mozilla Bug 516133</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <table role="treegrid" id="treegrid" + border="1" cellpadding="10" cellspacing="0"> + <thead> + <tr role="row"> + <th role="columnheader">subject</td> + <th role="columnheader">sender</th> + <th role="columnheader">date</th> + </tr> + </thead> + <tbody> + <tr role="row"> + <td role="gridcell">about everything</td> + <td role="gridcell">president</td> + <td role="gridcell">today</td> + </tr> + <tr role="row"> + <td role="gridcell">new bugs</td> + <td role="gridcell">mozilla team</td> + <td role="gridcell">today</td> + </tr> + </tbody> + </table> + +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_struct_table.html b/accessible/tests/mochitest/table/test_struct_table.html new file mode 100644 index 0000000000..46bad05c62 --- /dev/null +++ b/accessible/tests/mochitest/table/test_struct_table.html @@ -0,0 +1,217 @@ +<!DOCTYPE html> +<html> + +<head> + <title>Table accessible tree and table interface tests for HTML tables</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" + src="../table.js"></script> + + <script type="application/javascript"> + function doTest() { + // //////////////////////////////////////////////////////////////////////// + // column headers from thead and tfoot + + cellsArray = [ + [kColHeaderCell, kColHeaderCell, kColSpanned], + [kRowSpanned, kColHeaderCell, kColHeaderCell], + [kDataCell, kDataCell, kDataCell], + [kColHeaderCell, kColHeaderCell, kColHeaderCell], + ]; + + testTableStruct("table1", cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // row and column headers from thead and @scope + + var cellsArray = [ + [kColHeaderCell, kColHeaderCell, kColHeaderCell], + [kRowHeaderCell, kDataCell, kDataCell], + [kRowHeaderCell, kDataCell, kDataCell], + ]; + + testTableStruct("table2", cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // caption and @summary + + cellsArray = [ + [kColHeaderCell, kColHeaderCell, kColHeaderCell, kColHeaderCell], + [kRowHeaderCell, kDataCell, kDataCell, kDataCell], + [kRowHeaderCell, kDataCell, kDataCell, kDataCell], + ]; + + testTableStruct("table3", cellsArray, kNoColumnHeader, + "Test Table", + "this is a test table for nsIAccessibleTable"); + + // //////////////////////////////////////////////////////////////////////// + // row and column spans + + cellsArray = [ + [kDataCell, kDataCell, kDataCell, kColSpanned, kDataCell, kDataCell, kDataCell, kDataCell], + [kDataCell, kDataCell, kDataCell, kDataCell, kDataCell, kDataCell, kDataCell, kRowSpanned], + [kDataCell, kDataCell, kColSpanned, kDataCell, kDataCell, kDataCell, kDataCell, kRowSpanned], + [kDataCell, kRowSpanned, kSpanned, kDataCell, kDataCell, kRowSpanned, kDataCell, kRowSpanned], + ]; + + testTableStruct("table4", cellsArray); + + // //////////////////////////////////////////////////////////////////////// + // Table with a cell that has display: block; style + + cellsArray = [ + [kRowHeaderCell, kDataCell], + ]; + + testTableStruct("table5", cellsArray); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> +<body> + + <a target="_blank" + title="Fix our nsHTMLAccessibleTable class so GetIndexAt and GetRowAtIndex and GetColumnAtIndex behave consistently" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a> + <a target="_blank" + title="GetCellDataAt callers that expect an error if no cell is found are wrong" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=417912">Mozilla Bug 417912</a> + <a target="_blank" + title="create accessibles for HTML tr" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=493695">Mozilla Bug 493695</a> + <a target="_blank" + title="implement IAccessibleTable2" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424">Mozilla Bug 512424</a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <table id="table1"> + <thead> + <tr> + <th rowspan="2">col1</th><th colspan="2">col2</th> + </tr> + <tr> + <th>col2sub1</th><th>col2sub2</th> + </tr> + </thead> + <tbody> + <tr> + <td>cell1</td><td>cell2</td><td>cell3</td> + </tr> + </tbody> + <tfoot> + <tr> + <th>col1</th><th>col2</th><th>col3</th> + </tr> + </tfoot> + </table> + + <table id="table2"> + <thead> + <tr> + <th id="table1_0">col1</th> + <th id="table1_1">col2</th> + <td id="table1_2" scope="col">col3</td> + </tr> + </thead> + <tbody> + <tr> + <th id="table1_3">row1</th> + <td id="table1_4">cell1</td> + <td id="table1_5">cell2</td> + </tr> + <tr> + <td id="table1_6" scope="row">row2</td> + <td id="table1_7">cell3</td> + <td id="table1_8">cell4</td> + </tr> + </tbody> + </table> + + <table id="table3" border="1" + summary="this is a test table for nsIAccessibleTable"> + <caption>Test Table</caption> + <thead> + <tr> + <th></th> + <th>columnHeader_1</th> + <th id ="col2a">columnHeader_2</th> + <th>columnHeader_3</th> + </tr> + </thead> + <tr> + <th id="row2a">rowHeader_1</th> + <td id="row2b">row1_column1</td> + <td id ="col2b">row1_column2</td> + <td id="row2c">row1_column3</td> + </tr> + <tr> + <th>rowHeader_2</th> + <td>row2_column1</td> + <td id ="col2c">row2_column2</td> + <td>row2_column3</td> + </tr> + </table> + + <table id="table4" cellpadding="2" cellspacing="2" border="1" width="50%"> + <tbody> + <tr> + <td><br></td> + <td><br></td> + <td rowspan="1" colspan="2"><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td rowspan="4" colspan="1"><br></td> + </tr> + <tr> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + </tr> + <tr> + <td><br></td> + <td rowspan="2" colspan="2">c1</td> + <td><br></td> + <td><br></td> + <td rowspan="2" colspan="1"><br></td> + <td><br></td> + </tr> + <tr> + <td><br></td> + <td><br></td> + <td><br></td> + <td><br></td> + </tr> + </tbody> + </table> + + <table id="table5"> + <tr> + <th>a</th> + <td style="display: block;">b</td> + </tr> + </table> + +</body> +</html> diff --git a/accessible/tests/mochitest/table/test_struct_tree.xhtml b/accessible/tests/mochitest/table/test_struct_tree.xhtml new file mode 100644 index 0000000000..6710bd2e8b --- /dev/null +++ b/accessible/tests/mochitest/table/test_struct_tree.xhtml @@ -0,0 +1,73 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + title="Table accessible tree and table interface tests for XUL trees"> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + + <script type="application/javascript" + src="../treeview.js" /> + + <script type="application/javascript" + src="../common.js" /> + <script type="application/javascript" + src="../events.js" /> + <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" + src="../table.js" /> + + <script type="application/javascript"> + <![CDATA[ + //////////////////////////////////////////////////////////////////////////// + // Test + + // gA11yEventDumpID = "debug"; + + function doTest() + { + var cellsArray = [ + [kDataCell, kDataCell], + [kDataCell, kDataCell], + [kDataCell, kDataCell] + ]; + + testTableStruct("table", cellsArray, kTreeColumnHeader); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yXULTreeLoadEvent(doTest, "table", new nsTableTreeView(3)); + ]]> + </script> + + <hbox flex="1" style="overflow: auto;"> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424" + title="implement IAccessibleTable2"> + Mozilla Bug 512424 + </a><br/> + <p id="display"></p> + <div id="content" style="display: none"> + </div> + <pre id="test"> + </pre> + </body> + + <vbox id="debug"/> + <tree id="table" flex="1"> + <treecols> + <treecol id="col" flex="1" label="column"/> + <treecol id="scol" flex="1" label="column 2"/> + </treecols> + <treechildren id="treechildren"/> + </tree> + </hbox> + +</window> + diff --git a/accessible/tests/mochitest/table/test_table_1.html b/accessible/tests/mochitest/table/test_table_1.html new file mode 100644 index 0000000000..b1331a5cc3 --- /dev/null +++ b/accessible/tests/mochitest/table/test_table_1.html @@ -0,0 +1,107 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> + <head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + + <script type="application/javascript"> + +function doTest() { + var accTable = getAccessible("table", [nsIAccessibleTable]); + + var s = window.getSelection(); + if (s.rangeCount > 0) + s.removeAllRanges(); + + var cell = getNode("col2b"); + var range = document.createRange(); + range.selectNode(cell); + s.addRange(range); + + is(accTable.selectedCellCount, 1, "only one cell selected"); + cell = getNode("col2a"); + range = document.createRange(); + range.selectNode(cell); + s.addRange(range); + cell = getNode("col2c"); + range = document.createRange(); + range.selectNode(cell); + s.addRange(range); + is(accTable.selectedColumnCount, 1, "only one column selected"); + + cell = getNode("row2a"); + range = document.createRange(); + range.selectNode(cell); + s.addRange(range); + cell = getNode("row2b"); + range = document.createRange(); + range.selectNode(cell); + s.addRange(range); + range = document.createRange(); + cell = getNode("row2c"); + range.selectNode(cell); + s.addRange(range); + + is(accTable.selectedRowCount, 1, "no cells selected"); + + // These shouldn't throw. + try { + accTable.getColumnDescription(1); + accTable.getRowDescription(1); + } catch (ex) { + ok(false, "getColumnDescription/getRowDescription shouldn't throw."); + } + SimpleTest.finish(); +} +SimpleTest.waitForExplicitFinish(); +addA11yLoadEvent(doTest); + </script> + </head> + <body > + + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=760878" + title="decomtaminate Get Row / Column Description() on accessible tables"> + Mozilla Bug 760878 + </a> + + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <!-- Test Table --> + <br><br><b> Testing Table:</b><br><br> + <center> + <table id="table" border="1" + summary="this is a test table for nsIAccessibleTable" > + <caption>Test Table</caption> + <thead> + <tr> + <th></th> + <th>columnHeader_1</th> + <th id ="col2a">columnHeader_2</th> + <th>columnHeader_3</th> + </tr> + </thead> + <tr> + <th id="row2a">rowHeader_1</th> + <td id="row2b">row1_column1</td> + <td id ="col2b">row1_column2</td> + <td id="row2c">row1_column3</td> + </tr> + <tr> + <th>rowHeader_2</th> + <td>row2_column1</td> + <td id ="col2c">row2_column2</td> + <td>row2_column3</td> + </tr> + </table> + </center> + </body> +</html> diff --git a/accessible/tests/mochitest/table/test_table_2.html b/accessible/tests/mochitest/table/test_table_2.html new file mode 100644 index 0000000000..6bd7c56b37 --- /dev/null +++ b/accessible/tests/mochitest/table/test_table_2.html @@ -0,0 +1,87 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> + <head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + + <script type="text/javascript"> + +function doTest() { + // Test table with role=alert. + var tableInterfaceExposed = true; + var accTable3 = getAccessible("table3", [nsIAccessibleTable], null, DONOTFAIL_IF_NO_INTERFACE); + if (!accTable3) + tableInterfaceExposed = false; + ok(tableInterfaceExposed, "table interface is not exposed"); + + if (tableInterfaceExposed) { + testRole(accTable3, ROLE_ALERT); + + is(accTable3.getCellAt(0, 0).firstChild.name, "cell0", "wrong cell"); + is(accTable3.getCellAt(0, 1).firstChild.name, "cell1", "wrong cell"); + } + + // Test table with role=log and aria property in tr. We create accessible for + // tr in this case. + tableInterfaceExposed = true; + var accTable4 = getAccessible("table4", [nsIAccessibleTable], null, DONOTFAIL_IF_NO_INTERFACE); + if (!accTable4) + tableInterfaceExposed = false; + ok(tableInterfaceExposed, "table interface is not exposed"); + + if (tableInterfaceExposed) { + let accNotCreated = (!isAccessible("tr")); + ok(!accNotCreated, "missed tr accessible"); + + testRole(accTable4, ROLE_TABLE); + + is(accTable4.getCellAt(0, 0).firstChild.name, "cell0", "wrong cell"); + is(accTable4.getCellAt(0, 1).firstChild.name, "cell1", "wrong cell"); + is(accTable4.getCellAt(1, 0).firstChild.name, "cell2", "wrong cell"); + is(accTable4.getCellAt(1, 1).firstChild.name, "cell3", "wrong cell"); + } + + SimpleTest.finish(); +} +SimpleTest.waitForExplicitFinish(); +addA11yLoadEvent(doTest); + </script> + </head> + + <body > + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=419811">Mozilla Bug 419811</a> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <!-- Test Table --> + <br><br><b> Testing Table:</b><br><br> + <center> + <table id="table3" border="1" role="alert"> + <tr> + <td>cell0</td> + <td>cell1</td> + </tr> + </table> + + <table id="table4" border="1" role="log"> + <tr aria-live="polite" id="tr"> + <td>cell0</td> + <td>cell1</td> + </tr> + <tr> + <td>cell2</td> + <td>cell3</td> + </tr> + </table> + + </center> + </body> +</html> diff --git a/accessible/tests/mochitest/table/test_table_mutation.html b/accessible/tests/mochitest/table/test_table_mutation.html new file mode 100644 index 0000000000..671e627244 --- /dev/null +++ b/accessible/tests/mochitest/table/test_table_mutation.html @@ -0,0 +1,100 @@ +<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <title>Table mutation</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../table.js"></script> + <script type="application/javascript" + src="../promisified-events.js"></script> + + <script type="application/javascript"> + + async function doTest() { + let headers = [ + { + cell: "t1r1c1", + columnHeaderCells: [], + rowHeaderCells: [], + }, + // t1r2 is hidden + { + cell: "t1r3c1", + columnHeaderCells: ["t1r1c1"], + rowHeaderCells: [], + }, + ]; + testHeaderCells(headers); + + info("Remove row"); + let reordered = waitForEvent(EVENT_REORDER, "t1"); + getNode("t1r1").hidden = true; + await reordered; + headers = [ + // t1r1 and t1r2 are hidden + { + cell: "t1r3c1", + columnHeaderCells: [], + rowHeaderCells: [], + }, + ]; + testHeaderCells(headers); + + info("Add rows"); + reordered = waitForEvent(EVENT_REORDER, "t1"); + getNode("t1r1").hidden = false; + getNode("t1r2").hidden = false; + await reordered; + headers = [ + { + cell: "t1r1c1", + columnHeaderCells: [], + rowHeaderCells: [], + }, + { + cell: "t1r2c1", + columnHeaderCells: ["t1r1c1"], + rowHeaderCells: [], + }, + { + cell: "t1r3c1", + columnHeaderCells: ["t1r2c1", "t1r1c1"], + rowHeaderCells: [], + }, + ]; + testHeaderCells(headers); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <table id="t1"> + <tr id="t1r1"> + <th id="t1r1c1"></th> + </tr> + <tr id="t1r2" hidden> + <th id="t1r2c1"></th> + </tr> + <tr id="t1r3"> + <td id="t1r3c1"></td> + </tr> + </table> +</body> +</html> |