diff --git a/test/browser/column/renderEditCell.test.tsx b/test/browser/column/renderEditCell.test.tsx index d4aec74b95..6cdc712ccc 100644 --- a/test/browser/column/renderEditCell.test.tsx +++ b/test/browser/column/renderEditCell.test.tsx @@ -7,6 +7,8 @@ import type { Column, DataGridProps } from '../../../src'; import { getCellsAtRowIndex, getRowWithCell, safeTab, scrollGrid, testCount } from '../utils'; const grid = page.getGrid(); +const col1Editor = page.getByRole('spinbutton', { name: 'col1-editor' }); +const col2Editor = page.getByRole('textbox', { name: 'col2-editor' }); interface Row { col1: number; @@ -16,28 +18,26 @@ interface Row { describe('Editor', () => { it('should open editor on double click', async () => { await page.render(); - const editor = page.getByRole('spinbutton', { name: 'col1-editor' }); await userEvent.click(getCellsAtRowIndex(0).nth(0)); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col1Editor).not.toBeInTheDocument(); await userEvent.dblClick(getCellsAtRowIndex(0).nth(0)); - await expect.element(editor).toHaveValue(1); + await expect.element(col1Editor).toHaveValue(1); await userEvent.keyboard('2'); await safeTab(); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col1Editor).not.toBeInTheDocument(); await expect.element(getCellsAtRowIndex(0).nth(0)).toHaveTextContent(/^12$/); }); it('should open and commit changes on enter', async () => { await page.render(); - const editor = page.getByRole('spinbutton', { name: 'col1-editor' }); await userEvent.click(getCellsAtRowIndex(0).nth(0)); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col1Editor).not.toBeInTheDocument(); await userEvent.keyboard('{enter}'); - await expect.element(editor).toHaveValue(1); + await expect.element(col1Editor).toHaveValue(1); await userEvent.keyboard('3{enter}'); await expect.element(getCellsAtRowIndex(0).nth(0)).toHaveTextContent(/^13$/); await expect.element(getCellsAtRowIndex(0).nth(0)).toHaveFocus(); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col1Editor).not.toBeInTheDocument(); }); it('should open editor when user types', async () => { @@ -51,10 +51,9 @@ describe('Editor', () => { it('should close editor and discard changes on escape', async () => { await page.render(); await userEvent.dblClick(getCellsAtRowIndex(0).nth(0)); - const editor = page.getByRole('spinbutton', { name: 'col1-editor' }); - await expect.element(editor).toHaveValue(1); + await expect.element(col1Editor).toHaveValue(1); await userEvent.keyboard('2222{escape}'); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col1Editor).not.toBeInTheDocument(); await expect.element(getCellsAtRowIndex(0).nth(0)).toHaveTextContent(/^1$/); await expect.element(getCellsAtRowIndex(0).nth(0)).toHaveFocus(); }); @@ -62,11 +61,10 @@ describe('Editor', () => { it('should commit changes and close editor when clicked outside', async () => { await page.render(); await userEvent.dblClick(getCellsAtRowIndex(0).nth(0)); - const editor = page.getByRole('spinbutton', { name: 'col1-editor' }); - await expect.element(editor).toHaveValue(1); + await expect.element(col1Editor).toHaveValue(1); await userEvent.keyboard('2222'); await userEvent.click(page.getByText('outside')); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col1Editor).not.toBeInTheDocument(); await expect.element(getCellsAtRowIndex(0).nth(0)).toHaveTextContent(/^12222$/); }); @@ -100,13 +98,12 @@ describe('Editor', () => { await testCount(activeRowCells, 2); await scrollGrid({ top: 2001 }); await testCount(activeRowCells, 1); - const editor = grid.getByRole('spinbutton', { name: 'col1-editor' }); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col1Editor).not.toBeInTheDocument(); await expect.element(grid).toHaveProperty('scrollTop', 2001); // TODO: await userEvent.keyboard('123'); fails in FF await userEvent.keyboard('{enter}123'); await testCount(activeRowCells, 2); - await expect.element(editor).toHaveValue(123); + await expect.element(col1Editor).toHaveValue(123); await expect.element(grid).toHaveProperty('scrollTop', 0); }); @@ -116,13 +113,13 @@ describe('Editor', () => { const cell = getCellsAtRowIndex(0).nth(1); await expect.element(cell).not.toHaveAttribute('aria-readonly'); await userEvent.dblClick(cell); - await expect.element(page.getByRole('textbox', { name: 'col2-editor' })).toBeInTheDocument(); + await expect.element(col2Editor).toBeInTheDocument(); }); it('should be editable if an editor is specified and editable is set to true', async () => { await page.render(); await userEvent.dblClick(getCellsAtRowIndex(0).nth(1)); - await expect.element(page.getByRole('textbox', { name: 'col2-editor' })).toBeInTheDocument(); + await expect.element(col2Editor).toBeInTheDocument(); }); it('should not be editable if editable is false', async () => { @@ -131,19 +128,16 @@ describe('Editor', () => { await expect.element(cell).toHaveAttribute('aria-readonly', 'true'); await userEvent.dblClick(cell); - await expect - .element(page.getByRole('textbox', { name: 'col2-editor' })) - .not.toBeInTheDocument(); + await expect.element(col2Editor).not.toBeInTheDocument(); }); it('should not be editable if editable function returns false', async () => { await page.render( row.col1 === 2} />); await userEvent.dblClick(getCellsAtRowIndex(0).nth(1)); - const editor = page.getByRole('textbox', { name: 'col2-editor' }); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col2Editor).not.toBeInTheDocument(); await userEvent.dblClick(getCellsAtRowIndex(1).nth(1)); - await expect.element(editor).toBeInTheDocument(); + await expect.element(col2Editor).toBeInTheDocument(); }); }); @@ -153,21 +147,20 @@ describe('Editor', () => { ); await userEvent.dblClick(getCellsAtRowIndex(0).nth(1)); - const editor1 = page.getByRole('textbox', { name: 'col2-editor' }); - await expect.element(editor1).toHaveValue('a1'); + await expect.element(col2Editor).toHaveValue('a1'); await userEvent.keyboard('23'); // The cell value should update as the editor value is changed await expect.element(getCellsAtRowIndex(0).nth(1)).toHaveTextContent(/^a123$/); // clicking in a portal does not count as an outside click - await userEvent.click(editor1); - await expect.element(editor1).toBeInTheDocument(); + await userEvent.click(col2Editor); + await expect.element(col2Editor).toBeInTheDocument(); // true outside clicks are still detected await userEvent.click(page.getByText('outside')); - await expect.element(editor1).not.toBeInTheDocument(); + await expect.element(col2Editor).not.toBeInTheDocument(); await expect.element(getCellsAtRowIndex(0).nth(1)).not.toHaveFocus(); await userEvent.dblClick(getCellsAtRowIndex(0).nth(1)); - await userEvent.click(page.getByRole('textbox', { name: 'col2-editor' })); + await userEvent.click(col2Editor); await userEvent.keyboard('{enter}'); await expect.element(getCellsAtRowIndex(0).nth(1)).toHaveFocus(); }); @@ -181,13 +174,12 @@ describe('Editor', () => { /> ); await userEvent.dblClick(getCellsAtRowIndex(0).nth(1)); - const editor = page.getByRole('textbox', { name: 'col2-editor' }); - await expect.element(editor).toBeInTheDocument(); + await expect.element(col2Editor).toBeInTheDocument(); await userEvent.click(page.getByText('outside')); - await expect.element(editor).toBeInTheDocument(); - await userEvent.click(editor); + await expect.element(col2Editor).toBeInTheDocument(); + await userEvent.click(col2Editor); await userEvent.keyboard('{enter}'); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col2Editor).not.toBeInTheDocument(); }); it('should not open editor if onCellKeyDown prevents the default event', async () => { @@ -205,9 +197,7 @@ describe('Editor', () => { await userEvent.keyboard('{enter}yz{enter}'); await expect.element(getCellsAtRowIndex(0).nth(1)).toHaveTextContent(/^a1yz$/); await userEvent.keyboard('x'); - await expect - .element(page.getByRole('textbox', { name: 'col2-editor' })) - .not.toBeInTheDocument(); + await expect.element(col2Editor).not.toBeInTheDocument(); }); it('should prevent navigation if onCellKeyDown prevents the default event', async () => { @@ -236,10 +226,9 @@ describe('Editor', () => { /> ); await userEvent.dblClick(getCellsAtRowIndex(0).nth(1)); - const editor = page.getByRole('textbox', { name: 'col2-editor' }); - await expect.element(editor).toBeInTheDocument(); + await expect.element(col2Editor).toBeInTheDocument(); await userEvent.click(page.getByRole('button', { name: 'update' })); - await expect.element(editor).not.toBeInTheDocument(); + await expect.element(col2Editor).not.toBeInTheDocument(); }); it('should not close the editor when closeOnExternalRowChange is false and row is changed from outside', async () => { @@ -252,10 +241,9 @@ describe('Editor', () => { /> ); await userEvent.dblClick(getCellsAtRowIndex(0).nth(1)); - const editor = page.getByRole('textbox', { name: 'col2-editor' }); - await expect.element(editor).toBeInTheDocument(); + await expect.element(col2Editor).toBeInTheDocument(); await userEvent.click(page.getByRole('button', { name: 'update' })); - await expect.element(editor).toBeInTheDocument(); + await expect.element(col2Editor).toBeInTheDocument(); }); }); diff --git a/test/browser/utils.tsx b/test/browser/utils.tsx index 0b4558ef72..381a80d023 100644 --- a/test/browser/utils.tsx +++ b/test/browser/utils.tsx @@ -27,9 +27,12 @@ export async function validateCellPosition(columnIdx: number, rowIdx: number) { export async function scrollGrid(options: ScrollToOptions) { await new Promise((resolve) => { - const gridElement = page.getGrid().element() as HTMLElement; - gridElement.addEventListener('scrollend', resolve, { once: true }); - gridElement.scroll(options); + // wait for browser state to stablize before scrolling, to avoid flaky scroll-related tests + requestAnimationFrame(() => { + const gridElement = page.getGrid().element(); + gridElement.addEventListener('scrollend', resolve, { once: true }); + gridElement.scroll(options); + }); }); } diff --git a/vite.config.ts b/vite.config.ts index 5c4afce666..3053cfaf87 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -44,7 +44,7 @@ const viewport = { width: 1920, height: 1080 } as const; // vitest modifies the instance objects, so we cannot rely on static objects function getInstances(): BrowserInstanceOption[] { const opts: PlaywrightProviderOptions = { - actionTimeout: 1000, + actionTimeout: 2000, contextOptions: { viewport } @@ -123,9 +123,6 @@ export default defineConfig( include: ['browser/**/*.test.*'], browser: { enabled: true, - trace: { - mode: isCI ? 'off' : 'retain-on-failure' - }, instances: getInstances(), commands: { resizeColumn, dragFill }, viewport,