From 0c7316d283d940298f66e0e7684190d61355343d Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 21 Jan 2025 16:18:37 +0100 Subject: [PATCH 01/34] override react transition group + remove `waitFor` calls --- .../src/tests/license.DataGridPro.test.tsx | 6 +- .../src/tests/rows.DataGrid.test.tsx | 103 +++++++----------- test/utils/mochaHooks.js | 18 +++ 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx index e65d7ff55bf09..e19bad19e2791 100644 --- a/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import { createRenderer, screen, waitFor } from '@mui/internal-test-utils'; +import { createRenderer, screen } from '@mui/internal-test-utils'; import { DataGridPro } from '@mui/x-data-grid-pro'; import { LicenseInfo } from '@mui/x-license'; @@ -14,8 +14,6 @@ describe(' - License', () => { 'MUI X: Missing license key.', ]); - await waitFor(() => { - expect(screen.getByText('MUI X Missing license key')).not.to.equal(null); - }); + expect(screen.getByText('MUI X Missing license key')).not.to.equal(null); }); }); diff --git a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx index 5c447f2ed24cd..055da4353389c 100644 --- a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx @@ -280,9 +280,7 @@ describe(' - Rows', () => { render( []} />); expect(screen.queryByText('print')).to.equal(null); fireEvent.click(screen.getByRole('menuitem', { name: 'more' })); - await waitFor(() => { - expect(screen.queryByText('print')).not.to.equal(null); - }); + expect(screen.queryByText('print')).not.to.equal(null); }); it('should not select the row when clicking in an action', async () => { @@ -291,8 +289,7 @@ describe(' - Rows', () => { ); expect(getRow(0)).not.to.have.class('Mui-selected'); fireEvent.click(screen.getByRole('menuitem', { name: 'print' })); - - await waitFor(() => expect(getRow(0)).not.to.have.class('Mui-selected')); + expect(getRow(0)).not.to.have.class('Mui-selected'); }); it('should not select the row when clicking in a menu action', async () => { @@ -303,14 +300,11 @@ describe(' - Rows', () => { ); expect(getRow(0)).not.to.have.class('Mui-selected'); fireEvent.click(screen.getByRole('menuitem', { name: 'more' })); - await waitFor(() => { - expect(screen.queryByText('print')).not.to.equal(null); - }); + expect(screen.queryByText('print')).not.to.equal(null); fireEvent.click(screen.getByText('print')); - await waitFor(() => { - expect(getRow(0)).not.to.have.class('Mui-selected'); - }); + expect(getRow(0)).not.to.have.class('Mui-selected'); + await microtasks(); }); @@ -318,13 +312,11 @@ describe(' - Rows', () => { render( []} />); expect(getRow(0)).not.to.have.class('Mui-selected'); fireEvent.click(screen.getByRole('menuitem', { name: 'more' })); - await waitFor(() => { - expect(getRow(0)).not.to.have.class('Mui-selected'); - }); + expect(getRow(0)).not.to.have.class('Mui-selected'); }); it('should close other menus before opening a new one', async () => { - render( + const { user } = render( []} @@ -333,18 +325,12 @@ describe(' - Rows', () => { expect(screen.queryAllByRole('menu')).to.have.length(2); const more1 = screen.getAllByRole('menuitem', { name: 'more' })[0]; - fireEvent.mouseDown(more1); - fireEvent.click(more1); - await waitFor(() => { - expect(screen.queryAllByRole('menu')).to.have.length(2 + 1); - }); + await user.click(more1); + expect(screen.queryAllByRole('menu')).to.have.length(2 + 1); const more2 = screen.getAllByRole('menuitem', { name: 'more' })[1]; - fireEvent.mouseDown(more2); - fireEvent.click(more2); - await waitFor(() => { - expect(screen.queryAllByRole('menu')).to.have.length(2 + 1); - }); + await user.click(more2); + expect(screen.queryAllByRole('menu')).to.have.length(2 + 1); }); it('should allow to move focus to another cell with the arrow keys', () => { @@ -375,10 +361,8 @@ describe(' - Rows', () => { const moreButton = screen.getByRole('menuitem', { name: 'more' }); fireUserEvent.mousePress(moreButton); - await waitFor(() => { - const printButton = screen.queryByRole('menuitem', { name: 'print' }); - expect(printButton).toHaveFocus(); - }); + const printButton = screen.queryByRole('menuitem', { name: 'print' }); + expect(printButton).toHaveFocus(); }); it('should allow to navigate between actions using the arrow keys', () => { @@ -642,9 +626,9 @@ describe(' - Rows', () => { '.MuiDataGrid-virtualScrollerContent', ); const expectedHeight = baselineProps.rows.length * (contentHeight + border); - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); - }); + + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); @@ -669,9 +653,9 @@ describe(' - Rows', () => { measuredRowHeight + border + // Measured rows also include the border (baselineProps.rows.length - 1) * defaultRowHeight; - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); - }); + + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); @@ -696,9 +680,9 @@ describe(' - Rows', () => { const firstRowHeight = measuredRowHeight + border; // Measured rows also include the border const expectedHeight = firstRowHeight + (baselineProps.rows.length - 1) * estimatedRowHeight; - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); - }); + + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); @@ -714,14 +698,12 @@ describe(' - Rows', () => { const virtualScrollerContent = document.querySelector( '.MuiDataGrid-virtualScrollerContent', ); - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ height: '101px' }); - }); + + expect(virtualScrollerContent).toHaveComputedStyle({ height: '101px' }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); setProps({ rows: [{ clientId: 'c1', expanded: true }] }); - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ height: '201px' }); - }); + expect(virtualScrollerContent).toHaveComputedStyle({ height: '201px' }); + expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); @@ -764,20 +746,16 @@ describe(' - Rows', () => { />, ); const virtualScroller = grid('virtualScroller')!; - await waitFor(() => - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 52 + 52), - ); - virtualScroller.scrollTop = 101; // Scroll to measure the 2nd cell + + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 52 + 52), + (virtualScroller.scrollTop = 101); // Scroll to measure the 2nd cell virtualScroller.dispatchEvent(new Event('scroll')); - await waitFor(() => - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 52), - ); - virtualScroller.scrollTop = 10e6; // Scroll to measure all cells + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 52), + (virtualScroller.scrollTop = 10e6); // Scroll to measure all cells virtualScroller.dispatchEvent(new Event('scroll')); - await waitFor(() => - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 101), - ); + + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 101); }); it('should allow to mix rows with dynamic row height and default row height', async () => { @@ -800,10 +778,9 @@ describe(' - Rows', () => { const virtualScrollerContent = document.querySelector( '.MuiDataGrid-virtualScrollerContent', )!; - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ - height: `${Math.floor(expectedHeight)}px`, - }); + + expect(virtualScrollerContent).toHaveComputedStyle({ + height: `${Math.floor(expectedHeight)}px`, }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); @@ -833,9 +810,7 @@ describe(' - Rows', () => { fireEvent.click(screen.getByRole('button', { name: /next page/i })); - await waitFor(() => { - expect(gridOffsetTop()).to.equal(0); - }); + expect(gridOffsetTop()).to.equal(0); }, ); @@ -895,9 +870,7 @@ describe(' - Rows', () => { setProps({ pageSize: 10 }); fireEvent.click(screen.getByRole('button', { name: /next page/i })); - await waitFor(() => { - expect(gridOffsetTop()).to.equal(0); - }); + expect(gridOffsetTop()).to.equal(0); }, ); }); diff --git a/test/utils/mochaHooks.js b/test/utils/mochaHooks.js index e7d0a9df9f613..5500614e0f6b3 100644 --- a/test/utils/mochaHooks.js +++ b/test/utils/mochaHooks.js @@ -5,8 +5,26 @@ import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingTreeView import { unstable_cleanupDOM as unstable_cleanupDOMCharts } from '@mui/x-charts/internals'; import { clearWarningsCache } from '@mui/x-internals/warning'; import { generateTestLicenseKey, setupTestLicenseKey } from './testLicense'; +import * as ReactTransitionGroup from 'react-transition-group'; +import React from 'react'; export function createXMochaHooks(coreMochaHooks = {}) { + const OriginalTransition = ReactTransitionGroup.Transition; + const OriginalCSSTransition = ReactTransitionGroup.CSSTransition; + const FakeTransition = (props) => { + return props.in ? ( + + ) : null; + }; + const FakeCSSTransition = (props) => { + return props.in ? ( + + ) : null; + }; + + ReactTransitionGroup.Transition = FakeTransition; + ReactTransitionGroup.CSSTransition = FakeCSSTransition; + const mochaHooks = { beforeAll: [...(coreMochaHooks.beforeAll ?? [])], afterAll: [...(coreMochaHooks.afterAll ?? [])], From 2f5117adefcbd8395d59d3667f0b40038554e78e Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 22 Jan 2025 09:02:02 +0200 Subject: [PATCH 02/34] Install missing `react-transition-group` dep in `test` package --- pnpm-lock.yaml | 3 +++ test/package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c0300c8d0bc51..e47a6a180eef7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1651,6 +1651,9 @@ importers: react-router-dom: specifier: ^6.28.2 version: 6.28.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react-transition-group: + specifier: ^4.4.5 + version: 4.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) semver: specifier: ^7.6.3 version: 7.6.3 diff --git a/test/package.json b/test/package.json index af9c7d07deddf..7f39ed8882cb6 100644 --- a/test/package.json +++ b/test/package.json @@ -34,6 +34,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^6.28.2", + "react-transition-group": "^4.4.5", "semver": "^7.6.3", "stylis": "^4.3.5", "stylis-plugin-rtl": "^2.1.1" From cfbdf4e16f7d7aa0e18befe15b34c6d21c791274 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 22 Jan 2025 09:03:03 +0200 Subject: [PATCH 03/34] Always render the transition component - `in` as `false` should render a hidden element --- test/utils/mochaHooks.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/utils/mochaHooks.js b/test/utils/mochaHooks.js index 5500614e0f6b3..da3c9940e49b1 100644 --- a/test/utils/mochaHooks.js +++ b/test/utils/mochaHooks.js @@ -1,3 +1,5 @@ +import * as React from 'react'; +import * as ReactTransitionGroup from 'react-transition-group'; import sinon from 'sinon'; import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingDataGrid } from '@mui/x-data-grid'; import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingDataGridPro } from '@mui/x-data-grid-pro'; @@ -5,21 +7,15 @@ import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingTreeView import { unstable_cleanupDOM as unstable_cleanupDOMCharts } from '@mui/x-charts/internals'; import { clearWarningsCache } from '@mui/x-internals/warning'; import { generateTestLicenseKey, setupTestLicenseKey } from './testLicense'; -import * as ReactTransitionGroup from 'react-transition-group'; -import React from 'react'; export function createXMochaHooks(coreMochaHooks = {}) { const OriginalTransition = ReactTransitionGroup.Transition; const OriginalCSSTransition = ReactTransitionGroup.CSSTransition; const FakeTransition = (props) => { - return props.in ? ( - - ) : null; + return ; }; const FakeCSSTransition = (props) => { - return props.in ? ( - - ) : null; + return }; ReactTransitionGroup.Transition = FakeTransition; From 73c71ba63144e6d6ee00204e49d6d1585dbd3047 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 22 Jan 2025 12:03:31 +0200 Subject: [PATCH 04/34] Fix eslint and prettier issues --- packages/x-data-grid/src/tests/rows.DataGrid.test.tsx | 9 ++++----- test/utils/mochaHooks.js | 10 +++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx index 055da4353389c..8c98da1171b1e 100644 --- a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx @@ -5,7 +5,6 @@ import { screen, act, ErrorBoundary, - waitFor, reactMajor, } from '@mui/internal-test-utils'; import clsx from 'clsx'; @@ -747,12 +746,12 @@ describe(' - Rows', () => { ); const virtualScroller = grid('virtualScroller')!; - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 52 + 52), - (virtualScroller.scrollTop = 101); // Scroll to measure the 2nd cell + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 52 + 52); + virtualScroller.scrollTop = 101; // Scroll to measure the 2nd cell virtualScroller.dispatchEvent(new Event('scroll')); - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 52), - (virtualScroller.scrollTop = 10e6); // Scroll to measure all cells + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 52); + virtualScroller.scrollTop = 10e6; // Scroll to measure all cells virtualScroller.dispatchEvent(new Event('scroll')); expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 101); diff --git a/test/utils/mochaHooks.js b/test/utils/mochaHooks.js index da3c9940e49b1..c9d3eb99b924e 100644 --- a/test/utils/mochaHooks.js +++ b/test/utils/mochaHooks.js @@ -11,14 +11,18 @@ import { generateTestLicenseKey, setupTestLicenseKey } from './testLicense'; export function createXMochaHooks(coreMochaHooks = {}) { const OriginalTransition = ReactTransitionGroup.Transition; const OriginalCSSTransition = ReactTransitionGroup.CSSTransition; - const FakeTransition = (props) => { + function FakeTransition(props) { return ; }; - const FakeCSSTransition = (props) => { - return + function FakeCSSTransition(props) { + return ( + + ); }; + // eslint-disable-next-line no-import-assign ReactTransitionGroup.Transition = FakeTransition; + // eslint-disable-next-line no-import-assign ReactTransitionGroup.CSSTransition = FakeCSSTransition; const mochaHooks = { From 5546f973ee3510eb49d36f8614c51ebb9f33b26f Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 22 Jan 2025 12:35:14 +0200 Subject: [PATCH 05/34] Try built-in `react-transition-group` transition disabling for testing --- test/utils/mochaHooks.js | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/test/utils/mochaHooks.js b/test/utils/mochaHooks.js index c9d3eb99b924e..94baa0a6fd05b 100644 --- a/test/utils/mochaHooks.js +++ b/test/utils/mochaHooks.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import * as ReactTransitionGroup from 'react-transition-group'; +import { config } from 'react-transition-group'; import sinon from 'sinon'; import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingDataGrid } from '@mui/x-data-grid'; import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingDataGridPro } from '@mui/x-data-grid-pro'; @@ -9,21 +9,9 @@ import { clearWarningsCache } from '@mui/x-internals/warning'; import { generateTestLicenseKey, setupTestLicenseKey } from './testLicense'; export function createXMochaHooks(coreMochaHooks = {}) { - const OriginalTransition = ReactTransitionGroup.Transition; - const OriginalCSSTransition = ReactTransitionGroup.CSSTransition; - function FakeTransition(props) { - return ; - }; - function FakeCSSTransition(props) { - return ( - - ); - }; - - // eslint-disable-next-line no-import-assign - ReactTransitionGroup.Transition = FakeTransition; - // eslint-disable-next-line no-import-assign - ReactTransitionGroup.CSSTransition = FakeCSSTransition; + // disable "react-transition-group" transitions + // https://reactcommunity.org/react-transition-group/testing/ + config.disabled = true; const mochaHooks = { beforeAll: [...(coreMochaHooks.beforeAll ?? [])], From 583b0784441ee89e46e5dc25757c23f60891ffc2 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 23 Jan 2025 10:34:59 +0200 Subject: [PATCH 06/34] Try mocking components instead of using config --- .../src/tests/license.DataGridPro.test.tsx | 2 +- .../src/tests/rows.DataGrid.test.tsx | 48 ++++++++++--------- test/utils/mochaHooks.js | 26 ++++++---- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx index e19bad19e2791..be77d8d2634fa 100644 --- a/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx @@ -7,7 +7,7 @@ import { LicenseInfo } from '@mui/x-license'; describe(' - License', () => { const { render } = createRenderer(); - it('should render watermark when the license is missing', async () => { + it('should render watermark when the license is missing', () => { LicenseInfo.setLicenseKey(''); expect(() => render()).toErrorDev([ diff --git a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx index 8c98da1171b1e..369ceb914af96 100644 --- a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx @@ -40,7 +40,7 @@ import { testSkipIf, isJSDOM, describeSkipIf } from 'test/utils/skipIf'; import { COMPACT_DENSITY_FACTOR } from '../hooks/features/density/densitySelector'; -describe(' - Rows', () => { +describe.only(' - Rows', () => { const { render } = createRenderer(); let apiRef: React.RefObject; @@ -276,13 +276,15 @@ describe(' - Rows', () => { }); it('should show in a menu the actions marked as showInMenu', async () => { - render( []} />); + const { user } = render( + []} />, + ); expect(screen.queryByText('print')).to.equal(null); - fireEvent.click(screen.getByRole('menuitem', { name: 'more' })); + await user.click(screen.getByRole('menuitem', { name: 'more' })); expect(screen.queryByText('print')).not.to.equal(null); }); - it('should not select the row when clicking in an action', async () => { + it('should not select the row when clicking in an action', () => { render( [} label="print" />]} />, ); @@ -292,25 +294,25 @@ describe(' - Rows', () => { }); it('should not select the row when clicking in a menu action', async () => { - render( + const { user } = render( [} label="print" showInMenu />]} />, ); expect(getRow(0)).not.to.have.class('Mui-selected'); - fireEvent.click(screen.getByRole('menuitem', { name: 'more' })); + await user.click(screen.getByRole('menuitem', { name: 'more' })); expect(screen.queryByText('print')).not.to.equal(null); - fireEvent.click(screen.getByText('print')); + await user.click(screen.getByText('print')); expect(getRow(0)).not.to.have.class('Mui-selected'); - - await microtasks(); }); it('should not select the row when opening the menu', async () => { - render( []} />); + const { user } = render( + []} />, + ); expect(getRow(0)).not.to.have.class('Mui-selected'); - fireEvent.click(screen.getByRole('menuitem', { name: 'more' })); + await user.click(screen.getByRole('menuitem', { name: 'more' })); expect(getRow(0)).not.to.have.class('Mui-selected'); }); @@ -349,7 +351,7 @@ describe(' - Rows', () => { }); it('should focus the first item when opening the menu', async () => { - render( + const { user } = render( [ } label="print" showInMenu />, @@ -358,7 +360,7 @@ describe(' - Rows', () => { />, ); const moreButton = screen.getByRole('menuitem', { name: 'more' }); - fireUserEvent.mousePress(moreButton); + await user.click(moreButton); const printButton = screen.queryByRole('menuitem', { name: 'print' }); expect(printButton).toHaveFocus(); @@ -617,7 +619,7 @@ describe(' - Rows', () => { ); } - it('should measure all rows and update the content size', async () => { + it('should measure all rows and update the content size', () => { const border = 1; const contentHeight = 100; render( contentHeight} getRowHeight={() => 'auto'} />); @@ -631,7 +633,7 @@ describe(' - Rows', () => { expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); - it('should use the default row height to calculate the content size when the row has not been measured yet', async () => { + it('should use the default row height to calculate the content size when the row has not been measured yet', () => { const columnHeaderHeight = 50; const border = 1; const defaultRowHeight = 52; @@ -658,7 +660,7 @@ describe(' - Rows', () => { expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); - it('should use the value from getEstimatedRowHeight to estimate the content size', async () => { + it('should use the value from getEstimatedRowHeight to estimate the content size', () => { const columnHeaderHeight = 50; const border = 1; const measuredRowHeight = 100; @@ -685,7 +687,7 @@ describe(' - Rows', () => { expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); - it('should recalculate the content size when the rows prop changes', async () => { + it('should recalculate the content size when the rows prop changes', () => { const { setProps } = render( (row.expanded ? 200 : 100)} @@ -732,7 +734,7 @@ describe(' - Rows', () => { expect($$(`.${gridClasses.cell}:not(.${gridClasses.cellEmpty})`)).to.have.length(2); }); - it('should measure rows while scrolling', async () => { + it('should measure rows while scrolling', () => { const columnHeaderHeight = 50; const border = 1; render( @@ -757,7 +759,7 @@ describe(' - Rows', () => { expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 101); }); - it('should allow to mix rows with dynamic row height and default row height', async () => { + it('should allow to mix rows with dynamic row height and default row height', () => { const columnHeaderHeight = 50; const densityFactor = 1.3; const rowHeight = 52; @@ -788,7 +790,7 @@ describe(' - Rows', () => { const { userAgent } = window.navigator; testSkipIf(!userAgent.includes('Headless') || /edg/i.test(userAgent))( 'should position correctly the render zone when the 2nd page has less rows than the 1st page', - async () => { + () => { const data = getBasicGridData(120, 3); const columnHeaderHeight = 50; const measuredRowHeight = 100; @@ -813,7 +815,7 @@ describe(' - Rows', () => { }, ); - it('should position correctly the render zone when changing pageSize to a lower value', async () => { + it('should position correctly the render zone when changing pageSize to a lower value', () => { const data = getBasicGridData(120, 3); const columnHeaderHeight = 50; const measuredRowHeight = 100; @@ -840,7 +842,7 @@ describe(' - Rows', () => { // In Chrome non-headless and Edge this test is flaky testSkipIf(!userAgent.includes('Headless') || /edg/i.test(userAgent))( 'should position correctly the render zone when changing pageSize to a lower value and moving to next page', - async () => { + () => { const data = getBasicGridData(120, 3); const columnHeaderHeight = 50; const measuredRowHeight = 100; @@ -1083,7 +1085,7 @@ describe(' - Rows', () => { // needs virtualization testSkipIf(isJSDOM)( 'should set proper `data-rowindex` and `aria-rowindex` when focused row is out of the viewport', - async () => { + () => { render(
{children}; }; + + function FakeCSSTransition(props) { + return props.in ? {props.children} : null; + } + + transitionStub = stub(ReactTransitionGroup, 'Transition').callsFake(FakeTransition); + cssTransitionStub = stub(ReactTransitionGroup, 'CSSTransition').callsFake(FakeCSSTransition); }); mochaHooks.beforeEach.push(function setupLicenseKey() { @@ -38,10 +43,15 @@ export function createXMochaHooks(coreMochaHooks = {}) { // Restore Sinon default sandbox to avoid memory leak // See https://github.com/sinonjs/sinon/issues/1866 - sinon.restore(); + restore(); }); mochaHooks.afterEach.push(clearWarningsCache); + mochaHooks.afterAll.push(function restoreTransition() { + transitionStub.restore(); + cssTransitionStub.restore(); + }); + return mochaHooks; } From 1e8be24f655cdbeaa70f867b702b598ee021e6e3 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 23 Jan 2025 10:37:50 +0200 Subject: [PATCH 07/34] prettier & eslint --- packages/x-data-grid/src/tests/rows.DataGrid.test.tsx | 3 +-- test/utils/mochaHooks.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx index 369ceb914af96..7695a269840b7 100644 --- a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx @@ -31,7 +31,6 @@ import { getRow, getActiveCell, getCell, - microtasks, $$, } from 'test/utils/helperFn'; import { fireUserEvent } from 'test/utils/fireUserEvent'; @@ -40,7 +39,7 @@ import { testSkipIf, isJSDOM, describeSkipIf } from 'test/utils/skipIf'; import { COMPACT_DENSITY_FACTOR } from '../hooks/features/density/densitySelector'; -describe.only(' - Rows', () => { +describe(' - Rows', () => { const { render } = createRenderer(); let apiRef: React.RefObject; diff --git a/test/utils/mochaHooks.js b/test/utils/mochaHooks.js index 93599af874968..412e6c6822ec4 100644 --- a/test/utils/mochaHooks.js +++ b/test/utils/mochaHooks.js @@ -16,14 +16,20 @@ export function createXMochaHooks(coreMochaHooks = {}) { afterEach: [...(coreMochaHooks.afterEach ?? [])], }; - let licenseKey, transitionStub, cssTransitionStub; + let licenseKey; + let transitionStub; + let cssTransitionStub; mochaHooks.beforeAll.push(function func() { licenseKey = generateTestLicenseKey(); - function FakeTransition({ children }) { return {children}; }; + // eslint-disable-next-line react/prop-types + function FakeTransition({ children }) { + return {children}; + } function FakeCSSTransition(props) { + // eslint-disable-next-line react/prop-types return props.in ? {props.children} : null; } From fd8dccd96f9985b17a284198e4ca728c4c6c7310 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 24 Jan 2025 17:35:08 +0200 Subject: [PATCH 08/34] Revert back to `config.disabled = "true"` solution --- test/utils/mochaHooks.js | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/test/utils/mochaHooks.js b/test/utils/mochaHooks.js index 412e6c6822ec4..4dd89eac557b3 100644 --- a/test/utils/mochaHooks.js +++ b/test/utils/mochaHooks.js @@ -1,6 +1,5 @@ -import * as React from 'react'; -import * as ReactTransitionGroup from 'react-transition-group'; -import { stub, restore } from 'sinon'; +import { config } from 'react-transition-group'; +import { restore } from 'sinon'; import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingDataGrid } from '@mui/x-data-grid'; import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingDataGridPro } from '@mui/x-data-grid-pro'; import { unstable_resetCleanupTracking as unstable_resetCleanupTrackingTreeView } from '@mui/x-tree-view'; @@ -17,24 +16,12 @@ export function createXMochaHooks(coreMochaHooks = {}) { }; let licenseKey; - let transitionStub; - let cssTransitionStub; mochaHooks.beforeAll.push(function func() { + // disable "react-transition-group" transitions + // https://reactcommunity.org/react-transition-group/testing/ + config.disabled = true; licenseKey = generateTestLicenseKey(); - - // eslint-disable-next-line react/prop-types - function FakeTransition({ children }) { - return {children}; - } - - function FakeCSSTransition(props) { - // eslint-disable-next-line react/prop-types - return props.in ? {props.children} : null; - } - - transitionStub = stub(ReactTransitionGroup, 'Transition').callsFake(FakeTransition); - cssTransitionStub = stub(ReactTransitionGroup, 'CSSTransition').callsFake(FakeCSSTransition); }); mochaHooks.beforeEach.push(function setupLicenseKey() { @@ -55,8 +42,7 @@ export function createXMochaHooks(coreMochaHooks = {}) { mochaHooks.afterEach.push(clearWarningsCache); mochaHooks.afterAll.push(function restoreTransition() { - transitionStub.restore(); - cssTransitionStub.restore(); + config.disabled = false; }); return mochaHooks; From f30868bfc0cf1b83bb93645578a3c9bf3529450e Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 27 Jan 2025 11:19:40 +0200 Subject: [PATCH 09/34] Override `config` flag for tests needing transitions --- packages/x-data-grid-premium/package.json | 2 ++ .../src/tests/rowGrouping.DataGridPremium.test.tsx | 8 ++++++++ packages/x-data-grid-pro/package.json | 2 ++ .../src/tests/columnHeaders.DataGridPro.test.tsx | 8 ++++++++ pnpm-lock.yaml | 12 ++++++++++++ 5 files changed, 32 insertions(+) diff --git a/packages/x-data-grid-premium/package.json b/packages/x-data-grid-premium/package.json index be6374c85d936..ce6a1a00d780e 100644 --- a/packages/x-data-grid-premium/package.json +++ b/packages/x-data-grid-premium/package.json @@ -76,9 +76,11 @@ "@mui/material": "^5.16.14", "@mui/system": "^5.16.14", "@types/prop-types": "^15.7.14", + "@types/react-transition-group": "^4.4.12", "date-fns": "^4.1.0", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-transition-group": "^4.4.5", "rimraf": "^6.0.1" }, "engines": { diff --git a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx index c25c327b78456..adb4b5cdcbc59 100644 --- a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { config } from 'react-transition-group'; import { createRenderer, fireEvent, @@ -1775,6 +1776,10 @@ describe(' - Row grouping', () => { }); it('should add a "Stop grouping {field}" menu item for each grouping criteria on the grouping column when prop.rowGroupingColumnMode = "single"', () => { + const restoreDisabledConfig = config.disabled; + // enable `react-transition-group` transitions for this test + config.disabled = false; + render( - Row grouping', () => { }); fireEvent.click(menuItemCategory2); expect(apiRef.current.state.rowGrouping.model).to.deep.equal([]); + + // restore previous config + config.disabled = restoreDisabledConfig; }); it('should add a "Stop grouping {field}" menu item for each grouping criteria with colDef.groupable = false but it should be disabled', () => { diff --git a/packages/x-data-grid-pro/package.json b/packages/x-data-grid-pro/package.json index d46649b5bb560..d01c8c61233c1 100644 --- a/packages/x-data-grid-pro/package.json +++ b/packages/x-data-grid-pro/package.json @@ -74,8 +74,10 @@ "@mui/material": "^5.16.14", "@mui/system": "^5.16.14", "@types/prop-types": "^15.7.14", + "@types/react-transition-group": "^4.4.12", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-transition-group": "^4.4.5", "rimraf": "^6.0.1" }, "engines": { diff --git a/packages/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx index 941db99c7893d..c8c5a7105eae7 100644 --- a/packages/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { config } from 'react-transition-group'; import { createRenderer, fireEvent, screen } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { gridClasses, DataGridPro, DataGridProProps } from '@mui/x-data-grid-pro'; @@ -198,6 +199,10 @@ describe(' - Column headers', () => { }); it('should remove the MuiDataGrid-menuOpen CSS class only after the transition has ended', () => { + const restoreDisabledConfig = config.disabled; + // enable `react-transition-group` transitions for this test + config.disabled = false; + render(
@@ -212,6 +217,9 @@ describe(' - Column headers', () => { expect(menuIconButton?.parentElement).to.have.class(gridClasses.menuOpen); clock.runToLast(); // Wait for the transition to run expect(menuIconButton?.parentElement).not.to.have.class(gridClasses.menuOpen); + + // restore previous config + config.disabled = restoreDisabledConfig; }); it('should restore focus to the column header when dismissing the menu by selecting any item', () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e47a6a180eef7..fee6e290ad432 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1147,6 +1147,9 @@ importers: '@types/prop-types': specifier: ^15.7.14 version: 15.7.14 + '@types/react-transition-group': + specifier: ^4.4.12 + version: 4.4.12(@types/react@19.0.7) date-fns: specifier: ^4.1.0 version: 4.1.0 @@ -1156,6 +1159,9 @@ importers: react-dom: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) + react-transition-group: + specifier: ^4.4.5 + version: 4.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -1209,12 +1215,18 @@ importers: '@types/prop-types': specifier: ^15.7.14 version: 15.7.14 + '@types/react-transition-group': + specifier: ^4.4.12 + version: 4.4.12(@types/react@19.0.7) react: specifier: ^19.0.0 version: 19.0.0 react-dom: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) + react-transition-group: + specifier: ^4.4.5 + version: 4.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rimraf: specifier: ^6.0.1 version: 6.0.1 From e8a289fc91d92ec9a6edc862c43121b0c99b3a7c Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 27 Jan 2025 13:04:21 +0200 Subject: [PATCH 10/34] Use `waitFor` in relevant cases, where browser tests fail otherwise --- .../src/tests/rows.DataGrid.test.tsx | 68 +++++++++++++------ 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx index fd05865aac418..1ad123f0d95d8 100644 --- a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx @@ -7,6 +7,7 @@ import { act, ErrorBoundary, reactMajor, + waitFor, } from '@mui/internal-test-utils'; import clsx from 'clsx'; import { expect } from 'chai'; @@ -331,7 +332,9 @@ describe(' - Rows', () => { const more2 = screen.getAllByRole('menuitem', { name: 'more' })[1]; await user.click(more2); - expect(screen.queryAllByRole('menu')).to.have.length(2 + 1); + await waitFor(() => { + expect(screen.queryAllByRole('menu')).to.have.length(2 + 1); + }); }); it('should allow to move focus to another cell with the arrow keys', () => { @@ -619,7 +622,7 @@ describe(' - Rows', () => { ); } - it('should measure all rows and update the content size', () => { + it('should measure all rows and update the content size', async () => { const border = 1; const contentHeight = 100; render( contentHeight} getRowHeight={() => 'auto'} />); @@ -628,12 +631,14 @@ describe(' - Rows', () => { ); const expectedHeight = baselineProps.rows.length * (contentHeight + border); - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + await waitFor(() => { + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); - it('should use the default row height to calculate the content size when the row has not been measured yet', () => { + it('should use the default row height to calculate the content size when the row has not been measured yet', async () => { const columnHeaderHeight = 50; const border = 1; const defaultRowHeight = 52; @@ -655,12 +660,14 @@ describe(' - Rows', () => { border + // Measured rows also include the border (baselineProps.rows.length - 1) * defaultRowHeight; - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + await waitFor(() => { + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); - it('should use the value from getEstimatedRowHeight to estimate the content size', () => { + it('should use the value from getEstimatedRowHeight to estimate the content size', async () => { const columnHeaderHeight = 50; const border = 1; const measuredRowHeight = 100; @@ -682,12 +689,14 @@ describe(' - Rows', () => { const expectedHeight = firstRowHeight + (baselineProps.rows.length - 1) * estimatedRowHeight; - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + await waitFor(() => { + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${expectedHeight}px` }); + }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); - it('should recalculate the content size when the rows prop changes', () => { + it('should recalculate the content size when the rows prop changes', async () => { const { setProps } = render( (row.expanded ? 200 : 100)} @@ -700,10 +709,15 @@ describe(' - Rows', () => { '.MuiDataGrid-virtualScrollerContent', ); - expect(virtualScrollerContent).toHaveComputedStyle({ height: '101px' }); + await waitFor(() => { + expect(virtualScrollerContent).toHaveComputedStyle({ height: '101px' }); + }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); setProps({ rows: [{ clientId: 'c1', expanded: true }] }); - expect(virtualScrollerContent).toHaveComputedStyle({ height: '201px' }); + + await waitFor(() => { + expect(virtualScrollerContent).toHaveComputedStyle({ height: '201px' }); + }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); @@ -734,7 +748,7 @@ describe(' - Rows', () => { expect($$(`.${gridClasses.cell}:not(.${gridClasses.cellEmpty})`)).to.have.length(2); }); - it('should measure rows while scrolling', () => { + it('should measure rows while scrolling', async () => { const columnHeaderHeight = 50; const border = 1; render( @@ -748,18 +762,24 @@ describe(' - Rows', () => { ); const virtualScroller = grid('virtualScroller')!; - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 52 + 52); + await waitFor(() => { + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 52 + 52); + }); virtualScroller.scrollTop = 101; // Scroll to measure the 2nd cell virtualScroller.dispatchEvent(new Event('scroll')); - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 52); + await waitFor(() => { + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 52); + }); virtualScroller.scrollTop = 10e6; // Scroll to measure all cells virtualScroller.dispatchEvent(new Event('scroll')); - expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 101); + await waitFor(() => { + expect(virtualScroller.scrollHeight).to.equal(columnHeaderHeight + 101 + 101 + 101); + }); }); - it('should allow to mix rows with dynamic row height and default row height', () => { + it('should allow to mix rows with dynamic row height and default row height', async () => { const columnHeaderHeight = 50; const densityFactor = 1.3; const rowHeight = 52; @@ -780,8 +800,10 @@ describe(' - Rows', () => { '.MuiDataGrid-virtualScrollerContent', )!; - expect(virtualScrollerContent).toHaveComputedStyle({ - height: `${Math.floor(expectedHeight)}px`, + await waitFor(() => { + expect(virtualScrollerContent).toHaveComputedStyle({ + height: `${Math.floor(expectedHeight)}px`, + }); }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); }); @@ -790,7 +812,7 @@ describe(' - Rows', () => { const { userAgent } = window.navigator; testSkipIf(!userAgent.includes('Headless') || /edg/i.test(userAgent))( 'should position correctly the render zone when the 2nd page has less rows than the 1st page', - () => { + async () => { const data = getBasicGridData(120, 3); const columnHeaderHeight = 50; const measuredRowHeight = 100; @@ -811,7 +833,9 @@ describe(' - Rows', () => { fireEvent.click(screen.getByRole('button', { name: /next page/i })); - expect(gridOffsetTop()).to.equal(0); + await waitFor(() => { + expect(gridOffsetTop()).to.equal(0); + }); }, ); @@ -842,7 +866,7 @@ describe(' - Rows', () => { // In Chrome non-headless and Edge this test is flaky testSkipIf(!userAgent.includes('Headless') || /edg/i.test(userAgent))( 'should position correctly the render zone when changing pageSize to a lower value and moving to next page', - () => { + async () => { const data = getBasicGridData(120, 3); const columnHeaderHeight = 50; const measuredRowHeight = 100; @@ -871,7 +895,9 @@ describe(' - Rows', () => { setProps({ pageSize: 10 }); fireEvent.click(screen.getByRole('button', { name: /next page/i })); - expect(gridOffsetTop()).to.equal(0); + await waitFor(() => { + expect(gridOffsetTop()).to.equal(0); + }); }, ); }); From b639fa25c77871b472dc8343a62bff125d6bdc1c Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 10:15:55 +0200 Subject: [PATCH 11/34] Remove `waitFor` where possible --- .../src/tests/DataGridPremium.test.tsx | 4 +- ...SourceAggregation.DataGridPremium.test.tsx | 22 ++++------- .../tests/license.DataGridPremium.test.tsx | 8 ++-- .../rowGrouping.DataGridPremium.test.tsx | 37 ++++++++----------- .../tests/cellEditing.DataGridPro.test.tsx | 12 +++--- .../tests/detailPanel.DataGridPro.test.tsx | 27 ++++---------- .../tests/editComponents.DataGridPro.test.tsx | 2 +- .../src/tests/rowEditing.DataGridPro.test.tsx | 12 +++--- .../src/tests/rowPinning.DataGridPro.test.tsx | 32 ++++++++-------- .../src/tests/columnHeaders.DataGrid.test.tsx | 6 +-- .../src/tests/layout.DataGrid.test.tsx | 12 ++---- .../src/tests/rowSelection.DataGrid.test.tsx | 22 ++++------- 12 files changed, 76 insertions(+), 120 deletions(-) diff --git a/packages/x-data-grid-premium/src/tests/DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/DataGridPremium.test.tsx index 2fc1d67f33d17..ece1b4dd4faf9 100644 --- a/packages/x-data-grid-premium/src/tests/DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/DataGridPremium.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { RefObject } from '@mui/x-internals/types'; -import { createRenderer, act, waitFor } from '@mui/internal-test-utils'; +import { createRenderer, act } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { DataGridPremium as DataGrid, @@ -104,6 +104,6 @@ describe(' - Quick filter', () => { }, }); - await waitFor(() => expect(getColumnValues(0)).to.deep.equal(['20th Century Fox (1)', ''])); + expect(getColumnValues(0)).to.deep.equal(['20th Century Fox (1)', '']); }); }); diff --git a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx index f7065916f2363..483ea7e0ffaa2 100644 --- a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { RefObject } from '@mui/x-internals/types'; import { useMockServer } from '@mui/x-data-grid-generator'; -import { createRenderer, waitFor, screen, within } from '@mui/internal-test-utils'; +import { createRenderer, screen, waitFor, within } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { DataGridPremium, @@ -99,23 +99,19 @@ describe(' - Data source aggregation', () => { it('should show aggregation option in the column menu', async () => { const { user } = render(); - await waitFor(() => { - expect(getRowsSpy.callCount).to.be.greaterThan(0); - }); + expect(getRowsSpy.callCount).to.be.greaterThan(0); await user.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); expect(screen.queryByLabelText('Aggregation')).not.to.equal(null); }); it('should not show aggregation option in the column menu when no aggregation function is defined', async () => { const { user } = render(); - await waitFor(() => { - expect(getRowsSpy.callCount).to.be.greaterThan(0); - }); + expect(getRowsSpy.callCount).to.be.greaterThan(0); await user.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); expect(screen.queryByLabelText('Aggregation')).to.equal(null); }); - it('should provide the `aggregationModel` in the `getRows` params', async () => { + it('should provide the `aggregationModel` in the `getRows` params', () => { render( - Data source aggregation', () => { }} />, ); - await waitFor(() => { - expect(getRowsSpy.callCount).to.be.greaterThan(0); - }); + expect(getRowsSpy.callCount).to.be.greaterThan(0); expect(getRowsSpy.args[0][0].aggregationModel).to.deep.equal({ id: 'size' }); }); @@ -145,7 +139,7 @@ describe(' - Data source aggregation', () => { expect(footerRow.id).to.deep.equal({ position: 'footer', value: 10 }); }); - it('should derive the aggregation values using `dataSource.getAggregatedValue`', async () => { + it('should derive the aggregation values using `dataSource.getAggregatedValue`', () => { render( - Data source aggregation', () => { getAggregatedValue={() => 'Agg value'} />, ); - await waitFor(() => { - expect(Object.keys(apiRef.current.state.aggregation.lookup).length).to.be.greaterThan(0); - }); + expect(Object.keys(apiRef.current.state.aggregation.lookup).length).to.be.greaterThan(0); expect(apiRef.current.state.aggregation.lookup[GRID_ROOT_GROUP_ID].id.value).to.equal( 'Agg value', ); diff --git a/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx index 9a230483cda99..873a63be4beeb 100644 --- a/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { addYears } from 'date-fns/addYears'; import { expect } from 'chai'; -import { createRenderer, screen, waitFor } from '@mui/internal-test-utils'; +import { createRenderer, screen } from '@mui/internal-test-utils'; import { DataGridPremium } from '@mui/x-data-grid-premium'; import { generateLicense, LicenseInfo } from '@mui/x-license'; @@ -23,15 +23,13 @@ describe(' - License', () => { ]); }); - it('should render watermark when the license is missing', async () => { + it('should render watermark when the license is missing', () => { LicenseInfo.setLicenseKey(''); expect(() => render()).toErrorDev([ 'MUI X: Missing license key.', ]); - await waitFor(() => { - expect(screen.getByText('MUI X Missing license key')).not.to.equal(null); - }); + expect(screen.getByText('MUI X Missing license key')).not.to.equal(null); }); }); diff --git a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx index 6e4702943649d..92f6d04840f94 100644 --- a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx @@ -1,14 +1,7 @@ import * as React from 'react'; import { config } from 'react-transition-group'; import { RefObject } from '@mui/x-internals/types'; -import { - createRenderer, - fireEvent, - screen, - act, - waitFor, - reactMajor, -} from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act, reactMajor } from '@mui/internal-test-utils'; import { microtasks, getColumnHeaderCell, @@ -2883,14 +2876,16 @@ describe(' - Row grouping', () => { />, ); - act(() => apiRef.current.updateRows([{ id: 1, group: 'A', username: 'username 2' }])); + await act(() => { + apiRef.current.updateRows([{ id: 1, group: 'A', username: 'username 2' }]); + }); - await waitFor(() => expect(getCell(1, 3).textContent).to.equal('username 2')); + expect(getCell(1, 3).textContent).to.equal('username 2'); }); // See https://github.com/mui/mui-x/issues/8580 it('should not collapse expanded groups after `updateRows`', async () => { - render( + const { user } = render( - Row grouping', () => { />, ); - fireEvent.click(screen.getByRole('button', { name: 'see children' })); - - act(() => apiRef.current.updateRows([{ id: 1, group: 'A', username: 'username 2' }])); + await user.click(screen.getByRole('button', { name: 'see children' })); - await waitFor(() => { - expect(screen.getByRole('button', { name: 'hide children' })).toBeVisible(); + await act(() => { + apiRef.current.updateRows([{ id: 1, group: 'A', username: 'username 2' }]); }); - await waitFor(() => expect(getCell(1, 3).textContent).to.equal('username 2')); + + expect(screen.getByRole('button', { name: 'hide children' })).toBeVisible(); + expect(getCell(1, 3).textContent).to.equal('username 2'); }); // See https://github.com/mui/mui-x/issues/8853 @@ -2925,10 +2920,10 @@ describe(' - Row grouping', () => { expect(getColumnValues(3)).to.deep.equal(['', 'username1', 'username2']); // trigger row update without any changes in row data - act(() => apiRef.current.updateRows([{ id: 1 }])); - - await waitFor(() => { - expect(getColumnValues(3)).to.deep.equal(['', 'username1', 'username2']); + await act(() => { + apiRef.current.updateRows([{ id: 1 }]); }); + + expect(getColumnValues(3)).to.deep.equal(['', 'username1', 'username2']); }); }); diff --git a/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx index 7878dbf52e4f3..acc692da58f8e 100644 --- a/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx @@ -14,7 +14,7 @@ import { GridColDef, } from '@mui/x-data-grid-pro'; import { getBasicGridData } from '@mui/x-data-grid-generator'; -import { createRenderer, fireEvent, act, waitFor } from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, act } from '@mui/internal-test-utils'; import { getCell, spyApi } from 'test/utils/helperFn'; import { fireUserEvent } from 'test/utils/fireUserEvent'; @@ -906,15 +906,13 @@ describe(' - Cell editing', () => { it('should call preProcessEditCellProps', async () => { const preProcessEditCellProps = spy(({ props }: GridPreProcessEditCellProps) => props); - render(); + const { user } = render(); const cell = getCell(0, 1); - fireUserEvent.mousePress(cell); - fireEvent.keyDown(cell, { key: 'Delete' }); + await user.click(cell); + await user.keyboard('{Delete}'); - await waitFor(() => { - expect(preProcessEditCellProps.callCount).to.equal(1); - }); + expect(preProcessEditCellProps.callCount).to.equal(1); expect(preProcessEditCellProps.lastCall.args[0].props).to.deep.equal({ value: '', diff --git a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx index 39d903233345a..ba1d78e2260af 100644 --- a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx @@ -12,14 +12,7 @@ import { GRID_DETAIL_PANEL_TOGGLE_FIELD, } from '@mui/x-data-grid-pro'; import { useBasicDemoData } from '@mui/x-data-grid-generator'; -import { - createRenderer, - fireEvent, - screen, - waitFor, - act, - reactMajor, -} from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act, reactMajor } from '@mui/internal-test-utils'; import { $, $$, grid, getRow, getCell, getColumnValues, microtasks } from 'test/utils/helperFn'; import { fireUserEvent } from 'test/utils/fireUserEvent'; import { testSkipIf, isJSDOM } from 'test/utils/skipIf'; @@ -122,7 +115,7 @@ describe(' - Detail panel', () => { ); } const rowHeight = 50; - render( + const { user } = render( - Detail panel', () => { />, ); const virtualScrollerContent = grid('virtualScrollerContent')!; - fireEvent.click(screen.getByRole('button', { name: 'Expand' })); + await user.click(screen.getByRole('button', { name: 'Expand' })); - await waitFor(() => { - expect(getRow(0).className).to.include(gridClasses['row--detailPanelExpanded']); - }); + expect(getRow(0).className).to.include(gridClasses['row--detailPanelExpanded']); - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${rowHeight + 100}px` }); - }); + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${rowHeight + 100}px` }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); const detailPanels = $$('.MuiDataGrid-detailPanel'); @@ -147,11 +136,9 @@ describe(' - Detail panel', () => { height: `100px`, }); - fireEvent.click(screen.getByRole('button', { name: 'Increase' })); + await user.click(screen.getByRole('button', { name: 'Increase' })); - await waitFor(() => { - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${rowHeight + 200}px` }); - }); + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${rowHeight + 200}px` }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); expect(detailPanels[0]).toHaveComputedStyle({ diff --git a/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx index 45a0e02221031..063527de12bbb 100644 --- a/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx @@ -598,7 +598,7 @@ describe(' - Edit components', () => { const cell = getCell(0, 0); await user.dblClick(cell); await user.click(screen.queryAllByRole('option')[1]); - await waitFor(() => expect(screen.queryByRole('listbox')).to.equal(null)); + expect(screen.queryByRole('listbox')).to.equal(null); await act(() => { screen.getByRole('combobox').focus(); }); diff --git a/packages/x-data-grid-pro/src/tests/rowEditing.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/rowEditing.DataGridPro.test.tsx index 1d7168f9154a2..2863ea3b22e60 100644 --- a/packages/x-data-grid-pro/src/tests/rowEditing.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/rowEditing.DataGridPro.test.tsx @@ -14,7 +14,7 @@ import { } from '@mui/x-data-grid-pro'; import Portal from '@mui/material/Portal'; import { getBasicGridData } from '@mui/x-data-grid-generator'; -import { createRenderer, fireEvent, act, screen, waitFor } from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, act, screen } from '@mui/internal-test-utils'; import { getCell, getRow, spyApi } from 'test/utils/helperFn'; import { fireUserEvent } from 'test/utils/fireUserEvent'; @@ -910,15 +910,13 @@ describe(' - Row editing', () => { it('should call preProcessEditCellProps', async () => { const preProcessEditCellProps = spy(({ props }: GridPreProcessEditCellProps) => props); - render(); + const { user } = render(); const cell = getCell(0, 1); - fireUserEvent.mousePress(cell); - fireEvent.keyDown(cell, { key: 'Delete' }); + await user.click(cell); + await user.keyboard('{Delete}'); - await waitFor(() => { - expect(preProcessEditCellProps.callCount).to.equal(1); - }); + expect(preProcessEditCellProps.callCount).to.equal(1); expect(preProcessEditCellProps.lastCall.args[0].props).to.deep.equal({ value: '', diff --git a/packages/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx index 6344c9b898a82..9e77bdd73f7f7 100644 --- a/packages/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx @@ -12,7 +12,7 @@ import { GridColDef, } from '@mui/x-data-grid-pro'; import { getBasicGridData } from '@mui/x-data-grid-generator'; -import { createRenderer, fireEvent, screen, act, waitFor } from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act } from '@mui/internal-test-utils'; import { $, grid, @@ -742,7 +742,7 @@ describe(' - Row pinning', () => { testSkipIf(isJSDOM)('should support cell editing', async () => { const processRowUpdate = spy((row) => ({ ...row, currencyPair: 'USD-GBP' })); const columns: GridColDef[] = [{ field: 'id' }, { field: 'name', editable: true }]; - render( + const { user } = render(
- Row pinning', () => { ); const cell = getCell(0, 1); - fireEvent.doubleClick(cell); + await user.dblClick(cell); const input = cell.querySelector('input')!; - fireEvent.change(input, { target: { value: 'Marcus' } }); - fireEvent.keyDown(input, { key: 'Enter' }); + // remove the previous value before typing in the new one + // was "fireEvent.change(input, { target: { value: 'Marcus' } })" + await user.clear(input); + await user.type(input, 'Marcus'); + await user.keyboard('{Enter}'); - await waitFor(() => { - expect(cell.textContent).to.equal('Marcus'); - }); + expect(cell.textContent).to.equal('Marcus'); expect(processRowUpdate.callCount).to.equal(1); expect(processRowUpdate.lastCall.args[0]).to.deep.equal({ id: 3, name: 'Marcus' }); }); @@ -778,7 +779,7 @@ describe(' - Row pinning', () => { testSkipIf(isJSDOM)('should support row editing', async () => { const processRowUpdate = spy((row) => ({ ...row, currencyPair: 'USD-GBP' })); const columns: GridColDef[] = [{ field: 'id' }, { field: 'name', editable: true }]; - render( + const { user } = render(
- Row pinning', () => { ); const cell = getCell(0, 1); - fireEvent.doubleClick(cell); + await user.dblClick(cell); const input = cell.querySelector('input')!; - fireEvent.change(input, { target: { value: 'Marcus' } }); - fireEvent.keyDown(input, { key: 'Enter' }); + // remove the previous value before typing in the new one + // was "fireEvent.change(input, { target: { value: 'Marcus' } })" + await user.clear(input); + await user.type(input, 'Marcus'); + await user.keyboard('{Enter}'); - await waitFor(() => { - expect(cell.textContent).to.equal('Marcus'); - }); + expect(cell.textContent).to.equal('Marcus'); expect(processRowUpdate.callCount).to.equal(1); expect(processRowUpdate.lastCall.args[0]).to.deep.equal({ id: 3, name: 'Marcus' }); }); diff --git a/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx b/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx index d2fe4adf98538..8eb345f24470b 100644 --- a/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { createRenderer, screen, waitFor, within } from '@mui/internal-test-utils'; +import { createRenderer, screen, within } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { DataGrid } from '@mui/x-data-grid'; import { getColumnHeaderCell, getColumnHeadersTextContent } from 'test/utils/helperFn'; @@ -128,9 +128,7 @@ describe(' - Column headers', () => { expect(screen.queryByRole('menu')).not.to.equal(null); await user.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); - await waitFor(() => { - expect(screen.queryByRole('menu')).to.equal(null); - }); + expect(screen.queryByRole('menu')).to.equal(null); }); }); diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index 94b0c0493a625..87d31b6e557fc 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1157,7 +1157,7 @@ describe(' - Layout & warnings', () => { { field: 'username', width: 300 }, ]; - it('grid container', async () => { + it('grid container', () => { render(
@@ -1166,12 +1166,10 @@ describe(' - Layout & warnings', () => {
, ); - await waitFor(() => { - expect(grid('root')).toHaveComputedStyle({ width: '400px' }); - }); + expect(grid('root')).toHaveComputedStyle({ width: '400px' }); }); - it('flex container', async () => { + it('flex container', () => { render(
@@ -1180,9 +1178,7 @@ describe(' - Layout & warnings', () => {
, ); - await waitFor(() => { - expect(grid('root')).toHaveComputedStyle({ width: '400px' }); - }); + expect(grid('root')).toHaveComputedStyle({ width: '400px' }); }); }); diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index b41699bd13247..0cf9a067aaee9 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -251,7 +251,7 @@ describe(' - Row selection', () => { await user.click(checkboxInput!); - await waitFor(() => expect(getActiveCell()).to.equal('0-0')); + expect(getActiveCell()).to.equal('0-0'); }); it('should select all visible rows regardless of pagination', async () => { @@ -397,7 +397,7 @@ describe(' - Row selection', () => { expect(input2.checked).to.equal(true); }); - testSkipIf(isJSDOM)('should remove the selection from rows that are filtered out', async () => { + testSkipIf(isJSDOM)('should remove the selection from rows that are filtered out', () => { render( - Row selection', () => { fireEvent.change(screen.getByRole('spinbutton', { name: 'Value' }), { target: { value: 1 }, }); - await waitFor(() => { - // Previous selection is cleaned with only the filtered rows - expect(getSelectedRowIds()).to.deep.equal([1]); - }); + // Previous selection is cleaned with only the filtered rows + expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); @@ -439,9 +437,7 @@ describe(' - Row selection', () => { const selectAllCheckbox = screen.getByRole('checkbox', { name: 'Select all rows' }); fireEvent.click(selectAllCheckbox); - await waitFor(() => { - expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); - }); + expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); // Click on Menu in id header column @@ -455,15 +451,11 @@ describe(' - Row selection', () => { expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); fireEvent.click(selectAllCheckbox); // Unselect all - await waitFor(() => { - expect(getSelectedRowIds()).to.deep.equal([]); - }); + expect(getSelectedRowIds()).to.deep.equal([]); expect(grid('selectedRowCount')).to.equal(null); fireEvent.click(selectAllCheckbox); // Select all filtered rows - await waitFor(() => { - expect(getSelectedRowIds()).to.deep.equal([1]); - }); + expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); From a6f2d87cc80b194b45e65ac0c178ca9c520806df Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 13:32:26 +0200 Subject: [PATCH 12/34] Call `beforeAll` hooks to properly setup license and disable transitions in karma tests --- .../x-data-grid/src/tests/rowSelection.DataGrid.test.tsx | 6 +++--- test/karma.datagrid.tests.js | 4 ++++ test/karma.tests.js | 4 ++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 50322e561d7dc..cfd9422260581 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -397,8 +397,8 @@ describe(' - Row selection', () => { expect(input2.checked).to.equal(true); }); - testSkipIf(isJSDOM)('should remove the selection from rows that are filtered out', () => { - render( + testSkipIf(isJSDOM)('should remove the selection from rows that are filtered out', async () => { + const { user } = render( - Row selection', () => { />, ); const selectAllCheckbox = screen.getByRole('checkbox', { name: 'Select all rows' }); - fireEvent.click(selectAllCheckbox); + await user.click(selectAllCheckbox); expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); diff --git a/test/karma.datagrid.tests.js b/test/karma.datagrid.tests.js index 941ad1765d8e0..b073539a3d11b 100644 --- a/test/karma.datagrid.tests.js +++ b/test/karma.datagrid.tests.js @@ -6,6 +6,10 @@ import { createXMochaHooks } from './utils/mochaHooks'; const mochaHooks = createXMochaHooks(); +mochaHooks.beforeAll.forEach((mochaHook) => { + mochaHook.call(this); +}); + beforeEach(function beforeEachHook() { mochaHooks.beforeEach.forEach((mochaHook) => { mochaHook.call(this); diff --git a/test/karma.tests.js b/test/karma.tests.js index 2d2401669a76e..74d5423bf18a5 100644 --- a/test/karma.tests.js +++ b/test/karma.tests.js @@ -6,6 +6,10 @@ import { createXMochaHooks } from './utils/mochaHooks'; const mochaHooks = createXMochaHooks(); +mochaHooks.beforeAll.forEach((mochaHook) => { + mochaHook.call(this); +}); + beforeEach(function beforeEachHook() { mochaHooks.beforeEach.forEach((mochaHook) => { mochaHook.call(this); From f4b027b9edd63dbdb22e6a274bb260706176a19a Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 14:38:15 +0200 Subject: [PATCH 13/34] Fix tests --- .../src/tests/rowSelection.DataGrid.test.tsx | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index cfd9422260581..7f281f7efea97 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -2,7 +2,13 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { RefObject } from '@mui/x-internals/types'; -import { createRenderer, fireEvent, screen, act, waitFor } from '@mui/internal-test-utils'; +import { + createRenderer, + fireEvent, + screen, + act, + waitForElementToBeRemoved, +} from '@mui/internal-test-utils'; import { DataGrid, DataGridProps, @@ -11,7 +17,6 @@ import { GridEditModes, useGridApiRef, GridApi, - GridPreferencePanelsValue, GridRowSelectionModel, } from '@mui/x-data-grid'; import { @@ -397,64 +402,61 @@ describe(' - Row selection', () => { expect(input2.checked).to.equal(true); }); - testSkipIf(isJSDOM)('should remove the selection from rows that are filtered out', async () => { - const { user } = render( - , - ); + it('should remove the selection from rows that are filtered out', async () => { + let apiRef: RefObject; + function ControlCase() { + apiRef = useGridApiRef(); + return ; + } + const { user } = render(); const selectAllCheckbox = screen.getByRole('checkbox', { name: 'Select all rows' }); await user.click(selectAllCheckbox); expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); - fireEvent.change(screen.getByRole('spinbutton', { name: 'Value' }), { - target: { value: 1 }, + // open filter panel + await act(() => { + apiRef!.current?.showFilterPanel('id'); }); + await user.keyboard('1'); + + // wait until filtering is done + await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); // Previous selection is cleaned with only the filtered rows expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); it('should only select filtered items when "select all" is toggled after applying a filter', async () => { - render( - , - ); + let apiRef: RefObject; + function ControlCase() { + apiRef = useGridApiRef(); + return ; + } + const { user } = render(); const selectAllCheckbox = screen.getByRole('checkbox', { name: 'Select all rows' }); - fireEvent.click(selectAllCheckbox); + await user.click(selectAllCheckbox); expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); - // Click on Menu in id header column - fireEvent.change(screen.getByRole('spinbutton', { name: 'Value' }), { - target: { value: 1 }, - }); - await waitFor(() => { - // Previous selection is cleared and only the filtered row is selected - expect(getSelectedRowIds()).to.deep.equal([1]); + // open filter panel + await act(() => { + apiRef!.current?.showFilterPanel('id'); }); + await user.keyboard('1'); + + // wait until filtering is done + await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); + // Previous selection is cleared and only the filtered row is selected + expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); - fireEvent.click(selectAllCheckbox); // Unselect all + await user.click(selectAllCheckbox); // Unselect all expect(getSelectedRowIds()).to.deep.equal([]); expect(grid('selectedRowCount')).to.equal(null); - fireEvent.click(selectAllCheckbox); // Select all filtered rows + await user.click(selectAllCheckbox); // Select all filtered rows expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); From 7c15df75eb5b02a6cf3a4d96bac43d70eaaf4335 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 15:10:02 +0200 Subject: [PATCH 14/34] Fix the fix of tests :D --- .../src/tests/rowSelection.DataGrid.test.tsx | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 7f281f7efea97..d1a7f8caf1cca 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -2,13 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { RefObject } from '@mui/x-internals/types'; -import { - createRenderer, - fireEvent, - screen, - act, - waitForElementToBeRemoved, -} from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act, waitFor } from '@mui/internal-test-utils'; import { DataGrid, DataGridProps, @@ -420,10 +414,10 @@ describe(' - Row selection', () => { }); await user.keyboard('1'); - // wait until filtering is done - await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); - // Previous selection is cleaned with only the filtered rows - expect(getSelectedRowIds()).to.deep.equal([1]); + await waitFor(() => { + // Previous selection is cleaned with only the filtered rows + expect(getSelectedRowIds()).to.deep.equal([1]); + }); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); @@ -446,10 +440,10 @@ describe(' - Row selection', () => { }); await user.keyboard('1'); - // wait until filtering is done - await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); - // Previous selection is cleared and only the filtered row is selected - expect(getSelectedRowIds()).to.deep.equal([1]); + await waitFor(() => { + // Previous selection is cleaned with only the filtered rows + expect(getSelectedRowIds()).to.deep.equal([1]); + }); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); await user.click(selectAllCheckbox); // Unselect all From fcf61b8e9d80b849b7fbd0a093880e02a3ca171b Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 15:10:43 +0200 Subject: [PATCH 15/34] brainfart --- packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index d1a7f8caf1cca..f08be9c616149 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -441,7 +441,7 @@ describe(' - Row selection', () => { await user.keyboard('1'); await waitFor(() => { - // Previous selection is cleaned with only the filtered rows + // Previous selection is cleared and only the filtered row is selected expect(getSelectedRowIds()).to.deep.equal([1]); }); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); From a30bdc4403c1232dd0cd205ea9056eb296a9c2fc Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 15:49:20 +0200 Subject: [PATCH 16/34] Ensure the filter panel is opened before entering filter value --- packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index f08be9c616149..e04fdc43b484e 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -412,6 +412,7 @@ describe(' - Row selection', () => { await act(() => { apiRef!.current?.showFilterPanel('id'); }); + await waitFor(() => expect(screen.queryByRole('tooltip')).not.to.equal(null)); await user.keyboard('1'); await waitFor(() => { @@ -438,6 +439,7 @@ describe(' - Row selection', () => { await act(() => { apiRef!.current?.showFilterPanel('id'); }); + await waitFor(() => expect(screen.queryByRole('tooltip')).not.to.equal(null)); await user.keyboard('1'); await waitFor(() => { From 1efc333b99fd9d0ca31100ee1fd2eea3b7285c6e Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 16:36:31 +0200 Subject: [PATCH 17/34] Try more assertions --- .../src/tests/rowSelection.DataGrid.test.tsx | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index e04fdc43b484e..f248d5e5c9f49 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -2,7 +2,14 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { RefObject } from '@mui/x-internals/types'; -import { createRenderer, fireEvent, screen, act, waitFor } from '@mui/internal-test-utils'; +import { + createRenderer, + fireEvent, + screen, + act, + waitFor, + waitForElementToBeRemoved, +} from '@mui/internal-test-utils'; import { DataGrid, DataGridProps, @@ -413,12 +420,14 @@ describe(' - Row selection', () => { apiRef!.current?.showFilterPanel('id'); }); await waitFor(() => expect(screen.queryByRole('tooltip')).not.to.equal(null)); + await user.keyboard('1'); + expect(screen.queryByTestId('LoadIcon')).not.to.equal(null); - await waitFor(() => { - // Previous selection is cleaned with only the filtered rows - expect(getSelectedRowIds()).to.deep.equal([1]); - }); + await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); + + // Previous selection is cleaned with only the filtered rows + expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); @@ -440,12 +449,14 @@ describe(' - Row selection', () => { apiRef!.current?.showFilterPanel('id'); }); await waitFor(() => expect(screen.queryByRole('tooltip')).not.to.equal(null)); + await user.keyboard('1'); + expect(screen.queryByTestId('LoadIcon')).not.to.equal(null); - await waitFor(() => { - // Previous selection is cleared and only the filtered row is selected - expect(getSelectedRowIds()).to.deep.equal([1]); - }); + await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); + + // Previous selection is cleared and only the filtered row is selected + expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); await user.click(selectAllCheckbox); // Unselect all From da44c19b4ee490d10ba5e6e18afac64f5424d4f3 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 16:54:20 +0200 Subject: [PATCH 18/34] Make assertions properly async --- .../x-data-grid/src/tests/rowSelection.DataGrid.test.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index f248d5e5c9f49..231022449633b 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -7,7 +7,6 @@ import { fireEvent, screen, act, - waitFor, waitForElementToBeRemoved, } from '@mui/internal-test-utils'; import { @@ -419,10 +418,10 @@ describe(' - Row selection', () => { await act(() => { apiRef!.current?.showFilterPanel('id'); }); - await waitFor(() => expect(screen.queryByRole('tooltip')).not.to.equal(null)); + expect(await screen.findByRole('tooltip')).not.to.equal(null); await user.keyboard('1'); - expect(screen.queryByTestId('LoadIcon')).not.to.equal(null); + expect(await screen.findByTestId('LoadIcon')).not.to.equal(null); await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); @@ -448,10 +447,10 @@ describe(' - Row selection', () => { await act(() => { apiRef!.current?.showFilterPanel('id'); }); - await waitFor(() => expect(screen.queryByRole('tooltip')).not.to.equal(null)); + expect(await screen.findByRole('tooltip')).not.to.equal(null); await user.keyboard('1'); - expect(screen.queryByTestId('LoadIcon')).not.to.equal(null); + expect(await screen.findByTestId('LoadIcon')).not.to.equal(null); await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); From d8e765c4443c87c5550ca4a675a4839363d17c09 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 17:32:20 +0200 Subject: [PATCH 19/34] Try async expected DOM assertions --- .../src/tests/rowSelection.DataGrid.test.tsx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 231022449633b..099514b32ddbd 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -2,13 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { RefObject } from '@mui/x-internals/types'; -import { - createRenderer, - fireEvent, - screen, - act, - waitForElementToBeRemoved, -} from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act } from '@mui/internal-test-utils'; import { DataGrid, DataGridProps, @@ -421,13 +415,11 @@ describe(' - Row selection', () => { expect(await screen.findByRole('tooltip')).not.to.equal(null); await user.keyboard('1'); - expect(await screen.findByTestId('LoadIcon')).not.to.equal(null); - await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); + expect(await screen.findByText('1 row selected')).not.to.equal(null); // Previous selection is cleaned with only the filtered rows expect(getSelectedRowIds()).to.deep.equal([1]); - expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); it('should only select filtered items when "select all" is toggled after applying a filter', async () => { @@ -450,13 +442,11 @@ describe(' - Row selection', () => { expect(await screen.findByRole('tooltip')).not.to.equal(null); await user.keyboard('1'); - expect(await screen.findByTestId('LoadIcon')).not.to.equal(null); - await waitForElementToBeRemoved(() => screen.queryByTestId('LoadIcon')); + expect(await screen.findByText('1 row selected')).not.to.equal(null); // Previous selection is cleared and only the filtered row is selected expect(getSelectedRowIds()).to.deep.equal([1]); - expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); await user.click(selectAllCheckbox); // Unselect all expect(getSelectedRowIds()).to.deep.equal([]); From 2a48064319c66bf7760def7b4e7118b0445c1d10 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 17:50:24 +0200 Subject: [PATCH 20/34] Keep `waitFor` for a flaky test --- .../src/tests/detailPanel.DataGridPro.test.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx index c9653c2cf92b6..b674feba8ef9e 100644 --- a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx @@ -12,7 +12,14 @@ import { GRID_DETAIL_PANEL_TOGGLE_FIELD, } from '@mui/x-data-grid-pro'; import { useBasicDemoData } from '@mui/x-data-grid-generator'; -import { createRenderer, fireEvent, screen, act, reactMajor } from '@mui/internal-test-utils'; +import { + createRenderer, + fireEvent, + screen, + waitFor, + act, + reactMajor, +} from '@mui/internal-test-utils'; import { $, $$, grid, getRow, getCell, getColumnValues, microtasks } from 'test/utils/helperFn'; import { fireUserEvent } from 'test/utils/fireUserEvent'; import { testSkipIf, isJSDOM } from 'test/utils/skipIf'; @@ -138,7 +145,9 @@ describe(' - Detail panel', () => { await user.click(screen.getByRole('button', { name: 'Increase' })); - expect(virtualScrollerContent).toHaveComputedStyle({ height: `${rowHeight + 200}px` }); + await waitFor(() => { + expect(virtualScrollerContent).toHaveComputedStyle({ height: `${rowHeight + 200}px` }); + }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); expect(detailPanels[0]).toHaveComputedStyle({ From 40d8eb928725643fc5890ce1c4b42ece42fb4948 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 28 Jan 2025 18:03:31 +0200 Subject: [PATCH 21/34] Refactor --- .../src/tests/rowSelection.DataGrid.test.tsx | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 099514b32ddbd..748dc4b5cfdab 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { RefObject } from '@mui/x-internals/types'; -import { createRenderer, fireEvent, screen, act } from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act, waitFor } from '@mui/internal-test-utils'; import { DataGrid, DataGridProps, @@ -413,13 +413,16 @@ describe(' - Row selection', () => { apiRef!.current?.showFilterPanel('id'); }); expect(await screen.findByRole('tooltip')).not.to.equal(null); - + await act(async () => { + screen.getByRole('spinbutton', { name: 'Value' }).focus(); + }); await user.keyboard('1'); - expect(await screen.findByText('1 row selected')).not.to.equal(null); - - // Previous selection is cleaned with only the filtered rows - expect(getSelectedRowIds()).to.deep.equal([1]); + await waitFor(() => { + // Previous selection is cleaned with only the filtered rows + expect(getSelectedRowIds()).to.deep.equal([1]); + }); + expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); it('should only select filtered items when "select all" is toggled after applying a filter', async () => { @@ -440,13 +443,16 @@ describe(' - Row selection', () => { apiRef!.current?.showFilterPanel('id'); }); expect(await screen.findByRole('tooltip')).not.to.equal(null); - + await act(async () => { + screen.getByRole('spinbutton', { name: 'Value' }).focus(); + }); await user.keyboard('1'); - expect(await screen.findByText('1 row selected')).not.to.equal(null); - - // Previous selection is cleared and only the filtered row is selected - expect(getSelectedRowIds()).to.deep.equal([1]); + await waitFor(() => { + // Previous selection is cleared and only the filtered row is selected + expect(getSelectedRowIds()).to.deep.equal([1]); + }); + expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); await user.click(selectAllCheckbox); // Unselect all expect(getSelectedRowIds()).to.deep.equal([]); From e82a6959491c471a4052be44cbf312f7896b1189 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 29 Jan 2025 00:07:20 +0200 Subject: [PATCH 22/34] Try `user.type` --- .../src/tests/rowSelection.DataGrid.test.tsx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 748dc4b5cfdab..d1b06a72f0307 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -413,10 +413,8 @@ describe(' - Row selection', () => { apiRef!.current?.showFilterPanel('id'); }); expect(await screen.findByRole('tooltip')).not.to.equal(null); - await act(async () => { - screen.getByRole('spinbutton', { name: 'Value' }).focus(); - }); - await user.keyboard('1'); + + await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); await waitFor(() => { // Previous selection is cleaned with only the filtered rows @@ -443,10 +441,8 @@ describe(' - Row selection', () => { apiRef!.current?.showFilterPanel('id'); }); expect(await screen.findByRole('tooltip')).not.to.equal(null); - await act(async () => { - screen.getByRole('spinbutton', { name: 'Value' }).focus(); - }); - await user.keyboard('1'); + + await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); await waitFor(() => { // Previous selection is cleared and only the filtered row is selected From 78a49b54648896e99714581dcda094a381c318c7 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 29 Jan 2025 09:43:23 +0200 Subject: [PATCH 23/34] Try assertion for active filter --- .../src/tests/rowSelection.DataGrid.test.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index d1b06a72f0307..2af40ef9cdf1f 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -417,9 +417,10 @@ describe(' - Row selection', () => { await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); await waitFor(() => { - // Previous selection is cleaned with only the filtered rows - expect(getSelectedRowIds()).to.deep.equal([1]); + expect(screen.queryByLabelText('1 active filter')).not.to.equal(null); }); + // Previous selection is cleared and only the filtered row is selected + expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); @@ -445,9 +446,10 @@ describe(' - Row selection', () => { await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); await waitFor(() => { - // Previous selection is cleared and only the filtered row is selected - expect(getSelectedRowIds()).to.deep.equal([1]); + expect(screen.queryByLabelText('1 active filter')).not.to.equal(null); }); + // Previous selection is cleared and only the filtered row is selected + expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); await user.click(selectAllCheckbox); // Unselect all From 1daa8c313d96ad5b4694226844d476fa4c4cefee Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 29 Jan 2025 11:29:05 +0200 Subject: [PATCH 24/34] Use `findBy` instead of `waitFor` --- .../x-data-grid/src/tests/rowSelection.DataGrid.test.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 2af40ef9cdf1f..7123455b17329 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -416,9 +416,7 @@ describe(' - Row selection', () => { await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); - await waitFor(() => { - expect(screen.queryByLabelText('1 active filter')).not.to.equal(null); - }); + expect(await screen.findByLabelText('1 active filter')).not.to.equal(null); // Previous selection is cleared and only the filtered row is selected expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); @@ -445,9 +443,7 @@ describe(' - Row selection', () => { await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); - await waitFor(() => { - expect(screen.queryByLabelText('1 active filter')).not.to.equal(null); - }); + expect(await screen.findByLabelText('1 active filter')).not.to.equal(null); // Previous selection is cleared and only the filtered row is selected expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); From 8a87dbf3be36915fa00805f9ff0704c1096d3bf0 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 29 Jan 2025 11:52:41 +0200 Subject: [PATCH 25/34] Try with `skipClick` --- .../x-data-grid/src/tests/rowSelection.DataGrid.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 7123455b17329..decdaed5791bc 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { RefObject } from '@mui/x-internals/types'; -import { createRenderer, fireEvent, screen, act, waitFor } from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act } from '@mui/internal-test-utils'; import { DataGrid, DataGridProps, @@ -414,7 +414,7 @@ describe(' - Row selection', () => { }); expect(await screen.findByRole('tooltip')).not.to.equal(null); - await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); + await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1', { skipClick: true }); expect(await screen.findByLabelText('1 active filter')).not.to.equal(null); // Previous selection is cleared and only the filtered row is selected @@ -441,7 +441,7 @@ describe(' - Row selection', () => { }); expect(await screen.findByRole('tooltip')).not.to.equal(null); - await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1'); + await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1', { skipClick: true }); expect(await screen.findByLabelText('1 active filter')).not.to.equal(null); // Previous selection is cleared and only the filtered row is selected From 3a97908a26f09ad0990840215770bc16a64c47cc Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 29 Jan 2025 12:08:07 +0200 Subject: [PATCH 26/34] Revert test to original behavior --- .../src/tests/rowSelection.DataGrid.test.tsx | 92 ++++++++++--------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index decdaed5791bc..b39198bfbf85a 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { RefObject } from '@mui/x-internals/types'; -import { createRenderer, fireEvent, screen, act } from '@mui/internal-test-utils'; +import { createRenderer, fireEvent, screen, act, waitFor } from '@mui/internal-test-utils'; import { DataGrid, DataGridProps, @@ -11,6 +11,7 @@ import { GridEditModes, useGridApiRef, GridApi, + GridPreferencePanelsValue, GridRowSelectionModel, } from '@mui/x-data-grid'; import { @@ -396,64 +397,73 @@ describe(' - Row selection', () => { expect(input2.checked).to.equal(true); }); - it('should remove the selection from rows that are filtered out', async () => { - let apiRef: RefObject; - function ControlCase() { - apiRef = useGridApiRef(); - return ; - } - const { user } = render(); + testSkipIf(isJSDOM)('should remove the selection from rows that are filtered out', async () => { + render( + , + ); const selectAllCheckbox = screen.getByRole('checkbox', { name: 'Select all rows' }); - await user.click(selectAllCheckbox); + fireEvent.click(selectAllCheckbox); expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); - // open filter panel - await act(() => { - apiRef!.current?.showFilterPanel('id'); + fireEvent.change(screen.getByRole('spinbutton', { name: 'Value' }), { + target: { value: 1 }, + }); + await waitFor(() => { + // Previous selection is cleaned with only the filtered rows + expect(getSelectedRowIds()).to.deep.equal([1]); }); - expect(await screen.findByRole('tooltip')).not.to.equal(null); - - await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1', { skipClick: true }); - - expect(await screen.findByLabelText('1 active filter')).not.to.equal(null); - // Previous selection is cleared and only the filtered row is selected - expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); it('should only select filtered items when "select all" is toggled after applying a filter', async () => { - let apiRef: RefObject; - function ControlCase() { - apiRef = useGridApiRef(); - return ; - } - const { user } = render(); + render( + , + ); const selectAllCheckbox = screen.getByRole('checkbox', { name: 'Select all rows' }); - await user.click(selectAllCheckbox); - expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); + fireEvent.click(selectAllCheckbox); + await waitFor(() => { + expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); + }); expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); - // open filter panel - await act(() => { - apiRef!.current?.showFilterPanel('id'); + // Click on Menu in id header column + fireEvent.change(screen.getByRole('spinbutton', { name: 'Value' }), { + target: { value: 1 }, + }); + await waitFor(() => { + // Previous selection is cleared and only the filtered row is selected + expect(getSelectedRowIds()).to.deep.equal([1]); }); - expect(await screen.findByRole('tooltip')).not.to.equal(null); - - await user.type(screen.getByRole('spinbutton', { name: 'Value' }), '1', { skipClick: true }); - - expect(await screen.findByLabelText('1 active filter')).not.to.equal(null); - // Previous selection is cleared and only the filtered row is selected - expect(getSelectedRowIds()).to.deep.equal([1]); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); - await user.click(selectAllCheckbox); // Unselect all - expect(getSelectedRowIds()).to.deep.equal([]); + fireEvent.click(selectAllCheckbox); // Unselect all + await waitFor(() => { + expect(getSelectedRowIds()).to.deep.equal([]); + }); expect(grid('selectedRowCount')).to.equal(null); - await user.click(selectAllCheckbox); // Select all filtered rows - expect(getSelectedRowIds()).to.deep.equal([1]); + fireEvent.click(selectAllCheckbox); // Select all filtered rows + await waitFor(() => { + expect(getSelectedRowIds()).to.deep.equal([1]); + }); expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); }); From 5458de45b285b924ec8a74bdd64b2dfe9a586d3e Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 29 Jan 2025 12:47:41 +0200 Subject: [PATCH 27/34] Revert test change to maybe avoid flakiness --- .../tests/dataSourceAggregation.DataGridPremium.test.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx index 9531d610b5c7d..70aca110ddb35 100644 --- a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { RefObject } from '@mui/x-internals/types'; import { useMockServer } from '@mui/x-data-grid-generator'; -import { createRenderer, screen, waitFor, within } from '@mui/internal-test-utils'; +import { createRenderer, waitFor, screen, within } from '@mui/internal-test-utils'; import { expect } from 'chai'; import { DataGridPremium, @@ -99,7 +99,9 @@ describe(' - Data source aggregation', () => { it('should show aggregation option in the column menu', async () => { const { user } = render(); - expect(getRowsSpy.callCount).to.be.greaterThan(0); + await waitFor(() => { + expect(getRowsSpy.callCount).to.be.greaterThan(0); + }); await user.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); expect(screen.queryByLabelText('Aggregation')).not.to.equal(null); }); From 49ba6d5bfa6bc7e08f0b946bb6037ac5c7a58df2 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 29 Jan 2025 13:57:56 +0200 Subject: [PATCH 28/34] Try the failing assertion in async method --- .../tests/dataSourceAggregation.DataGridPremium.test.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx index 70aca110ddb35..da2fdfa1400e4 100644 --- a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx @@ -99,11 +99,9 @@ describe(' - Data source aggregation', () => { it('should show aggregation option in the column menu', async () => { const { user } = render(); - await waitFor(() => { - expect(getRowsSpy.callCount).to.be.greaterThan(0); - }); + expect(getRowsSpy.callCount).to.be.greaterThan(0); await user.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); - expect(screen.queryByLabelText('Aggregation')).not.to.equal(null); + expect(await screen.findByLabelText('Aggregation')).not.to.equal(null); }); it('should not show aggregation option in the column menu when no aggregation function is defined', async () => { From 6cfb5314995852d4d56064e54dbce47d5341292c Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 30 Jan 2025 09:59:45 +0200 Subject: [PATCH 29/34] Move config to `beforeEach` --- .../dataSourceAggregation.DataGridPremium.test.tsx | 2 +- test/karma.datagrid.tests.js | 4 ---- test/karma.tests.js | 4 ---- test/utils/mochaHooks.js | 11 +++++------ 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx index 5af3c4a89c859..a8811e1f5c05d 100644 --- a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx @@ -115,7 +115,7 @@ describe(' - Data source aggregation', () => { expect(screen.queryByLabelText('Aggregation')).to.equal(null); }); - it('should provide the `aggregationModel` in the `getRows` params', () => { + it('should provide the `aggregationModel` in the `getRows` params', async () => { render( { - mochaHook.call(this); -}); - beforeEach(function beforeEachHook() { mochaHooks.beforeEach.forEach((mochaHook) => { mochaHook.call(this); diff --git a/test/karma.tests.js b/test/karma.tests.js index 74d5423bf18a5..2d2401669a76e 100644 --- a/test/karma.tests.js +++ b/test/karma.tests.js @@ -6,10 +6,6 @@ import { createXMochaHooks } from './utils/mochaHooks'; const mochaHooks = createXMochaHooks(); -mochaHooks.beforeAll.forEach((mochaHook) => { - mochaHook.call(this); -}); - beforeEach(function beforeEachHook() { mochaHooks.beforeEach.forEach((mochaHook) => { mochaHook.call(this); diff --git a/test/utils/mochaHooks.js b/test/utils/mochaHooks.js index 4dd89eac557b3..5c37886ca4e36 100644 --- a/test/utils/mochaHooks.js +++ b/test/utils/mochaHooks.js @@ -18,14 +18,14 @@ export function createXMochaHooks(coreMochaHooks = {}) { let licenseKey; mochaHooks.beforeAll.push(function func() { - // disable "react-transition-group" transitions - // https://reactcommunity.org/react-transition-group/testing/ - config.disabled = true; licenseKey = generateTestLicenseKey(); }); - mochaHooks.beforeEach.push(function setupLicenseKey() { + mochaHooks.beforeEach.push(function setupCommon() { setupTestLicenseKey(licenseKey); + // disable "react-transition-group" transitions + // https://reactcommunity.org/react-transition-group/testing/ + config.disabled = true; }); mochaHooks.afterEach.push(function resetCleanupTracking() { @@ -40,8 +40,7 @@ export function createXMochaHooks(coreMochaHooks = {}) { }); mochaHooks.afterEach.push(clearWarningsCache); - - mochaHooks.afterAll.push(function restoreTransition() { + mochaHooks.afterEach.push(function resetCommon() { config.disabled = false; }); From 4cac57deef7347b049d4fd7faa78042098c1162c Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 30 Jan 2025 12:55:27 +0200 Subject: [PATCH 30/34] Code review: Jan --- .../src/tests/rowGrouping.DataGridPremium.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx index 22c645a89b72b..e3249649030a6 100644 --- a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx @@ -2892,7 +2892,7 @@ describe(' - Row grouping', () => { />, ); - await act(() => { + await act(async () => { apiRef.current?.updateRows([{ id: 1, group: 'A', username: 'username 2' }]); }); @@ -2911,7 +2911,7 @@ describe(' - Row grouping', () => { await user.click(screen.getByRole('button', { name: 'see children' })); - await act(() => { + await act(async () => { apiRef.current?.updateRows([{ id: 1, group: 'A', username: 'username 2' }]); }); @@ -2936,7 +2936,7 @@ describe(' - Row grouping', () => { expect(getColumnValues(3)).to.deep.equal(['', 'username1', 'username2']); // trigger row update without any changes in row data - await act(() => { + await act(async () => { apiRef.current?.updateRows([{ id: 1 }]); }); From d92ea56c277dfc03951c319b7467ab355df9531c Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 30 Jan 2025 12:55:39 +0200 Subject: [PATCH 31/34] A few flaky refactors --- .../src/tests/keyboard.DataGrid.test.tsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx b/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx index 826c9a19f04bc..0185daac91bf4 100644 --- a/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx @@ -639,7 +639,7 @@ describe(' - Keyboard', () => { expect(handleKeyDown.returnValues).to.deep.equal([true]); }); - it('should sort column when pressing enter and column header is selected', () => { + it('should sort column when pressing enter and column header is selected', async () => { const columns = [ { field: 'id', @@ -660,17 +660,19 @@ describe(' - Keyboard', () => { }, ]; - render( + const { user } = render(
, ); - act(() => getColumnHeaderCell(0).focus()); + await act(() => { + getColumnHeaderCell(0).focus(); + }); expect(getActiveColumnHeader()).to.equal('0'); expect(getColumnValues(1)).to.deep.equal(['John', 'Doe']); - fireEvent.keyDown(getColumnHeaderCell(0), { key: 'Enter' }); - fireEvent.keyDown(getColumnHeaderCell(0), { key: 'Enter' }); + await user.keyboard('{Enter}'); + await user.keyboard('{Enter}'); expect(getColumnValues(1)).to.deep.equal(['Doe', 'John']); }); @@ -702,25 +704,24 @@ describe(' - Keyboard', () => { expect(renderCell.callCount).to.equal(4); }); - it('should not scroll horizontally when cell is wider than viewport', () => { + it('should not scroll horizontally when cell is wider than viewport', async () => { const columns = [{ field: 'id', width: 400 }, { field: 'name' }]; const rows = [ { id: 1, name: 'John' }, { id: 2, name: 'Doe' }, ]; - render( + const { user } = render(
, ); const virtualScroller = document.querySelector('.MuiDataGrid-virtualScroller')!; - const firstCell = getCell(0, 0); - fireUserEvent.mousePress(firstCell); + await user.click(getCell(0, 0)); expect(virtualScroller.scrollLeft).to.equal(0); - fireEvent.keyDown(firstCell, { key: 'ArrowDown' }); + await user.keyboard('{ArrowDown}'); expect(virtualScroller.scrollLeft).to.equal(0); }); From 6dc13302c4a949fa8d5e1458db49e1dadbd73868 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 30 Jan 2025 15:23:40 +0200 Subject: [PATCH 32/34] Address another flaky test --- .../x-data-grid/src/tests/keyboard.DataGrid.test.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx b/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx index 0185daac91bf4..fc523981c77f8 100644 --- a/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx @@ -622,20 +622,19 @@ describe(' - Keyboard', () => { }); }); - it('should call preventDefault when using keyboard navigation', () => { + it('should call preventDefault when using keyboard navigation', async () => { const handleKeyDown = spy((event) => event.defaultPrevented); const columns = [{ field: 'id' }, { field: 'name' }]; const rows = [{ id: 1, name: 'John' }]; - render( + const { user } = render(
, ); - const firstCell = getCell(0, 0); - fireUserEvent.mousePress(firstCell); - fireEvent.keyDown(firstCell, { key: 'ArrowRight' }); + await user.click(getCell(0, 0)); + await user.keyboard('{ArrowRight}'); expect(handleKeyDown.returnValues).to.deep.equal([true]); }); @@ -666,7 +665,7 @@ describe(' - Keyboard', () => {
, ); - await act(() => { + await act(async () => { getColumnHeaderCell(0).focus(); }); expect(getActiveColumnHeader()).to.equal('0'); From ee62e4d5c94d59a022838613ccfe4637ca955be4 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 30 Jan 2025 16:05:14 +0200 Subject: [PATCH 33/34] Revert change --- .../tests/dataSourceAggregation.DataGridPremium.test.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx index f4102a32079f2..c96c589ce3ad2 100644 --- a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx @@ -157,7 +157,7 @@ describe(' - Data source aggregation', () => { expect(footerRow?.id).to.deep.equal({ position: 'footer', value: 10 }); }); - it('should derive the aggregation values using `dataSource.getAggregatedValue`', () => { + it('should derive the aggregation values using `dataSource.getAggregatedValue`', async () => { const getAggregatedValue = () => 'Agg value'; render( - Data source aggregation', () => { getAggregatedValue={getAggregatedValue} />, ); - expect(Object.keys(apiRef.current!.state.aggregation.lookup).length).to.be.greaterThan(0); + await waitFor(() => { + expect(Object.keys(apiRef.current!.state.aggregation.lookup).length).to.be.greaterThan(0); + }); expect(apiRef.current?.state.aggregation.lookup[GRID_ROOT_GROUP_ID].id.value).to.equal( 'Agg value', ); From d05549ac06e9230e8e27a615432e526584d0202a Mon Sep 17 00:00:00 2001 From: Lukas Tyla Date: Fri, 31 Jan 2025 12:43:30 +0200 Subject: [PATCH 34/34] Update packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx Co-authored-by: Jan Potoms <2109932+Janpot@users.noreply.github.com> Signed-off-by: Lukas Tyla --- .../src/tests/editComponents.DataGridPro.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx index c3492389cec9f..cd53cd71d0bfe 100644 --- a/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/editComponents.DataGridPro.test.tsx @@ -599,7 +599,7 @@ describe(' - Edit components', () => { await user.dblClick(cell); await user.click(screen.queryAllByRole('option')[1]); expect(screen.queryByRole('listbox')).to.equal(null); - await act(() => { + await act(async () => { screen.getByRole('combobox').focus(); }); await user.keyboard('{Enter}');