Closed Wozniaxos closed 1 year ago
Hey, @Wozniaxos. Thanks for reporting this.
Do you have a reproduction repository where I can look into this? I can't help much without a repo I can run and debug.
@kettanaito thanks for very quick answer!
https://github.com/Wozniaxos/msw-repro here is the repos
npm install
and npm run check-test
Hey, @Wozniaxos. Thanks for sharing the repository.
Upon the initial run of check-test
, the following error was thrown:
FAIL src/components/Watchlist/Watchlist.test.tsx [ src/components/Watchlist/Watchlist.test.tsx ]
Invariant Violation:
"fetch" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:
import fetch from 'cross-fetch';
import { ApolloClient, HttpLink } from '@apollo/client';
const client = new ApolloClient({
link: new HttpLink({ uri: '/graphql', fetch })
});
This clearly indicates that your testing setup is missing a fetch polyfill. This is something you must add if you wish to test browser code (your app) in Node (Vitest). This has nothing to do with MSW, to be totally clear here.
Just follow the Vitest suggestions:
npm install -D cross-fetch
// packages/project/src/App.tsx
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
+import fetch from 'cross-fetch'
const httpLink = new HttpLink({
uri: `http://localhost:3000/graphql`,
+ fetch,
})
export const apolloClient = new ApolloClient({
cache: new InMemoryCache(),
link: httpLink,
})
Once this is done, let's run the check-test
script again:
data is undefined
loading is true
querinasdas dasd asd asd asd asd asd asd asd asd asd g!!
You can see that your console.log
statement from the handler is printed, so MSW is functioning as expected, as far as we can tell. But the test still fails on a timeout:
FAIL src/components/Watchlist/Watchlist.test.tsx > Watchlist > renders properly
Error: Test timed out in 5000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
Notice how the timeout in the error message is 5000ms
despite you setting it to 10000
on the expect()
call in your test:
await waitFor(() => expect(screen.getByText('Rendered')).toBeDefined(), {
timeout: 10000,
})
That's a clear indication that your timeout is not respected in Vitest, and your test fails.
Let's set the timeout for your test on the it()
block itself:
describe('Watchlist', () => {
it('renders properly', async () => {
render(
<ApolloProvider client={apolloClient}>
<Watchlist />
</ApolloProvider>
)
+ await waitFor(() => expect(screen.getByText('Rendered')).toBeDefined())
+ }, 10_000)
})
Running the test again:
FAIL src/components/Watchlist/Watchlist.test.tsx > Watchlist > renders properly
TestingLibraryElementError: Unable to find an element with the text: Rendered. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
Ignored nodes: comments, script, style
<body>
<div>
<div>
rendered
</div>
</div>
</body>
Ignored nodes: comments, script, style
<html>
<head />
<body>
<div>
<div>
rendered
</div>
</div>
</body>
</html>
That's some progress! The timeout is gone, and we can see the RTL library saying it's unable to find a node by the text you've provided in the assertion.
Let's compare your expectations (the test) and the actuality (your Watchlist.tsx
):
await waitFor(() => expect(screen.getByText('Rendered')).toBeDefined())
Notice the capital "R".
// packages/project/src/components/Watchlist/Watchlist.tsx
function Watchlist() {
const { data, loading } = useWatchlistQuery();
console.log('data is', data);
console.log('loading is', loading);
// Hey, it's a lowercase "r"!
return data ? <div>rendered</div> : <div/>;
}
Casing matters. Let's account for that:
// packages/project/src/components/Watchlist/Watchlist.test.tsx
+await waitFor(() => expect(screen.getByText('rendered')).toBeDefined())
And running the test again...
data is undefined
loading is true
querinasdas dasd asd asd asd asd asd asd asd asd asd g!!
data is {
watchlist: [
{
__typename: 'WatchlistResponse',
id: '1',
venueAccount: 'Bitfinex',
securityId: '1',
symbol: 'SHIBUSD'
},
{
__typename: 'WatchlistResponse',
id: '2',
venueAccount: 'BitMEX',
securityId: '2',
symbol: 'SHIBUSD'
}
]
}
loading is false
✓ src/components/Watchlist/Watchlist.test.tsx (1)
Hooray! 🎉 You can clearly see that the mocked query response arrives at your Watchlist.tsx
component.
I enjoyed looking into this issue! If you'd like to support my open-source effort, please consider Sponsoring MSW on GitHub. Every contribution counts. It helps me help others without feeling like I'm sacrificing too much of my free time (which I try to do as little as possible, I promise).
Thanks!
@kettanaito Hey, it was my mistake with that fetch, i was misled cause of rest api handlers worked for me - but we use axios and axios is not using fetch under the hood. I indeed used cross-fetch and mocks are called properly. Speaking about the rest you pointed - i just made quickly repo changes to show you that mock is not called - failing test weren't a problem :) sorry that i didn't specified that and you wasted time for case sentisivness, timeout and other stuff besides that fetch. And BTW, i didn't get error about fetch that you posted
FAIL src/components/Watchlist/Watchlist.test.tsx [ src/components/Watchlist/Watchlist.test.tsx ]
Invariant Violation:
"fetch" has not been found globally and no fetcher has been configured. To fix this, install a fetch...
Only warning that fetch is experimental
Maybe because of different node? i use 19.
Thanks again!
Oh, got it! I will take a look into this when I have a minute.
MSW doesn't have official support for Node 18 and 19, so if Node version is the culprit, I can't treat this as an issue since we aren't promising compatibility with those versions, to begin with. But it'd be nice to know nonetheless.
Hi! i just want to say that i read all issues with that title and browse through all internet and can't make it work.
Apollo client version: 3.7.4 msw version: 0.49.3
My setup test file:
My server
Query: generated by code gen
My client setup
finally my handlers:
I've even tried with capturing all operation with graphql.operation and none was called. Whatever i try i get undefined from useQuery hook. I also have logged the handler at it prints it out as it exist
There is any fetch mocking in the entire project. Another thing that maybe is worth to mention that we have axios installed - but this one is not taking part in the test (not imported in any place)
I've also investigated the query that is dispatched during this test:
The thing is that there is nothing custom and different here than just "Get started" apollo setup + GraphQL mock setup 1:1 as per MSW docs says - at least it seems to, if i not did any major mistake here.