diff --git a/test/browser/column/renderEditCell.test.tsx b/test/browser/column/renderEditCell.test.tsx index deaab7b840..152c291246 100644 --- a/test/browser/column/renderEditCell.test.tsx +++ b/test/browser/column/renderEditCell.test.tsx @@ -1,6 +1,6 @@ import { useMemo, useState } from 'react'; import { createPortal } from 'react-dom'; -import { page, userEvent } from '@vitest/browser/context'; +import { commands, page, userEvent } from '@vitest/browser/context'; import { DataGrid } from '../../../src'; import type { Column, DataGridProps } from '../../../src'; @@ -266,11 +266,11 @@ describe('Editor', () => { await userEvent.dblClick(getCellsAtRowIndex(0)[1]); await userEvent.keyboard('abc'); - await scrollGrid({ scrollTop: 1500 }); - expect(getCellsAtRowIndex(40)[1]).toHaveTextContent(/^40$/); - await userEvent.click(getCellsAtRowIndex(40)[1]); - await expect.element(getSelectedCell()).toHaveTextContent(/^40$/); - await scrollGrid({ scrollTop: 0 }); + await commands.scrollGrid({ scrollTop: 1500 }); + expect(getCellsAtRowIndex(43)[1]).toHaveTextContent(/^43$/); + await userEvent.click(getCellsAtRowIndex(43)[1]); + await expect.element(getSelectedCell()).toHaveTextContent(/^43$/); + await commands.scrollGrid({ scrollTop: 0 }); expect(getCellsAtRowIndex(0)[1]).toHaveTextContent(/^0abc$/); }); diff --git a/test/browser/rowSelection.test.tsx b/test/browser/rowSelection.test.tsx index a37c375a91..dd0f8afa6d 100644 --- a/test/browser/rowSelection.test.tsx +++ b/test/browser/rowSelection.test.tsx @@ -52,10 +52,10 @@ function testSelection(rowIdx: number, isSelected: boolean) { expect(getRows()[rowIdx]).toHaveAttribute('aria-selected', isSelected ? 'true' : 'false'); } -async function toggleSelection(rowIdx: number, shift = false) { +async function toggleSelection(rowIdx: number, shift = false, force = false) { const element = page.getByRole('row').all()[rowIdx + 1].getByRole('checkbox', { name: 'Select' }); if (shift) await userEvent.keyboard('{Shift>}'); - await userEvent.click(element, { force: true }); + await userEvent.click(element, { force }); if (shift) await userEvent.keyboard('{/Shift}'); } @@ -126,7 +126,7 @@ test('should not select row when isRowSelectionDisabled returns true', async () ); await toggleSelection(0); testSelection(0, true); - await toggleSelection(1); + await toggleSelection(1, false, true); // force click even if disabled testSelection(1, false); await toggleSelection(2); testSelection(2, true); diff --git a/test/browser/scrollToCell.test.tsx b/test/browser/scrollToCell.test.tsx index ba843a39c3..3a58c416c5 100644 --- a/test/browser/scrollToCell.test.tsx +++ b/test/browser/scrollToCell.test.tsx @@ -4,21 +4,23 @@ import { page, userEvent } from '@vitest/browser/context'; import { DataGrid } from '../../src'; import type { Column, DataGridHandle } from '../../src'; import type { PartialPosition } from '../../src/ScrollToCell'; -import { getGrid } from './utils'; -type Row = undefined; - -const rows: readonly Row[] = new Array(50); -const summaryRows: readonly Row[] = [undefined, undefined]; - -const columns: Column[] = []; +const rows: readonly number[] = Array.from({ length: 50 }, (_, i) => i); +const summaryRows: readonly number[] = Array.from({ length: 2 }, (_, i) => i + 50); +const columns: Column[] = []; for (let i = 0; i < 50; i++) { const key = String(i); columns.push({ key, name: key, - frozen: i < 5 + frozen: i < 5, + renderCell(props) { + return `${props.column.key}×${props.row}`; + }, + renderSummaryCell(props) { + return `${props.column.key}×${props.row}`; + } }); } @@ -54,43 +56,57 @@ async function testScroll(p: PartialPosition) { test('scrollToCell', async () => { page.render(); - const grid = getGrid().element(); - validateScrollPosition(0, 0); + await validateCellVisibility('0×0', true); + await validateCellVisibility('40×30', false); + await validateCellVisibility('0×51', true); // should scroll to a cell when a valid position is specified await testScroll({ idx: 40, rowIdx: 30 }); - validateScrollPosition(1572, 132); + await validateCellVisibility('0×0', false); + await validateCellVisibility('40×30', true); // should scroll to a column when a valid idx is specified await testScroll({ idx: 6 }); - validateScrollPosition(1572, 50); + await validateCellVisibility('6×30', true); + await validateCellVisibility('40×30', false); await testScroll({ idx: 40 }); - validateScrollPosition(1572, 132); + await validateCellVisibility('6×30', false); + await validateCellVisibility('40×30', true); // should scroll to a row when a valid rowIdx is specified await testScroll({ rowIdx: 1 }); - validateScrollPosition(0, 132); + await validateCellVisibility('40×1', true); + await validateCellVisibility('40×30', false); await testScroll({ rowIdx: 30 }); - validateScrollPosition(1572, 132); + await validateCellVisibility('40×1', false); + await validateCellVisibility('40×30', true); // should not scroll if scroll to column is frozen await testScroll({ idx: 2 }); - validateScrollPosition(1572, 132); + await validateCellVisibility('40×30', true); // should not scroll if rowIdx is header row await testScroll({ idx: -1 }); - validateScrollPosition(1572, 132); + await validateCellVisibility('40×30', true); // should not scroll if rowIdx is summary row await testScroll({ idx: 50 }); - validateScrollPosition(1572, 132); + await validateCellVisibility('40×30', true); // should not scroll if position is out of bound await testScroll({ idx: 60, rowIdx: 60 }); - validateScrollPosition(1572, 132); + await validateCellVisibility('40×30', true); - function validateScrollPosition(scrollTop: number, scrollLeft: number) { - expect(grid.scrollTop).toBe(scrollTop); - expect(grid.scrollLeft).toBe(scrollLeft); - } + // should not scroll vertically when scrolling to summary row + await testScroll({ idx: 49, rowIdx: 51 }); + await validateCellVisibility('49×30', true); }); + +function validateCellVisibility(name: string, isVisible: boolean) { + const cell = page.getByRole('gridcell', { name, exact: true }); + if (isVisible) { + return expect.element(cell).toBeVisible(); + } + + return expect.element(cell).not.toBeInTheDocument(); +} diff --git a/test/globals.d.ts b/test/globals.d.ts index fad484533a..6ccaf2509e 100644 --- a/test/globals.d.ts +++ b/test/globals.d.ts @@ -1,7 +1,8 @@ declare module '@vitest/browser/context' { interface BrowserCommands { - resizeColumn: (resizeBy: number | readonly number[]) => Promise; dragFill: (from: string, to: string) => Promise; + resizeColumn: (resizeBy: number | readonly number[]) => Promise; + scrollGrid: (position: { scrollLeft?: number; scrollTop?: number }) => Promise; } } diff --git a/tsconfig.vite.json b/tsconfig.vite.json index 55ce01b576..57d8db9414 100644 --- a/tsconfig.vite.json +++ b/tsconfig.vite.json @@ -2,6 +2,7 @@ "extends": "./tsconfig.base.json", "compilerOptions": { "skipLibCheck": true, + "lib": ["ESNext", "DOM"], "types": ["@vitest/browser/providers/playwright"] }, "include": ["package.json", "rolldown.config.ts", "vite.config.ts"] diff --git a/vite.config.ts b/vite.config.ts index c2aefbaec4..dabe74be47 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -41,6 +41,24 @@ const dragFill: BrowserCommand<[from: string, to: string]> = async (context, fro await page.mouse.up(); }; +const scrollGrid: BrowserCommand<[{ scrollLeft?: number; scrollTop?: number }]> = async ( + context, + { scrollLeft, scrollTop } +) => { + const frame = await context.frame(); + await frame.getByRole('grid').evaluate( + (grid: HTMLDivElement, { scrollLeft, scrollTop }) => { + if (scrollLeft !== undefined) { + grid.scrollLeft = scrollLeft; + } + if (scrollTop !== undefined) { + grid.scrollTop = scrollTop; + } + }, + { scrollLeft, scrollTop } + ); +}; + const viewport = { width: 1920, height: 1080 } as const; export default defineConfig(({ command, isPreview }) => ({ @@ -108,7 +126,7 @@ export default defineConfig(({ command, isPreview }) => ({ context: { viewport } } ], - commands: { resizeColumn, dragFill }, + commands: { resizeColumn, dragFill, scrollGrid }, viewport, headless: true, screenshotFailures: !isCI