diff --git a/src/__tests__/act.test.tsx b/src/__tests__/act.test.tsx index 08944e994..dfe20e3e5 100644 --- a/src/__tests__/act.test.tsx +++ b/src/__tests__/act.test.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { Text } from 'react-native'; import { act, fireEvent, render, screen } from '..'; +import { getIsReactActEnvironment } from '../act'; type UseEffectProps = { callback(): void }; const UseEffect = ({ callback }: UseEffectProps) => { @@ -48,3 +49,32 @@ test('should be able to await act', async () => { test('should be able to await act when promise rejects', async () => { await expect(act(() => Promise.reject('error'))).rejects.toBe('error'); }); + +test('should restore act environment when callback throws synchronously', async () => { + const previousEnvironment = getIsReactActEnvironment(); + + const testError = new Error('Synchronous error in act'); + + await expect( + act(() => { + throw testError; + }), + ).rejects.toBe(testError); + + // Verify the act environment was restored even after error + expect(getIsReactActEnvironment()).toBe(previousEnvironment); +}); + +test('should restore act environment when callback returns non-promise value', async () => { + const previousEnvironment = getIsReactActEnvironment(); + + // Call act with a callback that returns a non-promise value + // This tests the else branch in withGlobalActEnvironment + const result = await act(() => { + return 42; + }); + + expect(result).toBe(42); + // Verify the act environment was restored + expect(getIsReactActEnvironment()).toBe(previousEnvironment); +}); diff --git a/src/__tests__/wait-for.test.tsx b/src/__tests__/wait-for.test.tsx index b9235b3e9..88c8429d3 100644 --- a/src/__tests__/wait-for.test.tsx +++ b/src/__tests__/wait-for.test.tsx @@ -316,3 +316,34 @@ test('waitFor throws if expectation is not a function', async () => { waitFor('not a function'), ).rejects.toThrowErrorMatchingInlineSnapshot(`"Received \`expectation\` arg must be a function"`); }); + +test.each([false, true])( + 'waitFor throws clear error when switching from fake timers to real timers (legacyFakeTimers = %s)', + async (legacyFakeTimers) => { + jest.useFakeTimers({ legacyFakeTimers }); + + const waitForPromise = waitFor(() => { + // Switch to real timers during waitFor - this should trigger an error + jest.useRealTimers(); + throw new Error('test'); + }); + + await expect(waitForPromise).rejects.toThrow( + 'Changed from using fake timers to real timers while using waitFor', + ); + }, +); + +test('waitFor throws clear error when switching from real timers to fake timers', async () => { + jest.useRealTimers(); + + const waitForPromise = waitFor(() => { + // Switch to fake timers during waitFor - this should trigger an error + jest.useFakeTimers(); + throw new Error('test'); + }); + + await expect(waitForPromise).rejects.toThrow( + 'Changed from using real timers to fake timers while using waitFor', + ); +});