diff --git a/test/browser/TreeDataGrid.test.tsx b/test/browser/TreeDataGrid.test.tsx
index 6a170f79cb..d303bcff03 100644
--- a/test/browser/TreeDataGrid.test.tsx
+++ b/test/browser/TreeDataGrid.test.tsx
@@ -5,7 +5,18 @@ import type { Column } from '../../src';
import { SelectColumn, textEditor, TreeDataGrid } from '../../src';
import { focusSinkClassname } from '../../src/style/core';
import { rowSelected } from '../../src/style/row';
-import { getCellsAtRowIndex, getHeaderCells, getRows, getSelectedCell, getTreeGrid } from './utils';
+import {
+ getCell,
+ getCellsAtRowIndex,
+ getRowByCell,
+ getRowByCellName,
+ getRows,
+ getSelectAllCheckbox,
+ getSelectedCell,
+ getTreeGrid,
+ testCount,
+ testRowCount
+} from './utils';
const rowSelectedClassname = 'rdg-row-selected';
@@ -128,35 +139,38 @@ function setup(groupBy: string[], groupIdGetter?: (groupKey: string, parentId?:
page.render();
}
-function getHeaderCellsContent() {
- return getHeaderCells().map((cell) => cell.textContent);
+async function testHeaderCellsContent(expected: readonly string[]) {
+ const headerCells = page.getByRole('columnheader');
+ await testCount(headerCells, expected.length);
+ const content = headerCells.elements().map((cell) => cell.textContent);
+ expect(content).toStrictEqual(expected);
}
test('should not group if groupBy is empty', async () => {
setup([]);
await expect.element(getTreeGrid()).toHaveAttribute('aria-rowcount', '7');
- expect(getHeaderCellsContent()).toStrictEqual(['', 'Sport', 'Country', 'Year', 'Id']);
- expect(getRows()).toHaveLength(6);
+ await testHeaderCellsContent(['', 'Sport', 'Country', 'Year', 'Id']);
+ await testRowCount(7);
});
test('should not group if column does not exist', async () => {
setup(['abc']);
await expect.element(getTreeGrid()).toHaveAttribute('aria-rowcount', '7');
- expect(getRows()).toHaveLength(6);
+ await testRowCount(7);
});
test('should group by single column', async () => {
setup(['country']);
await expect.element(getTreeGrid()).toHaveAttribute('aria-rowcount', '9');
- expect(getHeaderCellsContent()).toStrictEqual(['', 'Country', 'Sport', 'Year', 'Id']);
- expect(getRows()).toHaveLength(4);
+ await testHeaderCellsContent(['', 'Country', 'Sport', 'Year', 'Id']);
+ await testRowCount(5);
});
test('should group by multiple columns', async () => {
setup(['country', 'year']);
await expect.element(getTreeGrid()).toHaveAttribute('aria-rowcount', '13');
- expect(getHeaderCellsContent()).toStrictEqual(['', 'Country', 'Year', 'Sport', 'Id']);
- expect(getRows()).toHaveLength(4);
+ await testHeaderCellsContent(['', 'Country', 'Year', 'Sport', 'Id']);
+ await testRowCount(5);
});
test('should use groupIdGetter when provided', async () => {
@@ -165,186 +179,180 @@ test('should use groupIdGetter when provided', async () => {
);
setup(['country', 'year'], groupIdGetter);
expect(groupIdGetter).toHaveBeenCalled();
- expect(getTreeGrid()).toHaveAttribute('aria-rowcount', '13');
- expect(getHeaderCellsContent()).toStrictEqual(['', 'Country', 'Year', 'Sport', 'Id']);
- expect(getRows()).toHaveLength(4);
+ await expect.element(getTreeGrid()).toHaveAttribute('aria-rowcount', '13');
+ await testHeaderCellsContent(['', 'Country', 'Year', 'Sport', 'Id']);
+ await testRowCount(5);
groupIdGetter.mockClear();
- await userEvent.click(page.getByRole('gridcell', { name: 'USA' }));
- expect(getRows()).toHaveLength(6);
+ await userEvent.click(getCell('USA'));
+ await testRowCount(7);
expect(groupIdGetter).toHaveBeenCalled();
- await userEvent.click(page.getByRole('gridcell', { name: 'Canada' }));
- expect(getRows()).toHaveLength(8);
- await userEvent.click(page.getByRole('gridcell', { name: '2020' }));
- expect(getRows()).toHaveLength(9);
+ await userEvent.click(getCell('Canada'));
+ await testRowCount(9);
+ await userEvent.click(getCell('2020'));
+ await testRowCount(10);
});
test('should ignore duplicate groupBy columns', async () => {
setup(['year', 'year', 'year']);
await expect.element(getTreeGrid()).toHaveAttribute('aria-rowcount', '10');
- expect(getRows()).toHaveLength(5);
+ await testRowCount(6);
});
test('should use groupBy order while grouping', async () => {
setup(['year', 'country']);
await expect.element(getTreeGrid()).toHaveAttribute('aria-rowcount', '14');
- expect(getHeaderCellsContent()).toStrictEqual(['', 'Year', 'Country', 'Sport', 'Id']);
- expect(getRows()).toHaveLength(5);
+ await testHeaderCellsContent(['', 'Year', 'Country', 'Sport', 'Id']);
+ await testRowCount(6);
});
test('should toggle group when group cell is clicked', async () => {
setup(['year']);
- expect(getRows()).toHaveLength(5);
- const groupCell = page.getByRole('gridcell', { name: '2021' });
+ await testRowCount(6);
+ const groupCell = getCell('2021');
await userEvent.click(groupCell);
- expect(getRows()).toHaveLength(7);
+ await testRowCount(8);
await userEvent.click(groupCell);
- expect(getRows()).toHaveLength(5);
+ await testRowCount(6);
});
test('should toggle group using keyboard', async () => {
setup(['year']);
- expect(getRows()).toHaveLength(5);
- const groupCell = page.getByRole('gridcell', { name: '2021' });
+ await testRowCount(6);
+ const groupCell = getCell('2021');
await userEvent.click(groupCell);
- expect(getRows()).toHaveLength(7);
+ await testRowCount(8);
// clicking on the group cell selects the row
await expect.element(getSelectedCell()).not.toBeInTheDocument();
- await expect.element(getRows()[2]).toHaveClass(rowSelectedClassname);
+ await expect.element(getRowByCellName('2021')).toHaveClass(rowSelectedClassname);
await userEvent.keyboard('{arrowright}{arrowright}{enter}');
- expect(getRows()).toHaveLength(5);
+ await testRowCount(6);
await userEvent.keyboard('{enter}');
- expect(getRows()).toHaveLength(7);
+ await testRowCount(8);
});
test('should set aria-attributes', async () => {
setup(['year', 'country']);
- const groupCell1 = page.getByRole('gridcell', { name: '2020' }).element();
- const groupRow1 = groupCell1.parentElement!;
- expect(groupRow1).toHaveAttribute('aria-level', '1');
- expect(groupRow1).toHaveAttribute('aria-setsize', '3');
- expect(groupRow1).toHaveAttribute('aria-posinset', '1');
- expect(groupRow1).toHaveAttribute('aria-rowindex', '3');
- expect(groupRow1).toHaveAttribute('aria-expanded', 'false');
-
- const groupCell2 = page.getByRole('gridcell', { name: '2021' }).element();
- const groupRow2 = groupCell2.parentElement!;
- expect(groupRow2).toHaveAttribute('aria-level', '1');
- expect(groupRow2).toHaveAttribute('aria-setsize', '3');
- expect(groupRow2).toHaveAttribute('aria-posinset', '2');
- expect(groupRow2).toHaveAttribute('aria-rowindex', '6');
- expect(groupRow1).toHaveAttribute('aria-expanded', 'false');
+ const groupRow1 = getRowByCellName('2020');
+ await expect.element(groupRow1).toHaveAttribute('aria-level', '1');
+ await expect.element(groupRow1).toHaveAttribute('aria-setsize', '3');
+ await expect.element(groupRow1).toHaveAttribute('aria-posinset', '1');
+ await expect.element(groupRow1).toHaveAttribute('aria-rowindex', '3');
+ await expect.element(groupRow1).toHaveAttribute('aria-expanded', 'false');
+
+ const groupCell2 = getCell('2021');
+ const groupRow2 = getRowByCell(groupCell2);
+ await expect.element(groupRow2).toHaveAttribute('aria-level', '1');
+ await expect.element(groupRow2).toHaveAttribute('aria-setsize', '3');
+ await expect.element(groupRow2).toHaveAttribute('aria-posinset', '2');
+ await expect.element(groupRow2).toHaveAttribute('aria-rowindex', '6');
+ await expect.element(groupRow1).toHaveAttribute('aria-expanded', 'false');
await userEvent.click(groupCell2);
- expect(groupRow2).toHaveAttribute('aria-expanded', 'true');
+ await expect.element(groupRow2).toHaveAttribute('aria-expanded', 'true');
- const groupCell3 = page.getByRole('gridcell', { name: 'Canada' }).element();
- const groupRow3 = groupCell3.parentElement!;
- expect(groupRow3).toHaveAttribute('aria-level', '2');
- expect(groupRow3).toHaveAttribute('aria-setsize', '2');
- expect(groupRow3).toHaveAttribute('aria-posinset', '2');
- expect(groupRow3).toHaveAttribute('aria-rowindex', '9');
- expect(groupRow1).toHaveAttribute('aria-expanded', 'false');
+ const groupCell3 = getCell('Canada');
+ const groupRow3 = getRowByCell(groupCell3);
+ await expect.element(groupRow3).toHaveAttribute('aria-level', '2');
+ await expect.element(groupRow3).toHaveAttribute('aria-setsize', '2');
+ await expect.element(groupRow3).toHaveAttribute('aria-posinset', '2');
+ await expect.element(groupRow3).toHaveAttribute('aria-rowindex', '9');
+ await expect.element(groupRow1).toHaveAttribute('aria-expanded', 'false');
await userEvent.click(groupCell3);
- expect(groupRow3).toHaveAttribute('aria-expanded', 'true');
+ await expect.element(groupRow3).toHaveAttribute('aria-expanded', 'true');
});
test('should select rows in a group', async () => {
setup(['year', 'country']);
- const headerCheckbox = page.getByRole('checkbox', { name: 'Select All' });
+ const headerCheckbox = getSelectAllCheckbox();
await expect.element(headerCheckbox).not.toBeChecked();
// expand group
- const groupCell1 = page.getByRole('gridcell', { name: '2021' }).element();
+ const groupCell1 = getCell('2021');
await userEvent.click(groupCell1);
- const groupCell2 = page.getByRole('gridcell', { name: 'Canada' }).element();
+ const groupCell2 = getCell('Canada');
await userEvent.click(groupCell2);
- expect(page.getByRole('row', { selected: true }).all()).toHaveLength(0);
+ const selectedRows = page.getByRole('row', { selected: true });
+ await testCount(selectedRows, 0);
// select parent row
- await userEvent.click(
- page.elementLocator(groupCell1.parentElement!).getByRole('checkbox', { name: 'Select Group' })
- );
- let selectedRows = page.getByRole('row', { selected: true }).all();
- expect(selectedRows).toHaveLength(4);
- await expect.element(selectedRows[0]).toHaveAttribute('aria-rowindex', '6');
- await expect.element(selectedRows[1]).toHaveAttribute('aria-rowindex', '7');
- await expect.element(selectedRows[2]).toHaveAttribute('aria-rowindex', '9');
- await expect.element(selectedRows[3]).toHaveAttribute('aria-rowindex', '10');
+ await userEvent.click(getRowByCell(groupCell1).getByRole('checkbox', { name: 'Select Group' }));
+ await testCount(selectedRows, 4);
+ await expect.element(selectedRows.nth(0)).toHaveAttribute('aria-rowindex', '6');
+ await expect.element(selectedRows.nth(1)).toHaveAttribute('aria-rowindex', '7');
+ await expect.element(selectedRows.nth(2)).toHaveAttribute('aria-rowindex', '9');
+ await expect.element(selectedRows.nth(3)).toHaveAttribute('aria-rowindex', '10');
// unselecting child should unselect the parent row
- await userEvent.click(selectedRows[3].getByRole('checkbox', { name: 'Select' }));
- selectedRows = page.getByRole('row', { selected: true }).all();
- expect(selectedRows).toHaveLength(1);
- await expect.element(selectedRows[0]).toHaveAttribute('aria-rowindex', '7');
+ await userEvent.click(selectedRows.nth(3).getByRole('checkbox', { name: 'Select' }));
+ await testCount(selectedRows, 1);
+ await expect.element(selectedRows.nth(0)).toHaveAttribute('aria-rowindex', '7');
// select child group
- const checkbox = page.elementLocator(groupCell2.parentElement!).getByRole('checkbox', {
+ const checkbox = getRowByCell(groupCell2).getByRole('checkbox', {
name: 'Select Group'
});
await userEvent.click(checkbox);
- selectedRows = page.getByRole('row', { selected: true }).all();
- expect(selectedRows).toHaveLength(4);
+ await testCount(selectedRows, 4);
// unselect child group
await userEvent.click(checkbox);
- selectedRows = page.getByRole('row', { selected: true }).all();
- expect(selectedRows).toHaveLength(1);
+ await testCount(selectedRows, 1);
- await userEvent.click(page.getByRole('gridcell', { name: '2020' }));
- await userEvent.click(page.getByRole('gridcell', { name: '2022' }));
+ await userEvent.click(getCell('2020'));
+ await userEvent.click(getCell('2022'));
await userEvent.click(headerCheckbox);
- await expect.element(page.getByRole('row', { selected: true })).not.toBeInTheDocument();
+ await testCount(selectedRows, 0);
await userEvent.click(headerCheckbox);
- expect(page.getByRole('row', { selected: true }).all()).toHaveLength(8);
+ await testCount(selectedRows, 8);
await userEvent.click(headerCheckbox);
- await expect.element(page.getByRole('row', { selected: true })).not.toBeInTheDocument();
+ await testCount(selectedRows, 0);
});
test('cell navigation in a treegrid', async () => {
setup(['country', 'year']);
- expect(getRows()).toHaveLength(4);
- const focusSink = document.querySelector(`.${focusSinkClassname}`);
+ await testRowCount(5);
+ const focusSink = page.getBySelector(`.${focusSinkClassname}`);
// expand group
- const groupCell1 = page.getByRole('gridcell', { name: 'USA' });
+ const groupCell1 = getCell('USA');
expect(document.body).toHaveFocus();
- expect(focusSink).toHaveAttribute('tabIndex', '-1');
+ await expect.element(focusSink).toHaveAttribute('tabIndex', '-1');
await userEvent.click(groupCell1);
- expect(focusSink).toHaveFocus();
- expect(focusSink).toHaveAttribute('tabIndex', '0');
- expect(focusSink).toHaveStyle('grid-row-start:3');
- expect(focusSink).toHaveClass(rowSelected);
+ await expect.element(focusSink).toHaveFocus();
+ await expect.element(focusSink).toHaveAttribute('tabIndex', '0');
+ await expect.element(focusSink).toHaveStyle('grid-row-start:3');
+ await expect.element(focusSink).toHaveClass(rowSelected);
await userEvent.keyboard('{arrowup}');
- expect(focusSink).toHaveFocus();
- expect(focusSink).toHaveStyle('grid-row-start:2');
- expect(focusSink).toHaveClass(rowSelected);
+ await expect.element(focusSink).toHaveFocus();
+ await expect.element(focusSink).toHaveStyle('grid-row-start:2');
+ await expect.element(focusSink).toHaveClass(rowSelected);
await userEvent.keyboard('{arrowup}');
- expect(focusSink).toHaveFocus();
- expect(focusSink).toHaveStyle('grid-row-start:1');
- expect(focusSink).toHaveClass(rowSelected);
- expect(focusSink).toHaveFocus();
- expect(focusSink).toHaveStyle('grid-row-start:1');
- expect(focusSink).toHaveClass(rowSelected);
+ await expect.element(focusSink).toHaveFocus();
+ await expect.element(focusSink).toHaveStyle('grid-row-start:1');
+ await expect.element(focusSink).toHaveClass(rowSelected);
+ await expect.element(focusSink).toHaveFocus();
+ await expect.element(focusSink).toHaveStyle('grid-row-start:1');
+ await expect.element(focusSink).toHaveClass(rowSelected);
await userEvent.keyboard('{arrowdown}');
- expect(focusSink).toHaveFocus();
- expect(focusSink).toHaveStyle('grid-row-start:2');
- expect(focusSink).toHaveClass(rowSelected);
- const groupCell2 = page.getByRole('gridcell', { name: '2021' });
+ await expect.element(focusSink).toHaveFocus();
+ await expect.element(focusSink).toHaveStyle('grid-row-start:2');
+ await expect.element(focusSink).toHaveClass(rowSelected);
+ const groupCell2 = getCell('2021');
await userEvent.click(groupCell2);
- expect(focusSink).toHaveFocus();
- expect(focusSink).toHaveAttribute('tabIndex', '0');
+ await expect.element(focusSink).toHaveFocus();
+ await expect.element(focusSink).toHaveAttribute('tabIndex', '0');
// select cell
await userEvent.click(getCellsAtRowIndex(5)[1]);
expect(getCellsAtRowIndex(5)[1]).toHaveAttribute('aria-selected', 'true');
- expect(focusSink).toHaveAttribute('tabIndex', '-1');
+ await expect.element(focusSink).toHaveAttribute('tabIndex', '-1');
// select the previous cell
await userEvent.keyboard('{arrowleft}');
@@ -355,7 +363,7 @@ test('cell navigation in a treegrid', async () => {
await userEvent.keyboard('{arrowleft}');
expect(getCellsAtRowIndex(5)[0]).toHaveAttribute('aria-selected', 'false');
await expect.element(getRows()[4]).toHaveClass(rowSelectedClassname);
- expect(focusSink).toHaveFocus();
+ await expect.element(focusSink).toHaveFocus();
// if the row is selected then arrowright should select the first cell on the same row
await userEvent.keyboard('{arrowright}');
@@ -363,15 +371,15 @@ test('cell navigation in a treegrid', async () => {
await userEvent.keyboard('{arrowleft}{arrowup}');
- expect(getRows()).toHaveLength(7);
+ await testRowCount(8);
// left arrow should collapse the group
await userEvent.keyboard('{arrowleft}');
- expect(getRows()).toHaveLength(6);
+ await testRowCount(7);
// right arrow should expand the group
await userEvent.keyboard('{arrowright}');
- expect(getRows()).toHaveLength(7);
+ await testRowCount(8);
// left arrow on a collapsed group should select the parent group
await expect.element(getRows()[1]).not.toHaveClass(rowSelectedClassname);
@@ -386,19 +394,19 @@ test('cell navigation in a treegrid', async () => {
// collpase parent group
await userEvent.keyboard('{arrowdown}{arrowdown}{arrowleft}');
- await expect.element(page.getByRole('gridcell', { name: '2021' })).not.toBeInTheDocument();
- expect(getRows()).toHaveLength(4);
+ await expect.element(getCell('2021')).not.toBeInTheDocument();
+ await testRowCount(5);
});
test('copy/paste when grouping is enabled', async () => {
setup(['year']);
- await userEvent.click(page.getByRole('gridcell', { name: '2021' }));
+ await userEvent.click(getCell('2021'));
await userEvent.copy();
expect(onCellCopySpy).not.toHaveBeenCalled();
await userEvent.paste();
expect(onCellPasteSpy).not.toHaveBeenCalled();
- await userEvent.click(page.getByRole('gridcell', { name: 'USA' }));
+ await userEvent.click(getCell('USA'));
await userEvent.copy();
expect(onCellCopySpy).toHaveBeenCalledExactlyOnceWith(
{
@@ -427,16 +435,18 @@ test('copy/paste when grouping is enabled', async () => {
test('update row using cell renderer', async () => {
setup(['year']);
- await userEvent.click(page.getByRole('gridcell', { name: '2021' }));
- await userEvent.click(page.getByRole('gridcell', { name: 'USA' }));
+ await userEvent.click(getCell('2021'));
+ await userEvent.click(getCell('USA'));
await userEvent.keyboard('{arrowright}{arrowright}');
await expect.element(getSelectedCell()).toHaveTextContent('value: 2');
await userEvent.click(page.getByRole('button', { name: 'value: 2' }));
await expect.element(getSelectedCell()).toHaveTextContent('value: 12');
});
-test('custom renderGroupCell', () => {
+test('custom renderGroupCell', async () => {
setup(['country']);
- expect(getCellsAtRowIndex(1)[4]).toHaveTextContent('1');
- expect(getCellsAtRowIndex(4)[4]).toHaveTextContent('3');
+ await expect.element(getRowByCellName('USA').getByRole('gridcell').nth(4)).toHaveTextContent('1');
+ await expect
+ .element(getRowByCellName('Canada').getByRole('gridcell').nth(4))
+ .toHaveTextContent('3');
});
diff --git a/test/browser/column/grouping.test.ts b/test/browser/column/grouping.test.ts
index fbfe6a5aa3..9234755ba5 100644
--- a/test/browser/column/grouping.test.ts
+++ b/test/browser/column/grouping.test.ts
@@ -1,7 +1,14 @@
import { page, userEvent } from '@vitest/browser/context';
import type { ColumnOrColumnGroup } from '../../../src';
-import { getSelectedCell, setup, tabIntoGrid, validateCellPosition } from '../utils';
+import {
+ getGrid,
+ getSelectedCell,
+ setup,
+ tabIntoGrid,
+ testCount,
+ validateCellPosition
+} from '../utils';
const columns: readonly ColumnOrColumnGroup>[] = [
{ key: 'col1', name: 'col 1' },
@@ -90,31 +97,29 @@ const columns: readonly ColumnOrColumnGroup>[] = [
test('grouping', async () => {
setup({ columns, rows: [{}] });
- const grid = page.getByRole('grid');
+ const grid = getGrid();
await expect.element(grid).toHaveAttribute('aria-colcount', '12');
await expect.element(grid).toHaveAttribute('aria-rowcount', '5');
- const rows = page.getByRole('row').all();
- expect(rows).toHaveLength(5);
+ const rows = page.getByRole('row');
+ await testCount(rows, 5);
- await expect.element(rows[0]).toHaveAttribute('aria-rowindex', '1');
- await expect.element(rows[1]).toHaveAttribute('aria-rowindex', '2');
- await expect.element(rows[2]).toHaveAttribute('aria-rowindex', '3');
- await expect.element(rows[3]).toHaveAttribute('aria-rowindex', '4');
- await expect.element(rows[4]).toHaveAttribute('aria-rowindex', '5');
+ await expect.element(rows.nth(0)).toHaveAttribute('aria-rowindex', '1');
+ await expect.element(rows.nth(1)).toHaveAttribute('aria-rowindex', '2');
+ await expect.element(rows.nth(2)).toHaveAttribute('aria-rowindex', '3');
+ await expect.element(rows.nth(3)).toHaveAttribute('aria-rowindex', '4');
+ await expect.element(rows.nth(4)).toHaveAttribute('aria-rowindex', '5');
- expect(rows[0].getByRole('columnheader').all()).toHaveLength(2);
- expect(rows[1].getByRole('columnheader').all()).toHaveLength(2);
- expect(rows[2].getByRole('columnheader').all()).toHaveLength(4);
- expect(rows[3].getByRole('columnheader').all()).toHaveLength(12);
- expect(rows[4].getByRole('columnheader').all()).toHaveLength(0);
+ await testCount(rows.nth(0).getByRole('columnheader'), 2);
+ await testCount(rows.nth(1).getByRole('columnheader'), 2);
+ await testCount(rows.nth(2).getByRole('columnheader'), 4);
+ await testCount(rows.nth(3).getByRole('columnheader'), 12);
+ await testCount(rows.nth(4).getByRole('columnheader'), 0);
- const headerCells = page.getByRole('columnheader').all();
- expect(headerCells).toHaveLength(20);
-
- const headerCellDetails = headerCells.map((cellLocator) => {
- const cell = cellLocator.element();
+ const headerCells = page.getByRole('columnheader');
+ await testCount(headerCells, 20);
+ const headerCellDetails = headerCells.elements().map((cell) => {
return {
text: cell.textContent,
colIndex: cell.getAttribute('aria-colindex'),
diff --git a/test/browser/column/renderEditCell.test.tsx b/test/browser/column/renderEditCell.test.tsx
index 3462621fbb..95f358d861 100644
--- a/test/browser/column/renderEditCell.test.tsx
+++ b/test/browser/column/renderEditCell.test.tsx
@@ -4,7 +4,7 @@ import { commands, page, userEvent } from '@vitest/browser/context';
import { DataGrid } from '../../../src';
import type { Column, DataGridProps } from '../../../src';
-import { getCell, getCellsAtRowIndex, getGrid, getSelectedCell } from '../utils';
+import { getCell, getCellsAtRowIndex, getGrid, getSelectedCell, testCount } from '../utils';
interface Row {
col1: number;
@@ -98,15 +98,15 @@ describe('Editor', () => {
.getByRole('row')
.filter({ has: getSelectedCell() })
.getByRole('gridcell');
- await expect.poll(() => selectedRowCells.elements().length).toBe(2);
+ await testCount(selectedRowCells, 2);
await commands.scrollGrid({ scrollTop: 2000 });
- await expect.poll(() => selectedRowCells.elements().length).toBe(1);
+ await testCount(selectedRowCells, 1);
const editor = page.getByRole('spinbutton', { name: 'col1-editor' });
await expect.element(editor).not.toBeInTheDocument();
expect(getGrid().element().scrollTop).toBe(2000);
// TODO: await userEvent.keyboard('123'); fails in FF
await userEvent.keyboard('{enter}123');
- await expect.poll(() => selectedRowCells.elements().length).toBe(2);
+ await testCount(selectedRowCells, 2);
await expect.element(editor).toHaveValue(123);
expect(getGrid().element().scrollTop).toBe(0);
});
diff --git a/test/browser/column/resizable.test.tsx b/test/browser/column/resizable.test.tsx
index 49a1a1004b..f17eb1b286 100644
--- a/test/browser/column/resizable.test.tsx
+++ b/test/browser/column/resizable.test.tsx
@@ -2,40 +2,25 @@ import { useState } from 'react';
import { commands, page, userEvent } from '@vitest/browser/context';
import { DataGrid, type Column, type ColumnWidth, type ColumnWidths } from '../../../src';
-import { getGrid, getHeaderCells, setup } from '../utils';
+import { getGrid, getHeaderCell, setup } from '../utils';
interface Row {
readonly col1: number;
readonly col2: string;
}
-function queryResizeHandle(column: Element) {
- return column.querySelector('.rdg-resize-handle');
+function getResizeHandle(name: string) {
+ return getHeaderCell(name).getBySelector('.rdg-resize-handle');
}
-function getResizeHandle(column: Element) {
- const resizeHandle = queryResizeHandle(column);
+async function resize(columnName: string, resizeBy: number | readonly number[]) {
+ await expect.element(getResizeHandle(columnName)).toBeInTheDocument();
- if (resizeHandle === null) {
- throw new Error('Resize handle not found');
- }
-
- return resizeHandle;
-}
-
-interface ResizeArgs {
- readonly column: Element;
- readonly resizeBy: number | readonly number[];
-}
-
-async function resize({ column, resizeBy }: ResizeArgs) {
- expect(getResizeHandle(column)).toBeInTheDocument();
-
- await commands.resizeColumn(resizeBy);
+ await commands.resizeColumn('col2', resizeBy);
}
-async function autoResize(column: Element) {
- const resizeHandle = getResizeHandle(column);
+async function autoResize(columnName: string) {
+ const resizeHandle = getResizeHandle(columnName);
await userEvent.dblClick(resizeHandle);
}
@@ -56,10 +41,9 @@ const columns: readonly Column[] = [
}
];
-test('cannot resize or auto resize column when resizable is not specified', () => {
+test('cannot resize or auto resize column when resizable is not specified', async () => {
setup({ columns, rows: [] });
- const [col1] = getHeaderCells();
- expect(queryResizeHandle(col1)).not.toBeInTheDocument();
+ await expect.element(getResizeHandle('col1')).not.toBeInTheDocument();
});
test('should resize column when dragging the handle', async () => {
@@ -68,8 +52,7 @@ test('should resize column when dragging the handle', async () => {
const grid = getGrid();
expect(onColumnResize).not.toHaveBeenCalled();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
- const [, col2] = getHeaderCells();
- await resize({ column: col2, resizeBy: -50 });
+ await resize('col2', -50);
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 150px' });
expect(onColumnResize).toHaveBeenCalledExactlyOnceWith(expect.objectContaining(columns[1]), 150);
});
@@ -78,8 +61,7 @@ test('should use the maxWidth if specified when dragging the handle', async () =
setup({ columns, rows: [] });
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px ' });
- const [, col2] = getHeaderCells();
- await resize({ column: col2, resizeBy: 1000 });
+ await resize('col2', 1000);
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 400px' });
});
@@ -87,8 +69,7 @@ test('should use the minWidth if specified when dragging the handle', async () =
setup({ columns, rows: [] });
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
- const [, col2] = getHeaderCells();
- await resize({ column: col2, resizeBy: -150 });
+ await resize('col2', -150);
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 100px' });
});
@@ -98,7 +79,7 @@ test('should resize column using keboard', async () => {
const grid = getGrid();
expect(onColumnResize).not.toHaveBeenCalled();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
- const [, col2] = getHeaderCells();
+ const col2 = getHeaderCell('col2');
await userEvent.click(col2);
await userEvent.keyboard('{Control>}{ArrowRight}{/Control}');
@@ -116,7 +97,7 @@ test('should use the maxWidth if specified when resizing using keyboard', async
setup({ columns, rows: [], onColumnResize });
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px ' });
- const [, col2] = getHeaderCells();
+ const col2 = getHeaderCell('col2');
await userEvent.click(col2);
await userEvent.keyboard(`{Control>}${'{ArrowRight}'.repeat(22)}{/Control}`);
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 400px' });
@@ -128,7 +109,7 @@ test('should use the minWidth if specified resizing using keyboard', async () =>
setup({ columns, rows: [], onColumnResize });
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
- const [, col2] = getHeaderCells();
+ const col2 = getHeaderCell('col2');
await userEvent.click(col2);
await userEvent.keyboard(`{Control>}${'{ArrowLeft}'.repeat(12)}{/Control}`);
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 100px' });
@@ -149,8 +130,7 @@ test('should auto resize column when resize handle is double clicked', async ()
});
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
- const [, col2] = getHeaderCells();
- await autoResize(col2);
+ await autoResize('col2');
await testGridTemplateColumns('100px 327.703px', '100px 327.833px', '100px 400px');
expect(onColumnResize).toHaveBeenCalledExactlyOnceWith(
expect.objectContaining(columns[1]),
@@ -177,8 +157,7 @@ test('should use the maxWidth if specified on auto resize', async () => {
});
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
- const [, col2] = getHeaderCells();
- await autoResize(col2);
+ await autoResize('col2');
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 400px' });
});
@@ -194,8 +173,7 @@ test('should use the minWidth if specified on auto resize', async () => {
});
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
- const [, col2] = getHeaderCells();
- await autoResize(col2);
+ await autoResize('col2');
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '100px 100px' });
});
@@ -237,8 +215,7 @@ test('should remeasure flex columns when resizing a column', async () => {
});
await testGridTemplateColumns('639.328px 639.328px 639.344px', '639.333px 639.333px 639.333px');
- const [col1] = getHeaderCells();
- await autoResize(col1);
+ await autoResize('col1');
await testGridTemplateColumns(
'79.1406px 919.422px 919.438px',
'79.1667px 919.417px 919.417px',
@@ -246,7 +223,7 @@ test('should remeasure flex columns when resizing a column', async () => {
);
expect(onColumnResize).toHaveBeenCalledOnce();
// onColumnResize is not called if width is not changed
- await autoResize(col1);
+ await autoResize('col1');
await testGridTemplateColumns(
'79.1406px 919.422px 919.438px',
'79.1667px 919.417px 919.417px',
@@ -302,8 +279,7 @@ test('should use columnWidths and onColumnWidthsChange props when provided', asy
const grid = getGrid();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '101px 201px' });
- const [, col2] = getHeaderCells();
- await autoResize(col2);
+ await autoResize('col2');
expect(onColumnWidthsChangeSpy).toHaveBeenCalledExactlyOnceWith(
new Map([
['col1', { width: 101, type: 'measured' }],
@@ -317,7 +293,7 @@ test('should use columnWidths and onColumnWidthsChange props when provided', asy
onColumnWidthsChangeSpy.mockClear();
onColumnResizeSpy.mockClear();
- await resize({ column: col2, resizeBy: [5, 5, 5] });
+ await resize('col2', [5, 5, 5]);
expect(onColumnWidthsChangeSpy).toHaveBeenCalledExactlyOnceWith(
new Map([
['col1', { width: 101, type: 'measured' }],
@@ -335,7 +311,7 @@ test('should use columnWidths and onColumnWidthsChange props when provided', asy
expect(onColumnWidthsChangeSpy).not.toHaveBeenCalled();
expect(onColumnResizeSpy).not.toHaveBeenCalled();
await expect.element(grid).toHaveStyle({ gridTemplateColumns: '120px 120px' });
- await resize({ column: col2, resizeBy: [5, 5] });
+ await resize('col2', [5, 5]);
expect(onColumnWidthsChangeSpy).toHaveBeenCalledExactlyOnceWith(
new Map([
['col1', { width: 120, type: 'measured' }],
@@ -349,9 +325,11 @@ async function testGridTemplateColumns(chrome: string, firefox: string, firefoxC
if (navigator.userAgent.includes('Chrome')) {
await expect.element(grid).toHaveStyle({ gridTemplateColumns: chrome });
} else {
- expect((grid.element() as HTMLDivElement).style.gridTemplateColumns).toBeOneOf([
- firefox,
- firefoxCI
- ]);
+ await vi.waitFor(() => {
+ expect((grid.element() as HTMLDivElement).style.gridTemplateColumns).toBeOneOf([
+ firefox,
+ firefoxCI
+ ]);
+ });
}
}
diff --git a/test/browser/columnOrder.test.tsx b/test/browser/columnOrder.test.tsx
index b8639df072..fcdfe4f9de 100644
--- a/test/browser/columnOrder.test.tsx
+++ b/test/browser/columnOrder.test.tsx
@@ -2,7 +2,7 @@ import { page } from '@vitest/browser/context';
import { DataGrid, SelectColumn, TreeDataGrid } from '../../src';
import type { Column } from '../../src';
-import { getHeaderCells } from './utils';
+import { testCount } from './utils';
const frozen1: Column = {
key: 'f1',
@@ -26,10 +26,10 @@ const standard2: Column = {
name: 'std2'
};
-test('column order', () => {
+test('column order', async () => {
const rows: readonly unknown[] = [];
- function run(columns: readonly Column[]) {
+ async function run(columns: readonly Column[]) {
let unmount;
if (groupBy === undefined) {
({ unmount } = page.render());
@@ -46,31 +46,33 @@ test('column order', () => {
));
}
- expect(getHeaderCells().map((c) => c.textContent)).toStrictEqual(expected);
+ const headerCells = page.getByRole('columnheader');
+ await testCount(headerCells, expected.length);
+ expect(headerCells.elements().map((c) => c.textContent)).toStrictEqual(expected);
unmount();
}
let expected: readonly string[] = ['', 'frz1', 'frz2', 'std1', 'std2'];
let groupBy: readonly string[] | undefined;
- run([SelectColumn, frozen1, frozen2, standard1, standard2]);
- run([standard1, standard2, SelectColumn, frozen1, frozen2]);
- run([standard1, standard2, frozen1, SelectColumn, frozen2]);
- run([standard1, frozen1, standard2, frozen2, SelectColumn]);
+ await run([SelectColumn, frozen1, frozen2, standard1, standard2]);
+ await run([standard1, standard2, SelectColumn, frozen1, frozen2]);
+ await run([standard1, standard2, frozen1, SelectColumn, frozen2]);
+ await run([standard1, frozen1, standard2, frozen2, SelectColumn]);
expected = ['', 'std1', 'frz1', 'frz2', 'std2'];
groupBy = ['s1'];
- run([SelectColumn, frozen1, frozen2, standard1, standard2]);
- run([standard1, standard2, SelectColumn, frozen1, frozen2]);
- run([standard1, standard2, frozen1, SelectColumn, frozen2]);
- run([standard1, frozen1, standard2, frozen2, SelectColumn]);
+ await run([SelectColumn, frozen1, frozen2, standard1, standard2]);
+ await run([standard1, standard2, SelectColumn, frozen1, frozen2]);
+ await run([standard1, standard2, frozen1, SelectColumn, frozen2]);
+ await run([standard1, frozen1, standard2, frozen2, SelectColumn]);
expected = ['', 'std1', 'frz2', 'frz1', 'std2'];
groupBy = ['s1', 'f2'];
- run([SelectColumn, frozen1, frozen2, standard1, standard2]);
- run([standard1, standard2, SelectColumn, frozen1, frozen2]);
- run([standard1, standard2, frozen1, SelectColumn, frozen2]);
- run([standard1, frozen1, standard2, frozen2, SelectColumn]);
+ await run([SelectColumn, frozen1, frozen2, standard1, standard2]);
+ await run([standard1, standard2, SelectColumn, frozen1, frozen2]);
+ await run([standard1, standard2, frozen1, SelectColumn, frozen2]);
+ await run([standard1, frozen1, standard2, frozen2, SelectColumn]);
});
diff --git a/test/browser/events.test.tsx b/test/browser/events.test.tsx
index 72dcf8e48f..39e19598a6 100644
--- a/test/browser/events.test.tsx
+++ b/test/browser/events.test.tsx
@@ -2,7 +2,7 @@ import { page, userEvent } from '@vitest/browser/context';
import { DataGrid } from '../../src';
import type { Column, DataGridProps } from '../../src';
-import { getCellsAtRowIndex } from './utils';
+import { getCell } from './utils';
interface Row {
col1: number;
@@ -63,10 +63,10 @@ describe('Events', () => {
}}
/>
);
- await userEvent.click(getCellsAtRowIndex(0)[0]);
- expect(getCellsAtRowIndex(0)[0]).toHaveAttribute('aria-selected', 'false');
- await userEvent.click(getCellsAtRowIndex(0)[1]);
- expect(getCellsAtRowIndex(0)[1]).toHaveAttribute('aria-selected', 'true');
+ await userEvent.click(getCell('1'));
+ await expect.element(getCell('1')).toHaveAttribute('aria-selected', 'false');
+ await userEvent.click(getCell('a1'));
+ await expect.element(getCell('a1')).toHaveAttribute('aria-selected', 'true');
});
it('should be able to open editor editor on single click using onCellClick', async () => {
@@ -80,9 +80,9 @@ describe('Events', () => {
}}
/>
);
- await userEvent.click(getCellsAtRowIndex(0)[0]);
+ await userEvent.click(getCell('1'));
await expect.element(page.getByLabelText('col1-editor')).not.toBeInTheDocument();
- await userEvent.click(getCellsAtRowIndex(0)[1]);
+ await userEvent.click(getCell('a1'));
await expect.element(page.getByRole('textbox', { name: 'col2-editor' })).toBeInTheDocument();
});
@@ -96,9 +96,9 @@ describe('Events', () => {
}}
/>
);
- await userEvent.dblClick(getCellsAtRowIndex(0)[0]);
+ await userEvent.dblClick(getCell('1'));
await expect.element(page.getByLabelText('col1-editor')).not.toBeInTheDocument();
- await userEvent.dblClick(getCellsAtRowIndex(0)[1]);
+ await userEvent.dblClick(getCell('a1'));
await expect.element(page.getByRole('textbox', { name: 'col2-editor' })).toBeInTheDocument();
});
@@ -106,7 +106,7 @@ describe('Events', () => {
const onCellContextMenu = vi.fn();
page.render();
expect(onCellContextMenu).not.toHaveBeenCalled();
- await userEvent.click(getCellsAtRowIndex(0)[0], { button: 'right' });
+ await userEvent.click(getCell('1'), { button: 'right' });
expect(onCellContextMenu).toHaveBeenCalledExactlyOnceWith(
expect.objectContaining({
column: expect.objectContaining(columns[0]),
@@ -127,7 +127,7 @@ describe('Events', () => {
expect(onSelectedCellChange).not.toHaveBeenCalled();
// Selected by click
- await userEvent.click(getCellsAtRowIndex(0)[1]);
+ await userEvent.click(getCell('a1'));
expect(onSelectedCellChange).toHaveBeenLastCalledWith({
column: expect.objectContaining(columns[1]),
row: rows[0],
@@ -136,7 +136,7 @@ describe('Events', () => {
expect(onSelectedCellChange).toHaveBeenCalledOnce();
// Selected by double click
- await userEvent.dblClick(getCellsAtRowIndex(0)[0]);
+ await userEvent.dblClick(getCell('1'));
expect(onSelectedCellChange).toHaveBeenLastCalledWith({
column: expect.objectContaining(columns[0]),
row: rows[0],
@@ -145,7 +145,7 @@ describe('Events', () => {
expect(onSelectedCellChange).toHaveBeenCalledTimes(2);
// Selected by right-click
- await userEvent.click(getCellsAtRowIndex(1)[0], { button: 'right' });
+ await userEvent.click(getCell('2'), { button: 'right' });
expect(onSelectedCellChange).toHaveBeenLastCalledWith({
column: expect.objectContaining(columns[0]),
row: rows[1],
diff --git a/test/browser/keyboardNavigation.test.tsx b/test/browser/keyboardNavigation.test.tsx
index 40f3fe5000..c7aee2ec7f 100644
--- a/test/browser/keyboardNavigation.test.tsx
+++ b/test/browser/keyboardNavigation.test.tsx
@@ -2,7 +2,7 @@ import { commands, page, userEvent } from '@vitest/browser/context';
import { DataGrid, SelectColumn } from '../../src';
import type { Column } from '../../src';
-import { getSelectedCell, setup, tabIntoGrid, validateCellPosition } from './utils';
+import { getSelectedCell, setup, tabIntoGrid, testCount, validateCellPosition } from './utils';
type Row = undefined;
@@ -258,7 +258,7 @@ test('navigation when selected cell not in the viewport', async () => {
// TODO: replace with `toHaveLength` when migrating to v4
await expect.poll(() => selectedRowCells.elements().length).not.toBe(1);
await commands.scrollGrid({ scrollTop: 0 });
- await expect.poll(() => selectedRowCells.elements().length).toBe(1);
+ await testCount(selectedRowCells, 1);
await userEvent.keyboard('{arrowup}');
await validateCellPosition(99, 99);
await expect.poll(() => selectedRowCells.elements().length).not.toBe(1);
diff --git a/test/browser/renderers.test.tsx b/test/browser/renderers.test.tsx
index 5575487958..fcf7d65b0e 100644
--- a/test/browser/renderers.test.tsx
+++ b/test/browser/renderers.test.tsx
@@ -17,7 +17,7 @@ import type {
RenderSortStatusProps,
SortColumn
} from '../../src';
-import { getCells, getHeaderCells, getRows, setup } from './utils';
+import { getCell, getHeaderCell, getRowByCellName, setup, testCount, testRowCount } from './utils';
interface Row {
id: number;
@@ -116,21 +116,21 @@ function setupContext(props: DataGridProps
test('fallback defined using renderers prop with no rows', async () => {
setup({ columns, rows: noRows, renderers: { noRowsFallback: } });
- expect(getRows()).toHaveLength(0);
+ await testRowCount(1);
await expect.element(page.getByText('Local no rows fallback')).toBeInTheDocument();
});
test('fallback defined using context with no rows', async () => {
setupContext({ columns, rows: noRows });
- expect(getRows()).toHaveLength(0);
+ await testRowCount(1);
await expect.element(page.getByText('Global no rows fallback')).toBeInTheDocument();
});
test('fallback defined using both context and renderers with no rows', async () => {
setupContext({ columns, rows: noRows, renderers: { noRowsFallback: } });
- expect(getRows()).toHaveLength(0);
+ await testRowCount(1);
await expect.element(page.getByText('Local no rows fallback')).toBeInTheDocument();
});
@@ -141,14 +141,14 @@ test('fallback defined using renderers prop with a row', async () => {
renderers: { noRowsFallback: }
});
- expect(getRows()).toHaveLength(1);
+ await testRowCount(2);
await expect.element(page.getByText('Local no rows fallback')).not.toBeInTheDocument();
});
test('fallback defined using context with a row', async () => {
setupContext({ columns, rows: [{ id: 1, col1: 'value 1', col2: 'value 2' }] });
- expect(getRows()).toHaveLength(1);
+ await testRowCount(2);
await expect.element(page.getByText('Global no rows fallback')).not.toBeInTheDocument();
});
@@ -159,7 +159,7 @@ test('fallback defined using both context and renderers with a row', async () =>
renderers: { noRowsFallback: }
});
- expect(getRows()).toHaveLength(1);
+ await testRowCount(2);
await expect.element(page.getByText('Global no rows fallback')).not.toBeInTheDocument();
await expect.element(page.getByText('Local no rows fallback')).not.toBeInTheDocument();
});
@@ -167,21 +167,21 @@ test('fallback defined using both context and renderers with a row', async () =>
test('checkbox defined using renderers prop', async () => {
setup({ columns, rows: noRows, renderers: { renderCheckbox: renderLocalCheckbox } });
- expect(getRows()).toHaveLength(0);
+ await testRowCount(1);
await expect.element(page.getByText('Local checkbox')).toBeInTheDocument();
});
test('checkbox defined using context', async () => {
setupContext({ columns, rows: noRows });
- expect(getRows()).toHaveLength(0);
+ await testRowCount(1);
await expect.element(page.getByText('Global checkbox')).toBeInTheDocument();
});
test('checkbox defined using both context and renderers', async () => {
setupContext({ columns, rows: noRows, renderers: { renderCheckbox: renderLocalCheckbox } });
- expect(getRows()).toHaveLength(0);
+ await testRowCount(1);
await expect.element(page.getByText('Local checkbox')).toBeInTheDocument();
await expect.element(page.getByText('Global checkbox')).not.toBeInTheDocument();
});
@@ -189,14 +189,16 @@ test('checkbox defined using both context and renderers', async () => {
test('sortPriority defined using both contexts', async () => {
setupContext({ columns, rows: noRows });
- const [, headerCell2, headerCell3] = getHeaderCells();
- await userEvent.click(headerCell2);
+ const column1 = getHeaderCell('Column1');
+ const column2 = getHeaderCell('Column2');
+ await userEvent.click(column1);
await userEvent.keyboard('{Control>}');
- await userEvent.click(headerCell3);
+ await userEvent.click(column2);
- const p = page.getByTestId('global-sort-priority').elements();
- expect(p[0]).toHaveTextContent('1');
- expect(p[1]).toHaveTextContent('2');
+ const p = page.getByTestId('global-sort-priority');
+ await testCount(p, 2);
+ await expect.element(p.nth(0)).toHaveTextContent('1');
+ await expect.element(p.nth(1)).toHaveTextContent('2');
await expect.element(page.getByTestId('local-sort-priority')).not.toBeInTheDocument();
});
@@ -204,68 +206,68 @@ test('sortPriority defined using both contexts', async () => {
test('sortPriority defined using both contexts and renderers', async () => {
setupContext({ columns, rows: noRows, renderers: { renderSortStatus: renderLocalSortStatus } });
- const [, headerCell2, headerCell3] = getHeaderCells();
- await userEvent.click(headerCell3);
+ const column1 = getHeaderCell('Column1');
+ const column2 = getHeaderCell('Column2');
+ await userEvent.click(column2);
await userEvent.keyboard('{Control>}');
- await userEvent.click(headerCell2);
+ await userEvent.click(column1);
- const p = page.getByTestId('local-sort-priority').all();
- await expect.element(p[0]).toHaveTextContent('2');
- await expect.element(p[1]).toHaveTextContent('1');
+ const p = page.getByTestId('local-sort-priority');
+ await testCount(p, 2);
+ await expect.element(p.nth(0)).toHaveTextContent('2');
+ await expect.element(p.nth(1)).toHaveTextContent('1');
await expect.element(page.getByTestId('global-sort-priority')).not.toBeInTheDocument();
});
-test('renderCell defined using context', () => {
+test('renderCell defined using context', async () => {
setupContext({ columns, rows: [{ id: 1, col1: 'value 1', col2: 'value 2' }] });
- const [, cell1, cell2] = getCells();
- expect(cell1).toHaveTextContent('value 1');
- expect(cell1).toHaveClass('global');
- expect(cell1).not.toHaveClass('local');
- expect(cell1).toHaveStyle({ fontStyle: 'italic' });
+ const cell1 = getCell('value 1');
+ const cell2 = getCell('value 2');
+ await expect.element(cell1).toHaveClass('global');
+ await expect.element(cell1).not.toHaveClass('local');
+ await expect.element(cell1).toHaveStyle({ fontStyle: 'italic' });
- expect(cell2).toHaveTextContent('value 2');
- expect(cell2).toHaveClass('global');
- expect(cell2).not.toHaveClass('local');
- expect(cell2).toHaveStyle({ fontStyle: 'italic' });
+ await expect.element(cell2).toHaveClass('global');
+ await expect.element(cell2).not.toHaveClass('local');
+ await expect.element(cell2).toHaveStyle({ fontStyle: 'italic' });
});
-test('renderCell defined using both contexts and renderers', () => {
+test('renderCell defined using both contexts and renderers', async () => {
setupContext({
columns,
rows: [{ id: 1, col1: 'value 1', col2: 'value 2' }],
renderers: { renderCell: renderLocalCell }
});
- const [, cell1, cell2] = getCells();
- expect(cell1).toHaveTextContent('value 1');
- expect(cell1).toHaveClass('local');
- expect(cell1).not.toHaveClass('global');
- expect(cell1).toHaveStyle({ fontStyle: 'normal' });
+ const cell1 = getCell('value 1');
+ const cell2 = getCell('value 2');
+ await expect.element(cell1).toHaveClass('local');
+ await expect.element(cell1).not.toHaveClass('global');
+ await expect.element(cell1).toHaveStyle({ fontStyle: 'normal' });
- expect(cell2).toHaveTextContent('value 2');
- expect(cell2).toHaveClass('local');
- expect(cell2).not.toHaveClass('global');
- expect(cell2).toHaveStyle({ fontStyle: 'normal' });
+ await expect.element(cell2).toHaveClass('local');
+ await expect.element(cell2).not.toHaveClass('global');
+ await expect.element(cell2).toHaveStyle({ fontStyle: 'normal' });
});
-test('renderRow defined using context', () => {
+test('renderRow defined using context', async () => {
setupContext({ columns, rows: [{ id: 1, col1: 'value 1', col2: 'value 2' }] });
- const row = getRows()[0];
- expect(row).toHaveClass('global');
- expect(row).not.toHaveClass('local');
+ const row = getRowByCellName('value 1');
+ await expect.element(row).toHaveClass('global');
+ await expect.element(row).not.toHaveClass('local');
});
-test('renderRow defined using both contexts and renderers', () => {
+test('renderRow defined using both contexts and renderers', async () => {
setupContext({
columns,
rows: [{ id: 1, col1: 'value 1', col2: 'value 2' }],
renderers: { renderRow: renderLocalRow }
});
- const row = getRows()[0];
- expect(row).toHaveClass('local');
- expect(row).not.toHaveClass('global');
+ const row = getRowByCellName('value 1');
+ await expect.element(row).toHaveClass('local');
+ await expect.element(row).not.toHaveClass('global');
});
diff --git a/test/browser/rowClass.test.ts b/test/browser/rowClass.test.ts
index ad4a41d704..2a0206929b 100644
--- a/test/browser/rowClass.test.ts
+++ b/test/browser/rowClass.test.ts
@@ -1,6 +1,6 @@
import type { Column } from '../../src';
import { rowClassname } from '../../src/style/row';
-import { getRowsNew, setup } from './utils';
+import { getRowByCellName, setup } from './utils';
interface Row {
id: number;
@@ -15,10 +15,15 @@ test('rowClass is undefined', async () => {
rows,
rowClass: undefined
});
- const [row1, row2, row3] = getRowsNew('0', '1', '2');
- await expect.element(row1).toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
- await expect.element(row2).toHaveClass(`${rowClassname} rdg-row-odd`, { exact: true });
- await expect.element(row3).toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
+ await expect
+ .element(getRowByCellName('0'))
+ .toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
+ await expect
+ .element(getRowByCellName('1'))
+ .toHaveClass(`${rowClassname} rdg-row-odd`, { exact: true });
+ await expect
+ .element(getRowByCellName('2'))
+ .toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
});
test('rowClass returns a string', async () => {
@@ -27,10 +32,15 @@ test('rowClass returns a string', async () => {
rows,
rowClass: (row) => `my-row-${row.id}`
});
- const [row1, row2, row3] = getRowsNew('0', '1', '2');
- await expect.element(row1).toHaveClass(`${rowClassname} rdg-row-even my-row-0`, { exact: true });
- await expect.element(row2).toHaveClass(`${rowClassname} rdg-row-odd my-row-1`, { exact: true });
- await expect.element(row3).toHaveClass(`${rowClassname} rdg-row-even my-row-2`, { exact: true });
+ await expect
+ .element(getRowByCellName('0'))
+ .toHaveClass(`${rowClassname} rdg-row-even my-row-0`, { exact: true });
+ await expect
+ .element(getRowByCellName('1'))
+ .toHaveClass(`${rowClassname} rdg-row-odd my-row-1`, { exact: true });
+ await expect
+ .element(getRowByCellName('2'))
+ .toHaveClass(`${rowClassname} rdg-row-even my-row-2`, { exact: true });
});
test('rowClass returns undefined', async () => {
@@ -39,8 +49,13 @@ test('rowClass returns undefined', async () => {
rows,
rowClass: () => undefined
});
- const [row1, row2, row3] = getRowsNew('0', '1', '2');
- await expect.element(row1).toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
- await expect.element(row2).toHaveClass(`${rowClassname} rdg-row-odd`, { exact: true });
- await expect.element(row3).toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
+ await expect
+ .element(getRowByCellName('0'))
+ .toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
+ await expect
+ .element(getRowByCellName('1'))
+ .toHaveClass(`${rowClassname} rdg-row-odd`, { exact: true });
+ await expect
+ .element(getRowByCellName('2'))
+ .toHaveClass(`${rowClassname} rdg-row-even`, { exact: true });
});
diff --git a/test/browser/rowHeight.test.ts b/test/browser/rowHeight.test.ts
index 7e242d174b..3c3cf52438 100644
--- a/test/browser/rowHeight.test.ts
+++ b/test/browser/rowHeight.test.ts
@@ -1,7 +1,7 @@
-import { page, userEvent } from '@vitest/browser/context';
+import { userEvent } from '@vitest/browser/context';
import type { Column, DataGridProps } from '../../src';
-import { getRows, setup, tabIntoGrid } from './utils';
+import { getGrid, setup, tabIntoGrid, testRowCount } from './utils';
type Row = number;
@@ -23,7 +23,7 @@ function setupGrid(rowHeight: DataGridProps['rowHeight']) {
function expectGridRows(rowHeightFn: (row: number) => number, expected: string) {
setupGrid(rowHeightFn);
- const grid = page.getByRole('grid').element() as HTMLDivElement;
+ const grid = getGrid().element() as HTMLDivElement;
const gridTemplateRows = grid.style.gridTemplateRows;
expect(gridTemplateRows).toBe(expected);
@@ -32,33 +32,34 @@ function expectGridRows(rowHeightFn: (row: number) => number, expected: string)
test('rowHeight is number', async () => {
setupGrid(40);
- const grid = page.getByRole('grid').element();
- expect(grid).toHaveStyle({
+ const grid = getGrid();
+ await expect.element(grid).toHaveStyle({
gridTemplateRows:
'40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px'
});
- expect(getRows()).toHaveLength(30);
-
+ await testRowCount(31);
await tabIntoGrid();
- expect(grid.scrollTop).toBe(0);
+ const gridEl = grid.element();
+ expect(gridEl.scrollTop).toBe(0);
await userEvent.keyboard('{Control>}{end}');
- expect(grid.scrollTop + grid.clientHeight).toBe(grid.scrollHeight);
+ expect(gridEl.scrollTop + gridEl.clientHeight).toBe(gridEl.scrollHeight);
});
test('rowHeight is function', async () => {
setupGrid((row) => [40, 60, 80][row % 3]);
- const grid = page.getByRole('grid').element();
- expect(grid).toHaveStyle({
+ const grid = getGrid();
+ await expect.element(grid).toHaveStyle({
gridTemplateRows:
'35px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px'
});
- expect(getRows()).toHaveLength(22);
+ await testRowCount(23);
await tabIntoGrid();
- expect(grid.scrollTop).toBe(0);
+ const gridEl = grid.element();
+ expect(gridEl.scrollTop).toBe(0);
await userEvent.keyboard('{Control>}{end}');
- expect(grid.scrollTop + grid.clientHeight).toBe(grid.scrollHeight);
+ expect(gridEl.scrollTop + gridEl.clientHeight).toBe(gridEl.scrollHeight);
});
test('rowHeight with repeat pattern - multiple identical heights', () => {
diff --git a/test/browser/rowSelection.test.tsx b/test/browser/rowSelection.test.tsx
index ed9462dfea..b7b6990d2d 100644
--- a/test/browser/rowSelection.test.tsx
+++ b/test/browser/rowSelection.test.tsx
@@ -3,7 +3,7 @@ import { page, userEvent } from '@vitest/browser/context';
import { DataGrid, SelectColumn } from '../../src';
import type { Column } from '../../src';
-import { getCell, getSelectAllCheckbox } from './utils';
+import { getCell, getRowByCell, getSelectAllCheckbox } from './utils';
interface Row {
id: number;
@@ -49,7 +49,7 @@ function setup(initialRows = defaultRows) {
}
function getRowByText(rowIdx: number) {
- return page.getByRole('row').filter({ has: getCell(String(rowIdx + 1)) });
+ return getRowByCell(getCell(String(rowIdx + 1)));
}
function testSelection(rowIdx: number, isSelected: boolean) {
diff --git a/test/browser/utils.tsx b/test/browser/utils.tsx
index 512d1a940d..2ba02b6314 100644
--- a/test/browser/utils.tsx
+++ b/test/browser/utils.tsx
@@ -1,4 +1,4 @@
-import { page, userEvent } from '@vitest/browser/context';
+import { page, userEvent, type Locator } from '@vitest/browser/context';
import { css } from '@linaria/core';
import { DataGrid } from '../../src';
@@ -48,12 +48,12 @@ export function getHeaderCellsNew(...names: readonly string[]) {
return names.map((name) => getHeaderCell(name));
}
-export function getRow(name: string) {
- return page.getByRole('row', { name, exact: true });
+export function getRowByCell(cell: Locator) {
+ return page.getByRole('row').filter({ has: cell });
}
-export function getRowsNew(...names: readonly string[]) {
- return names.map(getRow);
+export function getRowByCellName(cell: string) {
+ return getRowByCell(getCell(cell));
}
export function getCell(name: string) {
@@ -72,6 +72,10 @@ export function getRows() {
return page.getByRole('row').elements().slice(1);
}
+export function getRowsNew() {
+ return page.getByRole('row');
+}
+
export function getCellsAtRowIndex(rowIdx: number) {
return Array.from(
document.querySelectorAll(`[aria-rowindex="${rowIdx + 2}"] > .rdg-cell`)
@@ -127,3 +131,11 @@ export async function tabIntoGrid() {
await userEvent.click(page.getByRole('button', { name: 'Before' }));
await userEvent.tab();
}
+
+export function testCount(locator: Locator, expectedCount: number) {
+ return expect.poll(() => locator.elements()).toHaveLength(expectedCount);
+}
+
+export function testRowCount(expectedLength: number) {
+ return testCount(getRowsNew(), expectedLength);
+}
diff --git a/test/globals.d.ts b/test/globals.d.ts
index 6ccaf2509e..acec8e74f0 100644
--- a/test/globals.d.ts
+++ b/test/globals.d.ts
@@ -1,9 +1,13 @@
declare module '@vitest/browser/context' {
interface BrowserCommands {
dragFill: (from: string, to: string) => Promise;
- resizeColumn: (resizeBy: number | readonly number[]) => Promise;
+ resizeColumn: (name: string, resizeBy: number | readonly number[]) => Promise;
scrollGrid: (position: { scrollLeft?: number; scrollTop?: number }) => Promise;
}
+
+ interface LocatorSelectors {
+ getBySelector: (selector: string) => Locator;
+ }
}
// somehow required to make `declare global` work
diff --git a/test/setupBrowser.ts b/test/setupBrowser.ts
index 3d18d2797c..ca6d1777fa 100644
--- a/test/setupBrowser.ts
+++ b/test/setupBrowser.ts
@@ -1,9 +1,16 @@
-import { configure as vitestReactConfigure } from 'vitest-browser-react/pure';
+import { locators } from '@vitest/browser/context';
+import { configure } from 'vitest-browser-react/pure';
// vitest-browser-react also automatically injects render method on the page
// need to import it so TypeScript can pick up types
import 'vitest-browser-react';
-vitestReactConfigure({
+configure({
reactStrictMode: true
});
+
+locators.extend({
+ getBySelector(selector: string) {
+ return selector;
+ }
+});
diff --git a/vite.config.ts b/vite.config.ts
index 350038aeab..920ad89a0c 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -8,13 +8,16 @@ const isCI = process.env.CI === 'true';
const isTest = process.env.NODE_ENV === 'test';
// TODO: remove when `userEvent.pointer` is supported
-const resizeColumn: BrowserCommand<[resizeBy: number | readonly number[]]> = async (
+const resizeColumn: BrowserCommand<[name: string, resizeBy: number | readonly number[]]> = async (
context,
+ name,
resizeBy
) => {
const page = context.page;
const frame = await context.frame();
- const resizeHandle = frame.locator('[role="columnheader"][aria-colindex="2"] div');
+ const resizeHandle = frame
+ .getByRole('columnheader', { name, exact: true })
+ .locator('.rdg-resize-handle');
const { x, y } = (await resizeHandle.boundingBox())!;
await resizeHandle.hover({
position: { x: 5, y: 5 }