mirror of
https://github.com/callstack/react-native-testing-library.git
synced 2026-09-18 23:09:04 +08:00
fix: modern jest timers (#397)
* fix: modern jest timers * treat modern timers as default, but be explicit in tests * we're node-only * rename to Thenable * add clarifications; unify test names * Update src/__tests__/auto-cleanup-skip.test.js Co-authored-by: Maciej Jastrzebski <mdjastrzebski@gmail.com> Co-authored-by: Maciej Jastrzebski <mdjastrzebski@gmail.com>
This commit is contained in:
committed by
GitHub
parent
859cb82b87
commit
111b1c9277
@@ -4,8 +4,8 @@ import { View } from 'react-native';
|
||||
let render;
|
||||
beforeAll(() => {
|
||||
process.env.RNTL_SKIP_AUTO_CLEANUP = 'true';
|
||||
const rtl = require('../');
|
||||
render = rtl.render;
|
||||
const rntl = require('..');
|
||||
render = rntl.render;
|
||||
});
|
||||
|
||||
let isMounted = false;
|
||||
@@ -20,14 +20,31 @@ class Test extends React.Component<*> {
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
// This just verifies that by importing RNTL in an environment which supports afterEach (like jest)
|
||||
// we'll get automatic cleanup between tests.
|
||||
test('component is mounted, but not umounted before test ends', () => {
|
||||
const fn = jest.fn();
|
||||
render(<Test onUnmount={fn} />);
|
||||
expect(isMounted).toEqual(true);
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('component is automatically umounted after first test ends', () => {
|
||||
expect(isMounted).toEqual(false);
|
||||
});
|
||||
|
||||
test('does not time out with legacy fake timers', () => {
|
||||
jest.useFakeTimers('legacy');
|
||||
render(<Test />);
|
||||
expect(isMounted).toEqual(true);
|
||||
});
|
||||
|
||||
test('does not time out with fake timers', () => {
|
||||
jest.useFakeTimers('modern');
|
||||
render(<Test />);
|
||||
expect(isMounted).toEqual(true);
|
||||
});
|
||||
@@ -35,6 +35,10 @@ class BananaContainer extends React.Component<{}, any> {
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('waits for element until it stops throwing', async () => {
|
||||
const { getByText, queryByText } = render(<BananaContainer />);
|
||||
|
||||
@@ -75,8 +79,8 @@ test('waits for element with custom interval', async () => {
|
||||
expect(mockFn).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
test('works with fake timers', async () => {
|
||||
jest.useFakeTimers();
|
||||
test('works with legacy fake timers', async () => {
|
||||
jest.useFakeTimers('legacy');
|
||||
|
||||
const mockFn = jest.fn(() => {
|
||||
throw Error('test');
|
||||
@@ -87,9 +91,24 @@ test('works with fake timers', async () => {
|
||||
} catch (e) {
|
||||
// suppress
|
||||
}
|
||||
jest.runTimersToTime(400);
|
||||
jest.advanceTimersByTime(400);
|
||||
|
||||
expect(mockFn).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
test('works with fake timers', async () => {
|
||||
jest.useFakeTimers('modern');
|
||||
|
||||
const mockFn = jest.fn(() => {
|
||||
throw Error('test');
|
||||
});
|
||||
|
||||
try {
|
||||
waitFor(() => mockFn(), { timeout: 400, interval: 200 });
|
||||
} catch (e) {
|
||||
// suppress
|
||||
}
|
||||
jest.advanceTimersByTime(400);
|
||||
|
||||
expect(mockFn).toHaveBeenCalledTimes(3);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
@@ -25,6 +25,10 @@ const TestSetup = ({ shouldUseDelay = true }) => {
|
||||
);
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('waits when using getBy query', async () => {
|
||||
const screen = render(<TestSetup />);
|
||||
|
||||
@@ -126,8 +130,22 @@ test('waits with custom interval', async () => {
|
||||
expect(mockFn).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
test('works with fake timers', async () => {
|
||||
jest.useFakeTimers();
|
||||
test('works with legacy fake timers', async () => {
|
||||
jest.useFakeTimers('legacy');
|
||||
|
||||
const mockFn = jest.fn(() => <View />);
|
||||
|
||||
waitForElementToBeRemoved(() => mockFn(), {
|
||||
timeout: 400,
|
||||
interval: 200,
|
||||
});
|
||||
|
||||
jest.advanceTimersByTime(400);
|
||||
expect(mockFn).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
test('works with fake timers', async () => {
|
||||
jest.useFakeTimers('modern');
|
||||
|
||||
const mockFn = jest.fn(() => <View />);
|
||||
|
||||
|
||||
+11
-4
@@ -1,15 +1,22 @@
|
||||
// @flow
|
||||
|
||||
import { printDeprecationWarning } from './helpers/errors';
|
||||
|
||||
type Thenable<T> = { then: (() => T) => mixed };
|
||||
|
||||
/**
|
||||
* Wait for microtasks queue to flush
|
||||
*/
|
||||
export default function flushMicrotasksQueue(): Promise<any> {
|
||||
export default function flushMicrotasksQueue<T>(): Thenable<T> {
|
||||
printDeprecationWarning('flushMicrotasksQueue');
|
||||
return flushMicroTasks();
|
||||
}
|
||||
|
||||
export function flushMicroTasks(): Promise<any> {
|
||||
return new Promise((resolve) => setImmediate(resolve));
|
||||
export function flushMicroTasks<T>(): Thenable<T> {
|
||||
return {
|
||||
// using "thenable" instead of a Promise, because otherwise it breaks when
|
||||
// using "modern" fake timers
|
||||
then(resolve) {
|
||||
setImmediate(resolve);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user