Skip to content

Commit 3abeac3

Browse files
committed
Merge branch 'main' into v13
# Conflicts: # jest-setup.ts
2 parents 7455b21 + 0c8f3a8 commit 3abeac3

21 files changed

+142
-30
lines changed

.github/workflows/ci.yml

+16-1
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,26 @@ jobs:
5656
uses: ./.github/actions/setup-deps
5757

5858
- name: Test
59-
run: yarn test:ci
59+
run: yarn test:ci:coverage
6060

6161
- name: Upload coverage to Codecov
6262
uses: codecov/codecov-action@v4
6363

64+
65+
test-concurrent:
66+
needs: [install-cache-deps]
67+
runs-on: ubuntu-latest
68+
name: Test (concurrent mode)
69+
steps:
70+
- name: Checkout
71+
uses: actions/checkout@v4
72+
73+
- name: Setup Node.js and deps
74+
uses: ./.github/actions/setup-deps
75+
76+
- name: Test in concurrent mode
77+
run: CONCURRENT_MODE=1 yarn test:ci
78+
6479
test-website:
6580
runs-on: ubuntu-latest
6681
name: Test Website

.release-it.json

+33-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,47 @@
11
{
2+
"hooks": {
3+
"before:init": ["yarn typecheck", "yarn test", "yarn lint"],
4+
"after:bump": "yarn build",
5+
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
6+
},
27
"git": {
3-
"commitMessage": "chore: release ${version}",
8+
"commitMessage": "chore: release v${version}",
49
"tagName": "v${version}"
510
},
611
"npm": {
712
"publish": true
813
},
914
"github": {
10-
"release": true
15+
"release": true,
16+
"releaseName": "v${version}"
1117
},
1218
"plugins": {
1319
"@release-it/conventional-changelog": {
14-
"preset": "angular"
20+
"preset": {
21+
"name": "conventionalcommits",
22+
"types": [
23+
{
24+
"type": "feat",
25+
"section": "✨ Features"
26+
},
27+
{
28+
"type": "perf",
29+
"section": "💨 Performance Improvements"
30+
},
31+
{
32+
"type": "fix",
33+
"section": "🐛 Bug Fixes"
34+
},
35+
{
36+
"type": "chore(deps)",
37+
"section": "🛠️ Dependency Upgrades"
38+
},
39+
{
40+
"type": "docs",
41+
"section": "📚 Documentation"
42+
}
43+
]
44+
}
1545
}
1646
}
1747
}

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ You can use the built-in Jest matchers automatically by having any import from `
4949
## Example
5050

5151
```jsx
52-
import { render, screen, fireEvent } from '@testing-library/react-native';
52+
import { render, screen, userEvent } from '@testing-library/react-native';
5353
import { QuestionsBoard } from '../QuestionsBoard';
5454

5555
// It is recommended to use userEvent with fake timers
@@ -105,7 +105,6 @@ React Native Testing Library consists of following APIs:
105105
- [Migration to 12.0](https://callstack.github.io/react-native-testing-library/docs/migration/v12)
106106
- [Migration to built-in Jest Matchers](https://callstack.github.io/react-native-testing-library/docs/migration/jest-matchers)
107107

108-
109108
## Troubleshooting
110109

111110
- [Troubleshooting guide](https://callstack.github.io/react-native-testing-library/docs/guides/troubleshooting)

examples/basic/.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
jest-setup.ts

examples/basic/components/AnimatedView.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function AnimatedView(props: AnimatedViewProps) {
1717
duration: props.fadeInDuration ?? 250,
1818
useNativeDriver: props.useNativeDriver ?? true,
1919
}).start();
20-
}, [fadeAnim]);
20+
}, [fadeAnim, props.fadeInDuration, props.useNativeDriver]);
2121

2222
return (
2323
<Animated.View

examples/basic/components/__tests__/AnimatedView.test.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import * as React from 'react';
2+
import { Text } from 'react-native';
13
import { act, render, screen } from '@testing-library/react-native';
24
import { AnimatedView } from '../AnimatedView';
35

@@ -13,7 +15,7 @@ describe('AnimatedView', () => {
1315
it('should use native driver when useNativeDriver is true', async () => {
1416
render(
1517
<AnimatedView fadeInDuration={250} useNativeDriver={true}>
16-
Test
18+
<Text>Test</Text>
1719
</AnimatedView>,
1820
);
1921
expect(screen.root).toHaveStyle({ opacity: 0 });
@@ -25,7 +27,7 @@ describe('AnimatedView', () => {
2527
it('should not use native driver when useNativeDriver is false', async () => {
2628
render(
2729
<AnimatedView fadeInDuration={250} useNativeDriver={false}>
28-
Test
30+
<Text>Test</Text>
2931
</AnimatedView>,
3032
);
3133
expect(screen.root).toHaveStyle({ opacity: 0 });

examples/basic/jest-setup.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
/* eslint-disable no-undef, import/no-extraneous-dependencies */
1+
import { configure } from '@testing-library/react-native';
22

33
// Import built-in Jest matchers
44
import '@testing-library/react-native/extend-expect';
55

66
// Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing
77
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
8+
9+
configure({ concurrentRoot: true });

examples/basic/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121
"devDependencies": {
2222
"@babel/core": "^7.24.0",
23-
"@testing-library/react-native": "^12.7.1",
23+
"@testing-library/react-native": "^12.8.0",
2424
"@types/eslint": "^8.56.10",
2525
"@types/jest": "^29.5.12",
2626
"@types/react": "~18.2.79",

examples/basic/yarn.lock

+5-5
Original file line numberDiff line numberDiff line change
@@ -2463,9 +2463,9 @@ __metadata:
24632463
languageName: node
24642464
linkType: hard
24652465

2466-
"@testing-library/react-native@npm:^12.7.1":
2467-
version: 12.7.1
2468-
resolution: "@testing-library/react-native@npm:12.7.1"
2466+
"@testing-library/react-native@npm:^12.8.0":
2467+
version: 12.8.0
2468+
resolution: "@testing-library/react-native@npm:12.8.0"
24692469
dependencies:
24702470
jest-matcher-utils: "npm:^29.7.0"
24712471
pretty-format: "npm:^29.7.0"
@@ -2478,7 +2478,7 @@ __metadata:
24782478
peerDependenciesMeta:
24792479
jest:
24802480
optional: true
2481-
checksum: 10c0/caaa4bdf97834b307b72af05c447ce40a2ba2ff40b464050bc29535caadf81981ea2873668445e633fdb3d13efccb136ef0932d6d9f4736bc6f7f98be98088d4
2481+
checksum: 10c0/216d40eefc3afa3259b37611213dcd6667cd0b8deb30521a8aaabe3afc15f07116ce64acba150f8c88b8e268df80639baf6bc38f05af1dbbae247e1d07639bde
24822482
languageName: node
24832483
linkType: hard
24842484

@@ -8923,7 +8923,7 @@ __metadata:
89238923
resolution: "root-workspace-0b6124@workspace:."
89248924
dependencies:
89258925
"@babel/core": "npm:^7.24.0"
8926-
"@testing-library/react-native": "npm:^12.7.1"
8926+
"@testing-library/react-native": "npm:^12.8.0"
89278927
"@types/eslint": "npm:^8.56.10"
89288928
"@types/jest": "npm:^29.5.12"
89298929
"@types/react": "npm:~18.2.79"

examples/cookbook/.eslintignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
test-utils.*
1+
jest-setup.ts
2+
test-utils.*

examples/cookbook/jest-setup.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* eslint-disable no-undef, import/no-extraneous-dependencies */
1+
import { configure } from '@testing-library/react-native';
22

33
// Import built-in Jest matchers
44
import '@testing-library/react-native/extend-expect';
@@ -9,7 +9,11 @@ jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
99

1010
// Enable API mocking via Mock Service Worker (MSW)
1111
beforeAll(() => server.listen());
12+
1213
// Reset any runtime request handlers we may add during the tests
1314
afterEach(() => server.resetHandlers());
15+
1416
// Disable API mocking after the tests are done
1517
afterAll(() => server.close());
18+
19+
configure({ concurrentRoot: true });

examples/cookbook/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"devDependencies": {
3131
"@babel/core": "^7.20.0",
3232
"@expo/metro-runtime": "~3.2.3",
33-
"@testing-library/react-native": "^12.7.2",
33+
"@testing-library/react-native": "^12.8.0",
3434
"@types/eslint": "^8.56.10",
3535
"@types/jest": "^29.5.12",
3636
"@types/react": "~18.2.45",

examples/cookbook/yarn.lock

+5-5
Original file line numberDiff line numberDiff line change
@@ -2833,9 +2833,9 @@ __metadata:
28332833
languageName: node
28342834
linkType: hard
28352835

2836-
"@testing-library/react-native@npm:^12.7.2":
2837-
version: 12.7.2
2838-
resolution: "@testing-library/react-native@npm:12.7.2"
2836+
"@testing-library/react-native@npm:^12.8.0":
2837+
version: 12.8.0
2838+
resolution: "@testing-library/react-native@npm:12.8.0"
28392839
dependencies:
28402840
jest-matcher-utils: "npm:^29.7.0"
28412841
pretty-format: "npm:^29.7.0"
@@ -2848,7 +2848,7 @@ __metadata:
28482848
peerDependenciesMeta:
28492849
jest:
28502850
optional: true
2851-
checksum: 10c0/0e4e26bd211056646f8b5c80e9177efc90affe0ddc7e1a2c22742a4e6da7129ec1f9125c7d233adddeb27f429fb3eb91e3f3bfa9e77e176f042475574546b001
2851+
checksum: 10c0/216d40eefc3afa3259b37611213dcd6667cd0b8deb30521a8aaabe3afc15f07116ce64acba150f8c88b8e268df80639baf6bc38f05af1dbbae247e1d07639bde
28522852
languageName: node
28532853
linkType: hard
28542854

@@ -9762,7 +9762,7 @@ __metadata:
97629762
dependencies:
97639763
"@babel/core": "npm:^7.20.0"
97649764
"@expo/metro-runtime": "npm:~3.2.3"
9765-
"@testing-library/react-native": "npm:^12.7.2"
9765+
"@testing-library/react-native": "npm:^12.8.0"
97669766
"@types/eslint": "npm:^8.56.10"
97679767
"@types/jest": "npm:^29.5.12"
97689768
"@types/react": "npm:~18.2.45"

jest-setup.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { resetToDefaults } from './src/pure';
1+
import { resetToDefaults, configure } from './src/pure';
2+
import './src/matchers/extend-expect';
23

34
beforeEach(() => {
45
resetToDefaults();
6+
if (process.env.CONCURRENT_MODE === '1') {
7+
configure({ concurrentRoot: true });
8+
}
59
});

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@testing-library/react-native",
3-
"version": "12.7.2",
3+
"version": "12.8.0",
44
"description": "Simple and complete React Native testing utilities that encourage good testing practices.",
55
"main": "build/index.js",
66
"types": "build/index.d.ts",
@@ -25,15 +25,16 @@
2525
"scripts": {
2626
"clean": "del build",
2727
"test": "jest",
28-
"test:ci": "jest --maxWorkers=2 --collectCoverage=true --coverage-provider=v8",
28+
"test:ci": "jest --maxWorkers=2",
29+
"test:ci:coverage": "jest --maxWorkers=2 --collectCoverage=true --coverage-provider=v8",
2930
"typecheck": "tsc",
3031
"copy-flowtypes": "cp typings/index.flow.js build",
3132
"lint": "eslint src --cache",
3233
"validate": "yarn lint && yarn typecheck && yarn test",
3334
"build:js": "babel src --out-dir build --extensions \".js,.ts,.jsx,.tsx\" --source-maps --ignore \"**/__tests__/**\"",
3435
"build:ts": "tsc --build tsconfig.release.json",
3536
"build": "yarn clean && yarn build:js && yarn build:ts && yarn copy-flowtypes",
36-
"publish": "yarn build && release-it"
37+
"release": "release-it"
3738
},
3839
"files": [
3940
"build/",

src/__tests__/config.test.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { getConfig, configure, resetToDefaults, configureInternal } from '../config';
22

3+
beforeEach(() => {
4+
resetToDefaults();
5+
});
6+
37
test('getConfig() returns existing configuration', () => {
48
expect(getConfig().asyncUtilTimeout).toEqual(1000);
59
expect(getConfig().defaultIncludeHiddenElements).toEqual(false);
@@ -12,6 +16,7 @@ test('configure() overrides existing config values', () => {
1216
asyncUtilTimeout: 5000,
1317
defaultDebugOptions: { message: 'debug message' },
1418
defaultIncludeHiddenElements: false,
19+
concurrentRoot: false,
1520
});
1621
});
1722

src/__tests__/render.test.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,13 @@ test('render calls detects host component names', () => {
241241
render(<View testID="test" />);
242242
expect(getConfig().hostComponentNames).not.toBeUndefined();
243243
});
244+
245+
test('supports legacy rendering', () => {
246+
render(<View testID="test" />, { concurrentRoot: false });
247+
expect(screen.root).toBeDefined();
248+
});
249+
250+
test('supports concurrent rendering', () => {
251+
render(<View testID="test" />, { concurrentRoot: true });
252+
expect(screen.root).toBeDefined();
253+
});

src/config.ts

+7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export type Config = {
1313

1414
/** Default options for `debug` helper. */
1515
defaultDebugOptions?: Partial<DebugOptions>;
16+
17+
/**
18+
* Set to `true` to enable concurrent rendering.
19+
* Otherwise `render` will default to legacy synchronous rendering.
20+
*/
21+
concurrentRoot: boolean;
1622
};
1723

1824
export type ConfigAliasOptions = {
@@ -37,6 +43,7 @@ export type InternalConfig = Config & {
3743
const defaultConfig: InternalConfig = {
3844
asyncUtilTimeout: 1000,
3945
defaultIncludeHiddenElements: false,
46+
concurrentRoot: false,
4047
};
4148

4249
let config = { ...defaultConfig };

src/render.tsx

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import type { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
1+
import type {
2+
ReactTestInstance,
3+
ReactTestRenderer,
4+
TestRendererOptions,
5+
} from 'react-test-renderer';
26
import * as React from 'react';
37
import { Profiler } from 'react';
48
import act from './act';
@@ -13,7 +17,18 @@ import { setRenderResult } from './screen';
1317
import { getQueriesForElement } from './within';
1418

1519
export interface RenderOptions {
20+
/**
21+
* Pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating
22+
* reusable custom render functions for common data providers.
23+
*/
1624
wrapper?: React.ComponentType<any>;
25+
26+
/**
27+
* Set to `true` to enable concurrent rendering.
28+
* Otherwise `render` will default to legacy synchronous rendering.
29+
*/
30+
concurrentRoot?: boolean | undefined;
31+
1732
createNodeMock?: (element: React.ReactElement) => unknown;
1833
unstable_validateStringsRenderedWithinText?: boolean;
1934
}
@@ -38,11 +53,18 @@ export function renderInternal<T>(
3853
) {
3954
const {
4055
wrapper: Wrapper,
56+
concurrentRoot,
4157
detectHostComponentNames = true,
4258
unstable_validateStringsRenderedWithinText,
43-
...testRendererOptions
59+
...rest
4460
} = options || {};
4561

62+
const testRendererOptions: TestRendererOptions = {
63+
...rest,
64+
// @ts-expect-error incomplete typing on RTR package
65+
unstable_isConcurrent: concurrentRoot ?? getConfig().concurrentRoot,
66+
};
67+
4668
if (detectHostComponentNames) {
4769
configureHostComponentNamesIfNeeded();
4870
}

0 commit comments

Comments
 (0)