blitz
blitz copied to clipboard
getQueryKey does not work in jest
What is the problem?
When I try to use the getQueryKey
function in a test environment, I get Cannot read property 'apiUrl' of undefined
error. From what I see it is caused by a non-existent _meta
prop on the resolver. An easy solution that comes to mind is to just add optional chaining like this:
// getQueryKey
return getQueryKeyFromUrlAndParams(sanitizeQuery(resolver)._meta?.apiUrl, params)
but maybe it's a bigger problem than this. Thanks for your help in advance!
Paste all your error logs here:
TypeError: Cannot read property 'apiUrl' of undefined
at getQueryKey (node_modules/@blitzjs/core/dist/blitzjs-core.cjs.dev.js:325:67)
Paste all relevant code snippets here:
getQueryKey(getCurrentUser);
What are detailed steps to reproduce this?
Just run frontend jest test on a component that is using getQueryKey
function
Run blitz -v
and paste the output here:
macOS Big Sur | darwin-x64 | Node: v14.17.0
blitz: 0.33.1 (global)
blitz: 0.38.1 (local)
Package manager: yarn
System:
OS: macOS 11.0.1
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 2.14 GB / 32.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 14.17.0 - ~/.nvm/versions/node/v14.17.0/bin/node
Yarn: 1.22.10 - /usr/local/bin/yarn
npm: 6.14.13 - ~/.nvm/versions/node/v14.17.0/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
npmPackages:
@prisma/client: 2.26.0 => 2.26.0
blitz: 0.38.1 => 0.38.1
prisma: 2.26.0 => 2.26.0
react: 18.0.0-alpha-568dc3532 => 18.0.0-alpha-568dc3532
react-dom: 18.0.0-alpha-568dc3532 => 18.0.0-alpha-568dc3532
typescript: 4.4.0-dev.20210702 => 4.4.0-dev.20210702
Thank you for bringing this up.
I think you're right, but I think the actual problem with that file is that as of https://github.com/blitz-js/blitz/blob/fcb2782b332900ebecbf8d27050a25cc7c8b7c0b/packages/core/src/utils/react-query-utils.ts#L91 the Type system is lying to you, claiming that the resolver is enhanced when (in the context of running Jest) it isn't an enhanced resolver at all.
That seems like a bigger problem, because if you can't trust the type system, then it loses its value.
I think it would be better if when the utility is validating a resolver in a test environment, instead of turning TypeScript into a liar, it appended some mock _meta information to the resolver if it isn't already present.
Something like:
if (!('_meta' in queryFn) && !isNotInUserTestEnvironment()) {
queryFn["_meta"] = {
name: queryFn.name || "testResolver",
type: "query", // should be "query" or "mutation" but the checks are disabled for tests so I don't think it matters
filePath: "filePath",
apiUrl: "apiUrl",
}
return queryFn as EnhancedResolverRpcClient<TInput, TResult>;
}
Heads up: the _meta implementation is changing in https://github.com/blitz-js/blitz/pull/2516 so no one work on this until that is merged.
This bug causes all useQuery
calls that are at the top level of any BlitzPage
component to throw the error Cannot read property 'apiUrl' of undefined
. Is there a recommended solution until #2516 is done? My workaround is to wrap every top-level useQuery
in its own hook so that I can mock the custom hook instead of useQuery
.
@jaydev if you need, we can merge a PR to fix this before #2516 is done.
@flybayer That would be super swell! Let me know if there's any way I can help out here.
@jaydev sorry for the delay here. You're welcome to make a PR for it if you want!
Maybe this will help someone
I tired to mock
import { useQuery } from 'blitz';
but it didn't work.
So I tried to mock
import { useQuery } from '@blitzjs/core';
instead and it worked!
import { useQuery } from '@blitzjs/core';
jest.mock('@blitzjs/core', () => {
return {
// @ts-ignore
...jest.requireActual('@blitzjs/core'),
useQuery: jest.fn(),
};
});
and then in test
it('should do something', () => {
(useQuery as jest.Mock).mockReturnValue([
null,
{
refetch: jest.fn(() => {
return Promise.resolve({ data: 'data' });
}),
},
]);
})