Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[test] Fix flaky data source tests in DataGrid #16395

Merged
merged 11 commits into from
Jan 30, 2025

Conversation

lauri865
Copy link
Contributor

@lauri865 lauri865 commented Jan 29, 2025

Randomly failing datasource tests have given me so much grief. It seems like there's a timing issue with useMockServer and datasource tests. I'm not 100% sure if I got to the bottom of it, but the problem is somewhere in useMockServer initialisation (doesn't happen synchronously), so every time fetchRows function reference changes, fetchRowSpy gets reset, but there could be timing issues still where previous fetches happen after fetchRowSpy has been reset, but fetch comes in later.

With delayed mounting, and waiting for mockServer, we now have to deal with StrictMode as well, since they don't get reset anymore in the useMemo that also runs twice (at least). Added a monkeypatch for now (a component) to see the actual problematic tests, since I didn't want to meddle with every single test.

Ideally fetchRowSpy should only be reset once per test, or within the test itself, not within the component lifecycle, otherwise these tests can be very flaky. I think for testing purposes, it would be better if mockServer wasn't a hook.

However, now we also have to deal with StrictMode fetches, since with delayed rendering, on mount it will fetch twice (always has, but previously it was reset in useMemo that also runs twice, at least, sometimes more).

Edit: fixed the tests.

@mui-bot
Copy link

mui-bot commented Jan 29, 2025

Deploy preview: https://deploy-preview-16395--material-ui-x.netlify.app/

Generated by 🚫 dangerJS against 4ca68a2

let mockServer: ReturnType<typeof useMockServer>;

// TODO: Resets strictmode calls, need to find a better fix for this, maybe an AbortController?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also be in favor of removing strict mode.

Copy link
Contributor Author

@lauri865 lauri865 Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if you know this, but useGridRegisterPipeProcessor is semi-broken in StrictMode. We can't control whether developers use StrictMode though, so turning it off doesn't just fix it.

  1. StrictMode call – invokes useFirstRender (it will only invoke the callback in StrictMode, since the isFirstRender ref doesn't restore, and we cannot restore it back)
  2. StrictMode call – runs useEffect in useGridRegisterPipeProcessor, that sets isFirstRender to false, and returns cleanup, that will remove the processor at the end of StrictMode invocation
  3. Normal call – useFirstRender has no effect, but processor is cleaned up
  4. Normal call – Processor is re-added only in useEffect, so anything that calls it before (even in useEffect level, but from previous hooks), it fails. Which is the reason why I reordered the hooks in useDatagridPremiumComponents

I'm not sure what a good fix is, besides following the rules of react, and do it in a simple useLayoutEffect to minimise the importance of ordering hooks.

We could prevent returning a cleanup function if isFirstRender is true, but then the processor never gets cleaned up without StrictMode, if it only registers once. Which may or may not be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@MBilalShafi MBilalShafi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

useGridAggregation(apiRef, props);
useGridDataSource(apiRef, props);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing this order in this PR to fix another bug, this change might be skipped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine as long as it comes after useGridAggregation, but if we fix the below, then the order won't matter (for this use case at least):
#16395 (comment)

@@ -367,5 +368,6 @@ export const useMockServer = (
loadNewData: () => {
setIndex((oldIndex) => oldIndex + 1);
},
isReady: Boolean(data?.rows?.length),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could probably be used in the demos too, let's leave it for later though.
Side note: When doing loadNewData it might not convey the correct information initially since the previous data would be there but outdated, isn't much of a problem though since updating the fetchRows would reset the dataSource retriggering a fetch call anyways.

@lauri865 lauri865 force-pushed the break-datasource-tests branch from bc0dbca to e3985e1 Compare January 30, 2025 09:46
@lauri865
Copy link
Contributor Author

lauri865 commented Jan 30, 2025

@MBilalShafi, I force pushed over the last change, since I fixed the root cause why the test failed – it was a completely valid failure. Throttling was never cleaned up, which caused race conditions when changing models (throttled renderedRowsIntervalChanged was called with stale params after sortModel changed). Try to avoid using greaterThan for fetch calls, that will just allow for mistakes. Using useGridSelector for state selectors was also potentially causing issues, so I refactored those.

Your commit, if you want to reincorporate any of those changes:
bc0dbca

It's not the first time throttling has caused issues, so I suggest creating a custom hook that takes care of cleanups. Easy to forget otherwise with manual implementations each time.

@MBilalShafi
Copy link
Member

MBilalShafi commented Jan 30, 2025

Try to avoid using greaterThan for fetch calls, that will just allow for mistakes.

Absolutely, I also started looking into the root cause, you got it first.
Much appreciated 👍

@MBilalShafi MBilalShafi force-pushed the break-datasource-tests branch from 127aa5b to c94cecf Compare January 30, 2025 10:14
Copy link
Member

@MBilalShafi MBilalShafi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let's see if @arminmeh has to add something

@arminmeh
Copy link
Contributor

Looks good. Thanks for the improvements
Maybe Reset component could be extracted, but it can also be done later

@arminmeh arminmeh changed the title [data grid] Fix flaky data source tests [test] Fix flaky data source tests in DataGrid Jan 30, 2025
@arminmeh arminmeh added test component: data grid This is the name of the generic UI component, not the React module! needs cherry-pick The PR should be cherry-picked to master after merge v7.x labels Jan 30, 2025
@lauri865
Copy link
Contributor Author

Can you please merge please @MBilalShafi? 🙏

@arminmeh arminmeh merged commit 1ea3ae2 into mui:master Jan 30, 2025
18 checks passed
Copy link

Cherry-pick PRs will be created targeting branches: v7.x

arminmeh added a commit to arminmeh/mui-x that referenced this pull request Jan 30, 2025
@arminmeh
Copy link
Contributor

Cherry-pick failed, so I have added the changes manually to #16382

A-s-h-o-k pushed a commit to A-s-h-o-k/mui-x that referenced this pull request Feb 4, 2025
Co-authored-by: Bilal Shafi <bilalshafidev@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: data grid This is the name of the generic UI component, not the React module! needs cherry-pick The PR should be cherry-picked to master after merge test v7.x
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants