diff --git a/src/__tests__/event-wrapper-nesting.js b/src/__tests__/event-wrapper-nesting.js
new file mode 100644
index 00000000..16e1f7a2
--- /dev/null
+++ b/src/__tests__/event-wrapper-nesting.js
@@ -0,0 +1,47 @@
+import * as React from 'react'
+import {render, screen, fireEvent} from '../'
+
+let mockActDepth = 0
+let mockMaxActDepth = 0
+jest.mock('react', () => {
+ const actual = jest.requireActual('react')
+ return {
+ ...actual,
+ act: jest.fn(cb => {
+ mockActDepth++
+ mockMaxActDepth = Math.max(mockMaxActDepth, mockActDepth)
+ try {
+ return actual.act(cb)
+ } finally {
+ mockActDepth--
+ }
+ }),
+ }
+})
+
+function Nested() {
+ return (
+ <>
+
+ fireEvent.change(screen.getByLabelText('inner'), {
+ target: {value: 'changed'},
+ })
+ }
+ />
+
+ >
+ )
+}
+
+test('eventWrapper does not nest `act` for a re-entrant event dispatch', () => {
+ render()
+ expect(screen.getByLabelText('inner').value).toBe('')
+
+ mockMaxActDepth = 0
+ fireEvent.focus(screen.getByLabelText('outer'))
+
+ expect(screen.getByLabelText('inner').value).toBe('changed')
+ expect(mockMaxActDepth).toBe(1)
+})
diff --git a/src/pure.js b/src/pure.js
index 054830fa..3ea36bfe 100644
--- a/src/pure.js
+++ b/src/pure.js
@@ -27,6 +27,8 @@ function jestFakeTimersAreEnabled() {
return false
}
+let inEventWrapper = false
+
configureDTL({
unstable_advanceTimersWrapper: cb => {
return act(cb)
@@ -58,11 +60,19 @@ configureDTL({
}
},
eventWrapper: cb => {
- let result
- act(() => {
- result = cb()
- })
- return result
+ if (inEventWrapper) {
+ return cb()
+ }
+ inEventWrapper = true
+ try {
+ let result
+ act(() => {
+ result = cb()
+ })
+ return result
+ } finally {
+ inEventWrapper = false
+ }
},
})