Skip to content

Commit 16100de

Browse files
committed
Merge branch 'master' into beta
1 parent 4d01e1f commit 16100de

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

docs/src/pages/guides/testing.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,55 @@ expect(result.current).toEqual({answer: 42});
8686
```
8787

8888
Here we are making use of `waitFor` and waiting until our Nock expectation indicates that it has been called. This way we know that our hook has finished and should have the correct data.
89+
90+
## Testing Load More / Infinite Scroll
91+
92+
First we need to mock our API response
93+
94+
```
95+
function generateMockedResponse(page) {
96+
return {
97+
page: page,
98+
items: [...]
99+
}
100+
}
101+
```
102+
103+
Then, our `nock` configuration needs to differentiate responses based on the page, and we'll be using `uri` to do this.
104+
`uri`'s value here will be something like `"/?page=1` or `/?page=2`
105+
106+
```
107+
const expectation = nock('http://example.com')
108+
.persist()
109+
.query(true)
110+
.get('/api/data')
111+
.reply(200, (uri) => {
112+
const url = new URL(`http://example.com${uri}`);
113+
const { page } = Object.fromEntries(url.searchParams);
114+
return generateMockedResponse(page);
115+
});
116+
```
117+
118+
(Notice the `.persist()`, because we'll be calling from this endpoint multiple times)
119+
120+
Now we can safely run our tests, the trick here is to await both `isFetching` and then `!isFetching` after calling `fetchMore()`:
121+
122+
```
123+
const { result, waitFor } = renderHook(() => useInfiniteQueryCustomHook(), { wrapper });
124+
125+
await waitFor(() => result.current.isSuccess);
126+
127+
expect(result.current.data).toStrictEqual(generateMockedResponse(1));
128+
129+
result.current.fetchMore();
130+
131+
await waitFor(() => result.current.isFetching);
132+
await waitFor(() => !result.current.isFetching);
133+
134+
expect(result.current.data).toStrictEqual([
135+
...generateMockedResponse(1),
136+
...generateMockedResponse(2),
137+
]);
138+
139+
expectation.done();
140+
```
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const Module = require('module')
2+
const path = require('path')
3+
const resolveFrom = require('resolve-from')
4+
5+
const node_modules = path.resolve(__dirname, 'node_modules')
6+
7+
const originalRequire = Module.prototype.require
8+
9+
// The following ensures that there is always only a single (and same)
10+
// copy of React in an app at any given moment.
11+
Module.prototype.require = function(modulePath) {
12+
// Only redirect resolutions to non-relative and non-absolute modules
13+
if (
14+
['/react/', '/react-dom/', '/react-query/'].some(d => {
15+
try {
16+
return require.resolve(modulePath).includes(d)
17+
} catch (err) {
18+
return false
19+
}
20+
})
21+
) {
22+
try {
23+
modulePath = resolveFrom(node_modules, modulePath)
24+
} catch (err) {
25+
//
26+
}
27+
}
28+
29+
return originalRequire.call(this, modulePath)
30+
}
31+
32+
module.exports = {
33+
webpack: config => {
34+
config.resolve = {
35+
...config.resolve,
36+
alias: {
37+
...config.resolve.alias,
38+
react$: resolveFrom(path.resolve('node_modules'), 'react'),
39+
'react-query$': resolveFrom(
40+
path.resolve('node_modules'),
41+
'react-query'
42+
),
43+
'react-dom$': resolveFrom(path.resolve('node_modules'), 'react-dom'),
44+
},
45+
}
46+
return config
47+
},
48+
}

examples/nextjs/next.config.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const Module = require('module')
2+
const path = require('path')
3+
const resolveFrom = require('resolve-from')
4+
5+
const node_modules = path.resolve(__dirname, 'node_modules')
6+
7+
const originalRequire = Module.prototype.require
8+
9+
// The following ensures that there is always only a single (and same)
10+
// copy of React in an app at any given moment.
11+
Module.prototype.require = function (modulePath) {
12+
// Only redirect resolutions to non-relative and non-absolute modules
13+
if (
14+
['/react/', '/react-dom/', '/react-query/'].some(d => {
15+
try {
16+
return require.resolve(modulePath).includes(d)
17+
} catch (err) {
18+
return false
19+
}
20+
})
21+
) {
22+
try {
23+
modulePath = resolveFrom(node_modules, modulePath)
24+
} catch (err) {
25+
//
26+
}
27+
}
28+
29+
return originalRequire.call(this, modulePath)
30+
}
31+
32+
module.exports = {
33+
webpack: config => {
34+
config.resolve = {
35+
...config.resolve,
36+
alias: {
37+
...config.resolve.alias,
38+
react$: resolveFrom(path.resolve('node_modules'), 'react'),
39+
'react-query$': resolveFrom(
40+
path.resolve('node_modules'),
41+
'react-query'
42+
),
43+
'react-dom$': resolveFrom(path.resolve('node_modules'), 'react-dom'),
44+
},
45+
}
46+
return config
47+
},
48+
}

0 commit comments

Comments
 (0)