T
TanStack•3y ago
unwilling-turquoise

Testing Component that uses UseQuery hook

Hello ! I don't know if I'm following the right logic on this, do not hesitate to tell me i'm wrong. I have a component that uses the data from a custom useQuery to conditionally render the content of my page. I want to test the different outputs of my component which depends on the result of my useQuery. Right now, I have my QueryProvider setup, my axios call is mocked, but when I try to assert on what my component render, I get an error as data is considered undefined. I'm considering mocking the useQuery as I can already verify the hook itself in another test. Would that be correct, and if so, how can I do that in Typescript ? The error:
Error: Uncaught [TypeError: Cannot destructure property 'data' of '(0 , _profile.useGetUserPermissions)(...)' as it is undefined.]
Error: Uncaught [TypeError: Cannot destructure property 'data' of '(0 , _profile.useGetUserPermissions)(...)' as it is undefined.]
I'll put the code samples in the thread. (i'll check if I can quickly reproduce a codesandbox) Thanks
2 Replies
unwilling-turquoise
unwilling-turquoiseOP•3y ago
Test:
const { queryByTestId } = renderWithProvider(
<ExportHistoryProvider>
<ExportHistory />
</ExportHistoryProvider>,
{
initialPermission: []
}
);

await waitFor(() => {
expect(queryByTestId("exporthistory-read-permission-error")).toBeInTheDocument();
});
const { queryByTestId } = renderWithProvider(
<ExportHistoryProvider>
<ExportHistory />
</ExportHistoryProvider>,
{
initialPermission: []
}
);

await waitFor(() => {
expect(queryByTestId("exporthistory-read-permission-error")).toBeInTheDocument();
});
Content of the component is kinda fancy due to business logic but I'll try to resume it here:
const MyChecker = ({permission}) => {
const { data, isLoading } = useGetUserPermissions()

if (isLoading) {
return <CircularProgress />
}
if (!data.includes(permission)){
return <h1>Access Denied</h1>
}
return <children/>
}
const MyChecker = ({permission}) => {
const { data, isLoading } = useGetUserPermissions()

if (isLoading) {
return <CircularProgress />
}
if (!data.includes(permission)){
return <h1>Access Denied</h1>
}
return <children/>
}
Content of the custom useQuery:
const useGetUserPermissions = (): UseQueryResult<Permission[], unknown> => {
const {
profile: { username }
} = useUserState();
const [
{
token: { accessToken }
}
] = useAuth();

// TODO: Monitor this query to see if it's being called too many times
// If so, consider adjusting staleTime and/or cacheTime
return useQuery<Permission[]>(
ProfileQueryKeys.getUserPermissions(username),
() => getUserPermissionsAPI(accessToken, username),
{
// Allows for the request to execute ONLY when enabled becomes "true"
enabled: !!accessToken && !!username,
onError: error => {
console.error(error);
},
staleTime: 2 * 60 * 1000 // 2 minutes
}
);
};
const useGetUserPermissions = (): UseQueryResult<Permission[], unknown> => {
const {
profile: { username }
} = useUserState();
const [
{
token: { accessToken }
}
] = useAuth();

// TODO: Monitor this query to see if it's being called too many times
// If so, consider adjusting staleTime and/or cacheTime
return useQuery<Permission[]>(
ProfileQueryKeys.getUserPermissions(username),
() => getUserPermissionsAPI(accessToken, username),
{
// Allows for the request to execute ONLY when enabled becomes "true"
enabled: !!accessToken && !!username,
onError: error => {
console.error(error);
},
staleTime: 2 * 60 * 1000 // 2 minutes
}
);
};
I tried to reproduce here https://codesandbox.io/s/admiring-hermann-r32h8g, but getting an issue in test with the queryclientprovider 😮
deep-jade
deep-jade•3y ago
I'm stuck with the same problem. And also struggle with it. This way is very questionable because how bloated it is, but works.
jest.mock("./CarDashboard.query");
const mockedUseCarDataQuery = jest.mocked(useCarDataQuery);

mockedUseCarDataQuery.mockReturnValue({
data: undefined,
error: null,
isError: false,
isLoading: true,
isLoadingError: false,
isRefetchError: false,
isSuccess: false,
dataUpdatedAt: 0,
errorUpdatedAt: 0,
failureCount: 0,
failureReason: null,
errorUpdateCount: 0,
isFetched: false,
isFetchedAfterMount: false,
isFetching: false,
isInitialLoading: false,
isPaused: false,
isPlaceholderData: false,
isPreviousData: false,
isRefetching: false,
isStale: false,
refetch(): Promise<QueryObserverResult<CarDataDto, Error>> {
throw new Error("Function not implemented.");
},
remove(): void {
throw new Error("Function not implemented.");
},
fetchStatus: "fetching",
status: "loading",
});
jest.mock("./CarDashboard.query");
const mockedUseCarDataQuery = jest.mocked(useCarDataQuery);

mockedUseCarDataQuery.mockReturnValue({
data: undefined,
error: null,
isError: false,
isLoading: true,
isLoadingError: false,
isRefetchError: false,
isSuccess: false,
dataUpdatedAt: 0,
errorUpdatedAt: 0,
failureCount: 0,
failureReason: null,
errorUpdateCount: 0,
isFetched: false,
isFetchedAfterMount: false,
isFetching: false,
isInitialLoading: false,
isPaused: false,
isPlaceholderData: false,
isPreviousData: false,
isRefetching: false,
isStale: false,
refetch(): Promise<QueryObserverResult<CarDataDto, Error>> {
throw new Error("Function not implemented.");
},
remove(): void {
throw new Error("Function not implemented.");
},
fetchStatus: "fetching",
status: "loading",
});
Probably should be possible to mock queryFn, but I'm not figured out yet why variant with mocking queryFn not working for me.

Did you find this page helpful?