Skip to content

Commit c388663

Browse files
author
Kent C. Dodds
committed
feat(act): Support async act 🎉
Closes #281
1 parent 7e6031f commit c388663

File tree

5 files changed

+56
-10
lines changed

5 files changed

+56
-10
lines changed

.github/PULL_REQUEST_TEMPLATE.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,11 @@ merge of your pull request!
3434

3535
<!-- to check an item, place an "x" in the box like so: "- [x] Documentation" -->
3636

37-
- [ ] Documentation added to the [docs site](https://github.com/alexkrolick/testing-library-docs)
37+
- [ ] Documentation added to the
38+
[docs site](https://github.com/alexkrolick/testing-library-docs)
3839
- [ ] Tests
3940
- [ ] Typescript definitions updated
4041
- [ ] Ready to be merged
4142
<!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->
42-
- [ ] Added myself to contributors table
43-
<!-- this is optional, see the contributing guidelines for instructions -->
4443

4544
<!-- feel free to add additional comments -->

jest.config.js

+4
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@ const jestConfig = require('kcd-scripts/jest')
22

33
module.exports = Object.assign(jestConfig, {
44
displayName: 'library',
5+
// We're not going to bother testing everything in act-compat.js with
6+
// different versions of React. Enzyme does and it's crazy-complicated.
7+
// Totally not worth the effort. So we wont bother tracking coverage either.
8+
coveragePathIgnorePatterns: ['/node_modules/', 'act-compat.js'],
59
})

package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
"node": ">=8"
1010
},
1111
"scripts": {
12-
"add-contributor": "kcd-scripts contributors add",
1312
"build": "kcd-scripts build && kcd-scripts build --bundle --no-clean",
1413
"lint": "kcd-scripts lint",
1514
"test": "kcd-scripts test --config=other/jest.config.js",
@@ -56,8 +55,8 @@
5655
"jest-dom": "3.1.3",
5756
"jest-in-case": "^1.0.2",
5857
"kcd-scripts": "1.1.2",
59-
"react": "^16.8.5",
60-
"react-dom": "^16.8.5",
58+
"react": "16.9.0-alpha.0",
59+
"react-dom": "16.9.0-alpha.0",
6160
"react-intl": "^2.8.0",
6261
"react-redux": "6.0.1",
6362
"react-router": "^5.0.0",

src/act-compat.js

+38-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,23 @@ import React from 'react'
22
import ReactDOM from 'react-dom'
33

44
let reactAct
5+
let actSupported = false
6+
let asyncActSupported = false
57
try {
68
reactAct = require('react-dom/test-utils').act
9+
actSupported = reactAct !== undefined
10+
11+
const originalError = console.error
12+
let errorCalled = false
13+
console.error = () => {
14+
errorCalled = true
15+
}
16+
console.error.calls = []
17+
reactAct(() => ({then: () => {}})).then(() => {})
18+
if (!errorCalled) {
19+
asyncActSupported = true
20+
}
21+
console.error = originalError
722
} catch (error) {
823
// ignore, this is to support old versions of react
924
}
@@ -19,8 +34,28 @@ function actPolyfill(cb) {
1934

2035
const act = reactAct || actPolyfill
2136

22-
function rtlAct(...args) {
23-
return act(...args)
37+
// this will not avoid warnings that react-dom 16.8.0 logs for triggering
38+
// state updates asynchronously, but at least we can tell people they need
39+
// to upgrade to avoid the warnings.
40+
async function asyncActPolyfill(cb) {
41+
if (actSupported) {
42+
// if act is supported and async act isn't and they're trying to use async
43+
// act, then they need to upgrade from 16.8 to 16.9.
44+
// This is a seemless upgrade, so we'll add a warning
45+
console.error(
46+
`It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least [email protected] to remove this warning.`,
47+
)
48+
}
49+
// make all effects resolve before
50+
act(() => {})
51+
await cb()
52+
// make all effects resolve after
53+
act(() => {})
2454
}
2555

26-
export default rtlAct
56+
const asyncAct = asyncActSupported ? reactAct : asyncActPolyfill
57+
58+
export default act
59+
export {asyncAct}
60+
61+
/* eslint no-console:0 */

src/index.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@ import {
44
getQueriesForElement,
55
prettyDOM,
66
fireEvent as dtlFireEvent,
7+
configure as configureDTL,
78
} from 'dom-testing-library'
8-
import act from './act-compat'
9+
import act, {asyncAct} from './act-compat'
10+
11+
configureDTL({
12+
asyncWrapper: asyncAct,
13+
})
914

1015
const mountedContainers = new Set()
1116

@@ -133,4 +138,8 @@ fireEvent.select = (node, init) => {
133138
export * from 'dom-testing-library'
134139
export {render, cleanup, fireEvent, act}
135140

141+
// NOTE: we're not going to export asyncAct because that's our own compatibility
142+
// thing for people using [email protected]. Anyone else doesn't need it and
143+
// people should just upgrade anyway.
144+
136145
/* eslint func-name-matching:0 */

0 commit comments

Comments
 (0)