Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b09dd00

Browse files
authored
Merge pull request #432 from huchenme/pr/after-unmount
Feature: add addCleanup util function
2 parents 90613ee + 8d0fc82 commit b09dd00

File tree

6 files changed

+148
-6
lines changed

6 files changed

+148
-6
lines changed

‎.all-contributorsrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,17 @@
183183
"contributions": [
184184
"test"
185185
]
186+
},
187+
{
188+
"login": "huchenme",
189+
"name": "Hu Chen",
190+
"avatar_url": "https://avatars3.githubusercontent.com/u/2078389?v=4",
191+
"profile": "https://huchen.dev/",
192+
"contributions": [
193+
"code",
194+
"doc",
195+
"example"
196+
]
186197
}
187198
],
188199
"commitConvention": "none"

‎README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
164164
<td align="center"><a href="https://github.com/102"><img src="https://avatars1.githubusercontent.com/u/5839225?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Roman Gusev</b></sub></a><br /><a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=102" title="Documentation">📖</a></td>
165165
<td align="center"><a href="https://github.com/hemlok"><img src="https://avatars2.githubusercontent.com/u/9043345?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adam Seckel</b></sub></a><br /><a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=hemlok" title="Code">💻</a></td>
166166
<td align="center"><a href="https://keiya01.github.io/portfolio"><img src="https://avatars1.githubusercontent.com/u/34934510?v=4?s=100" width="100px;" alt=""/><br /><sub><b>keiya sasaki</b></sub></a><br /><a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=keiya01" title="Tests">⚠️</a></td>
167+
<td align="center"><a href="https://huchen.dev/"><img src="https://avatars3.githubusercontent.com/u/2078389?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hu Chen</b></sub></a><br /><a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=huchenme" title="Code">💻</a> <a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=huchenme" title="Documentation">📖</a> <a href="#example-huchenme" title="Examples">💡</a></td>
167168
</tr>
168169
</table>
169170

170-
<!-- markdownlint-enable -->
171+
<!-- markdownlint-restore -->
171172
<!-- prettier-ignore-end -->
173+
172174
<!-- ALL-CONTRIBUTORS-LIST:END -->
173175

