-
Notifications
You must be signed in to change notification settings - Fork 46
QueryClientProvider refactor #544
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
base: main
Are you sure you want to change the base?
Conversation
const { rerender } = renderHookWithProviders( | ||
({ jobs }) => useInvalidateBalanceOnNewJob(workspaceIdentifier, getMockedResponse(jobs), {}), | ||
({ jobs }) => { | ||
const queryClient = useQueryClient(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we call useQueryClient
inside the wrapper to get access to the client from the tree mounted by this test
}; | ||
|
||
interface addNotificationProps { | ||
export interface AddNotificationProps { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no big changes here, i just capitalised this, OCD
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors how the React Query client is created and wired through the app’s providers, adding mutation cache support for error notifications, and updates several tests to use the new useQueryClient
pattern.
- Extract
createGetiQueryClient
into its own function and add aMutationCache
that triggers error notifications. - Refactor
RequiredProviders
and testing utilities to usePrefilledQueryClientProvider
with the new client creation API. - Update tests to use
useQueryClient
instead of manually instantiatingQueryClient
, and rename notification prop types.
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
web_ui/src/test-utils/required-providers-render.tsx | Use PrefilledQueryClientProvider and extracted query client code |
web_ui/src/routes/organizations/organizations-context.test.tsx | Replace waitForElementToBeRemoved with waitFor , simplify setup |
web_ui/src/providers/query-client-provider/query-client-provider.component.tsx | Extract createGetiQueryClient , add mutationCache , refactor provider |
web_ui/src/pages/media/hooks/media-delete/media-delete.hook.test.tsx | Switch to useQueryClient hook, remove direct QueryClient usage |
web_ui/src/notification/notification.component.tsx | Rename and export AddNotificationProps |
web_ui/src/core/jobs/hooks/utils.test.tsx | Update tests to call useQueryClient for invalidation testing |
Comments suppressed due to low confidence (1)
web_ui/src/core/jobs/hooks/utils.test.tsx:39
- [nitpick] The variable
queryClient
here holds the hook result, not the client directly. Consider renaming it (e.g.,hookResult
) to avoid confusion.
const queryClient = renderHookWithProviders(useQueryClient);
web_ui/src/providers/query-client-provider/query-client-provider.component.tsx
Show resolved
Hide resolved
web_ui/src/pages/media/hooks/media-delete/media-delete.hook.test.tsx
Outdated
Show resolved
Hide resolved
<ThemeProvider theme={defaultTheme}> | ||
<NotificationProvider> | ||
<Notifications /> | ||
<PrefilledQueryClientProvider featureFlags={featureFlags} profile={profile}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the main change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I fully understand the intend of this PR. I'll try to come back to this later
if (customQueryClient) { | ||
return customQueryClient; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels a bit odd to me, if a user needs a different query client then they can render the provider manually,
<TanstackQueryClientProvider client={customQueryClient}>
// ...
</TanstackQueryClientProvider>
instead of relying on this wrapper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, previous implementation quirks. Got rid of it now.
featureFlags?: CustomFeatureFlags; | ||
profile?: OnboardingProfile | null; | ||
}) => { | ||
const { addNotification } = useNotification(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this notification behaviour in our tests? If we verify that createGetiQueryClient
works as expected with a single unit test then I don't think we really need it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can also just pass the ref. But what you mean here is that we dont need notification stuff on the tests, but i dont think that is true. We do need it and we test a lot of notifications. Once we remove the "addNotification(...)" from the consumers (since our QC will trigger them by default) we will still be able to test the notification presence.
<Notifications /> | ||
<PrefilledQueryClientProvider featureFlags={featureFlags} profile={profile}> | ||
<ThemeProvider theme={defaultTheme}> | ||
<Suspense fallback={<IntelBrandedLoading />}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the extra suspense you might ask? Good question:
First, it's just for the tests so no danger there, secondly:
From google/copilot/chatgpt/testing:
"Sometimes, due to React’s rendering order or test environment quirks, the outer isn’t "ready" to catch suspensions from providers/components deep in the tree.
An inner ensures that any suspension in that subtree is always caught, preventing errors and showing the fallback as intended."
it('Should invalidate balance if feature flag is enabled', async () => { | ||
const queryClient = new QueryClient(); | ||
queryClient.invalidateQueries = jest.fn(); | ||
let invalidateSpy: jest.SpyInstance | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed offline about these. I just "refactored" the tests to make it work with the new approach, but fundamentally they are not great tests in the sense that they test if react-query works instead of testing our app behavior AFTER react-query acts. So we should check if , once we do X, then Y happens, not that react-query called its internals correctly.
web_ui/src/providers/query-client-provider/query-client-provider.component.tsx
Show resolved
Hide resolved
8fab795
to
2631381
Compare
queryClient.invalidateQueries = mockSetInvalidateQueries; | ||
|
||
const wrapper = ({ children }: { children: ReactNode }) => ( | ||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think instead of creating second QueryClientProvider
instance we could just leave the previous implementation of the RequiredProvidersProps
which accepts optionally the queryClient
. In case we want to mock queryClient
, we create it using createGetiQueryClient
and pass it to the hook/provider. For instance: useInvalidateBalanceOnNewJob(..., { providerProps: { queryClient }})
.
📝 Description
Why did this come up? I wanted to decouple notifications from a few places, which let me to update the mutation cache, which led to tests failing, which led to realising we were using different clients, which might be dangerous since then we'll be testing something different from what our main app uses. And here we are.
QueryClient now triggers notifications instead of each hook doing it. Which means the tests need the correct query client to test the existence of those notifications.
Note: I will wait for the release to merge this.
RequiredProvidersRender
will now use the actual query client we use for the geti appFor the next PRs:
addNotification
(non-custom ones) from all consumers.✨ Type of Change
Select the type of change your PR introduces:
🧪 Testing Scenarios
Describe how the changes were tested and how reviewers can test them too:
✅ Checklist
Before submitting the PR, ensure the following: