Skip to content

Commit 77bf93c

Browse files
chore: update Jest to 28 (#1008)
* chore: update jest * refactor: pass useFakeTimer config in tests * refactor: remove unused code * fix jest config unable to discover babel due to rootDir change Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
1 parent bdd8f75 commit 77bf93c

9 files changed

+682
-986
lines changed

babel.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = {
66
'@babel/preset-env',
77
{
88
targets: {
9-
node: '10',
9+
node: '14',
1010
},
1111
bugfixes: true,
1212
},

package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,27 @@
2929
"@babel/cli": "^7.8.4",
3030
"@babel/core": "^7.9.0",
3131
"@babel/plugin-proposal-class-properties": "^7.8.3",
32-
"@babel/plugin-transform-flow-strip-types": "^7.16.0",
32+
"@babel/plugin-transform-flow-strip-types": "^7.18.0",
3333
"@babel/preset-env": "^7.9.6",
3434
"@babel/preset-flow": "^7.9.0",
3535
"@babel/preset-react": "^7.9.4",
3636
"@babel/preset-typescript": "^7.16.0",
3737
"@callstack/eslint-config": "^11.0.0",
3838
"@release-it/conventional-changelog": "^2.0.0",
3939
"@testing-library/jest-native": "~4.0.2",
40-
"@types/jest": "^27.0.0",
40+
"@types/jest": "^28.0.0",
4141
"@types/react": "^17.0.0",
4242
"@types/react-native": "^0.66.6",
4343
"@types/react-test-renderer": "^17.0.0",
44-
"babel-jest": "^27.0.0",
44+
"babel-jest": "^28.0.0",
4545
"conventional-changelog-cli": "^2.0.11",
4646
"cp-cli": "^2.0.0",
4747
"dedent": "^0.7.0",
4848
"del-cli": "^3.0.1",
4949
"eslint": "^7.32.0",
5050
"flow-bin": "~0.170.0",
5151
"flow-copy-source": "^2.0.9",
52-
"jest": "^27.0.0",
52+
"jest": "^28.0.0",
5353
"react": "^18.0.0",
5454
"react-native": "~0.69.1",
5555
"react-test-renderer": "^18.0.0",
@@ -82,10 +82,10 @@
8282
"prepare": "yarn build"
8383
},
8484
"jest": {
85-
"preset": "../jest-preset",
86-
"rootDir": "./src",
85+
"preset": "./jest-preset",
8786
"testPathIgnorePatterns": [
88-
"timerUtils"
87+
"timerUtils",
88+
"examples/"
8989
],
9090
"testTimeout": 60000,
9191
"transformIgnorePatterns": [

src/__tests__/auto-cleanup.test.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ test('component is automatically umounted after first test ends', () => {
3838
});
3939

4040
test('does not time out with legacy fake timers', () => {
41-
jest.useFakeTimers('legacy');
41+
jest.useFakeTimers({ legacyFakeTimers: true });
4242
render(<Test />);
4343
expect(isMounted).toEqual(true);
4444
});
4545

4646
test('does not time out with fake timers', () => {
47-
jest.useFakeTimers('modern');
47+
jest.useFakeTimers();
4848
render(<Test />);
4949
expect(isMounted).toEqual(true);
5050
});

src/__tests__/timerUtils.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import { setTimeout } from '../helpers/timers';
22

3-
const TimerMode = {
4-
Legacy: 'legacy',
5-
Modern: 'modern', // broken for now
6-
} as const;
7-
83
async function sleep(ms: number): Promise<void> {
94
return new Promise((resolve) => setTimeout(resolve, ms));
105
}
116

12-
export { TimerMode, sleep };
7+
export { sleep };

src/__tests__/timers.test.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import waitFor from '../waitFor';
2-
import { TimerMode } from './timerUtils';
32

4-
describe.each([TimerMode.Legacy, TimerMode.Modern])(
5-
'%s fake timers tests',
6-
(fakeTimerType) => {
3+
describe.each([false, true])(
4+
'fake timers tests (legacyFakeTimers = %s)',
5+
(legacyFakeTimers) => {
76
beforeEach(() => {
8-
jest.useFakeTimers(fakeTimerType);
7+
jest.useFakeTimers({ legacyFakeTimers });
98
});
109

1110
test('it successfully runs tests', () => {

src/__tests__/waitFor.test.tsx

+24-35
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as React from 'react';
22
import { Text, TouchableOpacity, View } from 'react-native';
33
import { fireEvent, render, waitFor } from '..';
4-
import { TimerMode } from './timerUtils';
54

65
class Banana extends React.Component<any> {
76
changeFresh = () => {
@@ -79,36 +78,26 @@ test('waits for element with custom interval', async () => {
7978
expect(mockFn).toHaveBeenCalledTimes(2);
8079
});
8180

82-
test('waits for element until it stops throwing using modern fake timers', async () => {
83-
jest.useFakeTimers('modern');
84-
const { getByText, queryByText } = render(<BananaContainer />);
85-
86-
fireEvent.press(getByText('Change freshness!'));
87-
expect(queryByText('Fresh')).toBeNull();
88-
89-
jest.advanceTimersByTime(300);
90-
const freshBananaText = await waitFor(() => getByText('Fresh'));
91-
92-
expect(freshBananaText.props.children).toBe('Fresh');
93-
});
81+
test.each([false, true])(
82+
'waits for element until it stops throwing using fake timers (legacyFakeTimers = %s)',
83+
async (legacyFakeTimers) => {
84+
jest.useFakeTimers({ legacyFakeTimers });
85+
const { getByText, queryByText } = render(<BananaContainer />);
9486

95-
test('waits for element until it stops throwing using legacy fake timers', async () => {
96-
jest.useFakeTimers('legacy');
97-
const { getByText, queryByText } = render(<BananaContainer />);
87+
fireEvent.press(getByText('Change freshness!'));
88+
expect(queryByText('Fresh')).toBeNull();
9889

99-
fireEvent.press(getByText('Change freshness!'));
100-
expect(queryByText('Fresh')).toBeNull();
101-
102-
jest.advanceTimersByTime(300);
103-
const freshBananaText = await waitFor(() => getByText('Fresh'));
90+
jest.advanceTimersByTime(300);
91+
const freshBananaText = await waitFor(() => getByText('Fresh'));
10492

105-
expect(freshBananaText.props.children).toBe('Fresh');
106-
});
93+
expect(freshBananaText.props.children).toBe('Fresh');
94+
}
95+
);
10796

108-
test.each([TimerMode.Legacy, TimerMode.Modern])(
109-
'waits for assertion until timeout is met with %s fake timers',
110-
async (fakeTimerType) => {
111-
jest.useFakeTimers(fakeTimerType);
97+
test.each([false, true])(
98+
'waits for assertion until timeout is met with fake timers (legacyFakeTimers = %s)',
99+
async (legacyFakeTimers) => {
100+
jest.useFakeTimers({ legacyFakeTimers });
112101

113102
const mockFn = jest.fn(() => {
114103
throw Error('test');
@@ -124,10 +113,10 @@ test.each([TimerMode.Legacy, TimerMode.Modern])(
124113
}
125114
);
126115

127-
test.each([TimerMode.Legacy, TimerMode.Modern])(
128-
'waits for assertion until timeout is met with %s fake timers',
129-
async (fakeTimerType) => {
130-
jest.useFakeTimers(fakeTimerType);
116+
test.each([false, true])(
117+
'waits for assertion until timeout is met with fake timers (legacyFakeTimers = %s)',
118+
async (legacyFakeTimers) => {
119+
jest.useFakeTimers({ legacyFakeTimers });
131120

132121
const mockErrorFn = jest.fn(() => {
133122
throw Error('test');
@@ -150,10 +139,10 @@ test.each([TimerMode.Legacy, TimerMode.Modern])(
150139
}
151140
);
152141

153-
test.each([TimerMode.Legacy, TimerMode.Legacy])(
154-
'awaiting something that succeeds before timeout works with %s fake timers',
155-
async (fakeTimerType) => {
156-
jest.useFakeTimers(fakeTimerType);
142+
test.each([false, true])(
143+
'awaiting something that succeeds before timeout works with fake timers (legacyFakeTimers = %s)',
144+
async (legacyFakeTimers) => {
145+
jest.useFakeTimers({ legacyFakeTimers });
157146

158147
let calls = 0;
159148
const mockFn = jest.fn(() => {

src/__tests__/waitForElementToBeRemoved.test.tsx

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { useState } from 'react';
22
import { View, Text, TouchableOpacity } from 'react-native';
33
import { render, fireEvent, waitForElementToBeRemoved } from '..';
4-
import { TimerMode } from './timerUtils';
54

65
const TestSetup = ({ shouldUseDelay = true }) => {
76
const [isAdded, setIsAdded] = useState(true);
@@ -130,10 +129,10 @@ test('waits with custom interval', async () => {
130129
expect(mockFn).toHaveBeenCalledTimes(4);
131130
});
132131

133-
test.each([TimerMode.Legacy, TimerMode.Modern])(
134-
'works with %s fake timers',
135-
async (fakeTimerType) => {
136-
jest.useFakeTimers(fakeTimerType);
132+
test.each([false, true])(
133+
'works with fake timers (legacyFakeTimers = %s)',
134+
async (legacyFakeTimers) => {
135+
jest.useFakeTimers({ legacyFakeTimers });
137136

138137
const mockFn = jest.fn(() => <View />);
139138

src/helpers/timers.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
/* globals jest */
33
const globalObj = typeof window === 'undefined' ? global : window;
44

5+
type FakeTimersTypes = 'modern' | 'legacy';
6+
57
// Currently this fn only supports jest timers, but it could support other test runners in the future.
68
function runWithRealTimers<T>(callback: () => T): T {
79
const fakeTimersType = getJestFakeTimersType();
@@ -12,13 +14,14 @@ function runWithRealTimers<T>(callback: () => T): T {
1214
const callbackReturnValue = callback();
1315

1416
if (fakeTimersType) {
15-
jest.useFakeTimers(fakeTimersType);
17+
const fakeTimersConfig = getFakeTimersConfigFromType(fakeTimersType);
18+
jest.useFakeTimers(fakeTimersConfig);
1619
}
1720

1821
return callbackReturnValue;
1922
}
2023

21-
function getJestFakeTimersType() {
24+
function getJestFakeTimersType(): FakeTimersTypes | null {
2225
// istanbul ignore if
2326
if (
2427
typeof jest === 'undefined' ||
@@ -49,9 +52,16 @@ function getJestFakeTimersType() {
4952
// not using Jest's modern fake timers
5053
}
5154
}
55+
5256
return null;
5357
}
5458

59+
function getFakeTimersConfigFromType(type: FakeTimersTypes) {
60+
return type === 'legacy'
61+
? { legacyFakeTimers: true }
62+
: { legacyFakeTimers: false };
63+
}
64+
5565
const jestFakeTimersAreEnabled = (): boolean =>
5666
Boolean(getJestFakeTimersType());
5767

0 commit comments

Comments
 (0)