summaryrefslogtreecommitdiffstats
path: root/accessible/tests/mochitest/table
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--accessible/tests/mochitest/table.js1034
-rw-r--r--accessible/tests/mochitest/table/a11y.ini24
-rw-r--r--accessible/tests/mochitest/table/test_css_tables.html114
-rw-r--r--accessible/tests/mochitest/table/test_headers_ariagrid.html183
-rw-r--r--accessible/tests/mochitest/table/test_headers_ariatable.html94
-rw-r--r--accessible/tests/mochitest/table/test_headers_table.html756
-rw-r--r--accessible/tests/mochitest/table/test_headers_tree.xhtml100
-rw-r--r--accessible/tests/mochitest/table/test_indexes_ariagrid.html159
-rw-r--r--accessible/tests/mochitest/table/test_indexes_table.html481
-rw-r--r--accessible/tests/mochitest/table/test_indexes_tree.xhtml70
-rw-r--r--accessible/tests/mochitest/table/test_layoutguess.html554
-rw-r--r--accessible/tests/mochitest/table/test_mtable.html160
-rw-r--r--accessible/tests/mochitest/table/test_sels_ariagrid.html159
-rw-r--r--accessible/tests/mochitest/table/test_sels_table.html178
-rw-r--r--accessible/tests/mochitest/table/test_sels_tree.xhtml78
-rw-r--r--accessible/tests/mochitest/table/test_struct_ariagrid.html163
-rw-r--r--accessible/tests/mochitest/table/test_struct_ariatreegrid.html74
-rw-r--r--accessible/tests/mochitest/table/test_struct_table.html217
-rw-r--r--accessible/tests/mochitest/table/test_struct_tree.xhtml73
-rw-r--r--accessible/tests/mochitest/table/test_table_1.html107
-rw-r--r--accessible/tests/mochitest/table/test_table_2.html87
-rw-r--r--accessible/tests/mochitest/table/test_table_mutation.html100
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">&nbsp;</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">&nbsp;</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>