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 + } }, })