174176
This project follows the [all-contributors](https://allcontributors.org/) specification.

‎docs/api-reference.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ route: '/reference/api'
1010
- [`renderHook`](/reference/api#renderhook)
1111
- [`act`](/reference/api#act)
1212
- [`cleanup`](/reference/api#cleanup)
13+
- [`addCleanup`](/reference/api#addcleanup)
1314

1415
---
1516

@@ -108,7 +109,9 @@ This is the same [`act` function](https://reactjs.org/docs/test-utils.html#act)
108109
function cleanup: Promise<void>
109110
```
110111

111-
Unmounts any rendered hooks rendered with `renderHook`, ensuring all effects have been flushed.
112+
Unmounts any rendered hooks rendered with `renderHook`, ensuring all effects have been flushed. Any
113+
callbacks added with [`addCleanup`](<(/reference/api#addCleanup).>) will also be called when
114+
`cleanup` is run.
112115

113116
> Please note that this is done automatically if the testing framework you're using supports the
114117
> `afterEach` global (like Jest, mocha and Jasmine). If not, you will need to do manual cleanups
@@ -147,6 +150,35 @@ variable to `true` before importing `@testing-library/react-hooks` will also dis
147150
148151
---
149152
153+
## `addCleanup`
154+
155+
```js
156+
function addCleanup(callback: function(): void|Promise<void>): function(): void
157+
```
158+
159+
Add a callback to be called during [`cleanup`](/reference/api#cleanup), returning a function to
160+
remove the cleanup if is no longer required. Cleanups are called in reverse order to being added.
161+
This is usually only relevant when wanting a cleanup to run after the component has been unmounted.
162+
163+
If the provided callback is an `async` function or returns a promise, `cleanup` will wait for it to
164+
be resolved before moving onto the next cleanup callback.
165+
166+
> Please note that any cleanups added using `addCleanup` are removed after `cleanup` is called. For
167+
> cleanups that need to run with every test, it is advised to add them in a `beforeEach` block (or
168+
> equivalent for your test runner).
169+
170+
## `removeCleanup`
171+
172+
```js
173+
function removeCleanup(callback: function(): void|Promise<void>): void
174+
```
175+
176+
Removes a cleanup callback previously added with [`addCleanup`](/reference/api#addCleanup). Once
177+
removed, the provided callback will no longer execute as part of running
178+
[`cleanup`](/reference/api#cleanup).
179+
180+
---
181+
150182
## Async Utilities
151183

152184
### `waitForNextUpdate`

‎src/cleanup.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ let cleanupCallbacks = []
44

55
async function cleanup() {
66
await flushMicroTasks()
7-
cleanupCallbacks.forEach((cb) => cb())
7+
for (const callback of cleanupCallbacks) {
8+
await callback()
9+
}
810
cleanupCallbacks = []
911
}
1012

1113
function addCleanup(callback) {
12-
cleanupCallbacks.push(callback)
14+
cleanupCallbacks.unshift(callback)
15+
return () => removeCleanup(callback)
1316
}
1417

1518
function removeCleanup(callback) {

‎src/pure.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,4 @@ function renderHook(callback, { initialProps, wrapper } = {}) {
9999
}
100100
}
101101

102-
export { renderHook, cleanup, act }
102+
export { renderHook, cleanup, addCleanup,removeCleanup,act }

‎test/cleanup.test.js

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useEffect } from 'react'
2-
import { renderHook, cleanup} from 'src'
2+
import { renderHook, cleanup,addCleanup,removeCleanup} from 'src/pure'
33

44
describe('cleanup tests', () => {
55
test('should flush effects on cleanup', async () => {
@@ -38,4 +38,98 @@ describe('cleanup tests', () => {
3838
expect(cleanupCalled[1]).toBe(true)
3939
expect(cleanupCalled[2]).toBe(true)
4040
})
41+
42+
test('should call cleanups in reverse order', async () => {
43+
let callSequence = []
44+
addCleanup(() => {
45+
callSequence.push('cleanup')
46+
})
47+
addCleanup(() => {
48+
callSequence.push('another cleanup')
49+
})
50+
const hookWithCleanup = () => {
51+
useEffect(() => {
52+
return () => {
53+
callSequence.push('unmount')
54+
}
55+
})
56+
}
57+
renderHook(() => hookWithCleanup())
58+
59+
await cleanup()
60+
61+
expect(callSequence).toEqual(['unmount', 'another cleanup', 'cleanup'])
62+
})
63+
64+
test('should wait for async cleanup', async () => {
65+
let callSequence = []
66+
addCleanup(() => {
67+
callSequence.push('cleanup')
68+
})
69+
addCleanup(async () => {
70+
await new Promise((resolve) => setTimeout(resolve, 10))
71+
callSequence.push('another cleanup')
72+
})
73+
const hookWithCleanup = () => {
74+
useEffect(() => {
75+
return () => {
76+
callSequence.push('unmount')
77+
}
78+
})
79+
}
80+
renderHook(() => hookWithCleanup())
81+
82+
await cleanup()
83+
84+
expect(callSequence).toEqual(['unmount', 'another cleanup', 'cleanup'])
85+
})
86+
87+
test('should remove cleanup using removeCleanup', async () => {
88+
let callSequence = []
89+
addCleanup(() => {
90+
callSequence.push('cleanup')
91+
})
92+
const anotherCleanup = () => {
93+
callSequence.push('another cleanup')
94+
}
95+
addCleanup(anotherCleanup)
96+
const hookWithCleanup = () => {
97+
useEffect(() => {
98+
return () => {
99+
callSequence.push('unmount')
100+
}
101+
})
102+
}
103+
renderHook(() => hookWithCleanup())
104+
105+
removeCleanup(anotherCleanup)
106+
107+
await cleanup()
108+
109+
expect(callSequence).toEqual(['unmount', 'cleanup'])
110+
})
111+
112+
test('should remove cleanup using returned handler', async () => {
113+
let callSequence = []
114+
addCleanup(() => {
115+
callSequence.push('cleanup')
116+
})
117+
const remove = addCleanup(() => {
118+
callSequence.push('another cleanup')
119+
})
120+
const hookWithCleanup = () => {
121+
useEffect(() => {
122+
return () => {
123+
callSequence.push('unmount')
124+
}
125+
})
126+
}
127+
renderHook(() => hookWithCleanup())
128+
129+
remove()
130+
131+
await cleanup()
132+
133+
expect(callSequence).toEqual(['unmount', 'cleanup'])
134+
})
41135
})

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /