Skip to content

Commit c153378

Browse files
alpharius-cknarefyev91Copilot
authored
test: add shared jest tests for demo apps (#313)
* feat: add shared jest tests for demo apps * feat: use correct version for yarn * feat: add change set * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * feat: add required globals * feat: add ci workflow --------- Co-authored-by: Nicolay Arefyeu <n.arefyev91@gmail.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 874332b commit c153378

33 files changed

Lines changed: 1951 additions & 46 deletions

.changeset/orange-dancers-fry.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@callstack/brownfield-example-shared-tests': minor
3+
'@callstack/brownie': minor
4+
'@callstack/brownfield-cli': minor
5+
---
6+
7+
Jest unit tests

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
run: yarn changeset status --since=origin/${{ github.base_ref }}
2929

3030
build-lint:
31-
name: Build & static code analysis
31+
name: Build, lint, typecheck & Jest
3232
runs-on: ubuntu-latest
3333
steps:
3434
- name: Checkout
@@ -46,6 +46,9 @@ jobs:
4646
- name: Typecheck files
4747
run: yarn typecheck
4848

49+
- name: Run app tests (Jest)
50+
run: yarn test:apps
51+
4952
- name: Test Brownfield CLI (version)
5053
run: |
5154
yarn workspace @callstack/react-native-brownfield brownfield --version

CONTRIBUTING.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ We use [changesets](https://github.com/changesets/changesets) to make it easier
1919
- `lint` - runs linting on all JS/TS source files in the monorepo _[Turbo]_
2020
- `gradle-plugin:lint` - runs linting on the Brownfield Gradle plugin source code
2121
- `typecheck` - runs TypeScript type checking on all TS source files in the monorepo _[Turbo]_
22+
- `test:apps` - runs Jest for the React Native example apps under `apps/` (Expo 54, Expo 55, plain RN) _[Turbo]_
2223
- `build` - runs all `build*` tasks in the Turbo repo - see below for more details _[Turbo]_
2324
- `dev` - runs all `dev` tasks in all workspaces
2425
- `brownfield:plugin:publish:local` - publishes the Brownfield Gradle plugin to your local Maven repository for testing purposes
@@ -27,8 +28,30 @@ We use [changesets](https://github.com/changesets/changesets) to make it easier
2728
- `build:example:android-rn` - builds the example React Native app for Android (`apps/RNApp/android`)
2829
- `build:example:ios-rn` - builds the example React Native app for iOS (`apps/RNApp/ios`)
2930
- `build:example:android-consumer:expo55` - builds the example native Android consumer (`apps/AndroidApp`) app's flavor consuming the Expo 55 RN app (`apps/ExpoApp55`) artifact
30-
- - `build:example:android-consumer:expo54` - builds the example native Android consumer (`apps/AndroidApp`) app's flavor consuming the Expo 54 RN app (`apps/ExpoApp54`) artifact
31-
- - `build:example:android-consumer:vanilla` - builds the example native Android consumer (`apps/AndroidApp`) app's flavor consuming the vanilla RN app (`apps/RNApp`) artifact
31+
- `build:example:android-consumer:expo54` - builds the example native Android consumer (`apps/AndroidApp`) app's flavor consuming the Expo 54 RN app (`apps/ExpoApp54`) artifact
32+
- `build:example:android-consumer:vanilla` - builds the example native Android consumer (`apps/AndroidApp`) app's flavor consuming the vanilla RN app (`apps/RNApp`) artifact
3233
- `build:example:ios-consumer:expo55` - builds the example native iOS consumer app (`apps/AppleApp`) consuming the Expo 55 RN app (`apps/ExpoApp55`) artifact
3334
- `build:example:ios-consumer:expo54` - builds the example native iOS consumer app (`apps/AppleApp`) consuming the Expo 54 RN app (`apps/ExpoApp54`) artifact
3435
- `build:example:ios-consumer:vanilla` - builds the example native iOS consumer (`apps/AppleApp`) app's flavor consuming the vanilla RN app (`apps/RNApp`) artifact
36+
37+
## Example app tests
38+
39+
The React Native example apps share Jest utilities and test suites from `apps/brownfield-example-shared-tests`. Tests exercise integration with `@callstack/react-native-brownfield`, `@callstack/brownfield-navigation`, and `@callstack/brownie` as used in each demo.
40+
41+
From the repository root:
42+
43+
| Command | Description |
44+
| --- | --- |
45+
| `yarn test:apps` | Runs `test` in all workspaces under `apps/` that define it (via Turbo). |
46+
47+
Per example app (run from the repo root):
48+
49+
| Command | App |
50+
| --- | --- |
51+
| `yarn workspace @callstack/brownfield-example-rn-app test` | Plain React Native (`apps/RNApp`) |
52+
| `yarn workspace @callstack/brownfield-example-expo-app-54 test` | Expo SDK 54 (`apps/ExpoApp54`) |
53+
| `yarn workspace @callstack/brownfield-example-expo-app-55 test` | Expo SDK 55 (`apps/ExpoApp55`) |
54+
55+
Package-level scripts (`yarn test` inside `apps/RNApp`, `apps/ExpoApp54`, or `apps/ExpoApp55`) invoke Jest with each app’s `jest.config.js`.
56+
57+
The native-only sample apps (`apps/AppleApp`, `apps/AndroidApp`) use their platform test runners (Xcode / Gradle), not Jest.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import PostMessageTab from '../app/(tabs)/postMessage';
2+
import Counter from '../components/counter';
3+
import RNApp from '../RNApp';
4+
import {
5+
runPostMessageTabSuite,
6+
runCounterSuite,
7+
runExpoRnAppSuite,
8+
} from '@callstack/brownfield-example-shared-tests';
9+
10+
runPostMessageTabSuite('ExpoApp54', PostMessageTab);
11+
runCounterSuite('ExpoApp54', Counter);
12+
runExpoRnAppSuite('ExpoApp54', RNApp);

apps/ExpoApp54/jest.config.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const path = require('path');
2+
3+
module.exports = {
4+
preset: 'jest-expo',
5+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
6+
moduleNameMapper: {
7+
'^react$': require.resolve('react'),
8+
'^react/jsx-runtime$': require.resolve('react/jsx-runtime'),
9+
'^react/jsx-dev-runtime$': require.resolve('react/jsx-dev-runtime'),
10+
'^@testing-library/react-native$': require.resolve(
11+
'@testing-library/react-native'
12+
),
13+
'^@/(.*)$': '<rootDir>/$1',
14+
'^@callstack/react-native-brownfield$': path.join(
15+
__dirname,
16+
'../../packages/react-native-brownfield/src/index.ts'
17+
),
18+
'^@callstack/brownfield-navigation$': path.join(
19+
__dirname,
20+
'../../packages/brownfield-navigation/src/index.ts'
21+
),
22+
'^@callstack/brownie$': path.join(
23+
__dirname,
24+
'../../packages/brownie/src/index.ts'
25+
),
26+
},
27+
transformIgnorePatterns: [
28+
'node_modules/(?!((jest-)?react-native|@react-native(-community)?|@callstack/brownfield-example-shared-tests|expo|@expo|expo-modules-core)/)',
29+
],
30+
};

apps/ExpoApp54/jest.setup.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('@callstack/brownfield-example-shared-tests/jest/setup');

apps/ExpoApp54/package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"android": "expo run:android",
99
"ios": "expo run:ios",
1010
"web": "expo start --web",
11-
"lint": "expo lint",
11+
"lint": "expo lint --no-cache",
12+
"test": "jest --config jest.config.js",
1213
"prebuild": "expo prebuild",
1314
"brownfield:prepare:android:ci": "cd .. && node --experimental-strip-types --no-warnings ./scripts/prepare-android-build-gradle-for-ci.ts ExpoApp54",
1415
"brownfield:package:android": "brownfield package:android --module-name brownfieldlib --variant release",
@@ -41,9 +42,15 @@
4142
"react-native-worklets": "0.5.1"
4243
},
4344
"devDependencies": {
45+
"@callstack/brownfield-example-shared-tests": "workspace:^",
46+
"@testing-library/react-native": "^13.3.3",
47+
"@types/jest": "^30.0.0",
4448
"@types/react": "~19.1.10",
4549
"eslint": "^9.25.0",
4650
"eslint-config-expo": "~10.0.0",
51+
"jest": "^29.7.0",
52+
"jest-expo": "~54.0.16",
53+
"react-test-renderer": "19.1.0",
4754
"typescript": "~5.9.3"
4855
},
4956
"brownie": {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import PostMessageTab from '../src/app/postMessage';
2+
import Counter from '../src/components/counter';
3+
import RNApp from '../RNApp';
4+
import {
5+
runPostMessageTabSuite,
6+
runCounterSuite,
7+
runExpoRnAppSuite,
8+
} from '@callstack/brownfield-example-shared-tests';
9+
10+
runPostMessageTabSuite('ExpoApp55', PostMessageTab);
11+
runCounterSuite('ExpoApp55', Counter);
12+
runExpoRnAppSuite('ExpoApp55', RNApp);

apps/ExpoApp55/eslint.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
// https://docs.expo.dev/guides/using-eslint/
22
const { defineConfig } = require('eslint/config');
33
const expoConfig = require('eslint-config-expo/flat');
4+
const globals = require('globals');
45

56
module.exports = defineConfig([
67
expoConfig,
78
{
89
ignores: ['dist/*'],
910
},
11+
// Jest config is executed by Node (CommonJS); teach ESLint Node globals like __dirname.
12+
{
13+
files: ['jest.config.js'],
14+
languageOptions: {
15+
globals: globals.node,
16+
},
17+
},
1018
]);

apps/ExpoApp55/jest.config.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const path = require('path');
2+
3+
module.exports = {
4+
preset: 'jest-expo',
5+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
6+
moduleNameMapper: {
7+
'^react$': require.resolve('react'),
8+
'^react/jsx-runtime$': require.resolve('react/jsx-runtime'),
9+
'^react/jsx-dev-runtime$': require.resolve('react/jsx-dev-runtime'),
10+
'^@testing-library/react-native$': require.resolve(
11+
'@testing-library/react-native'
12+
),
13+
// Match before `@/` so `@/global.css` is stubbed (Expo web styling).
14+
'^.+\\.css$': '<rootDir>/jest/cssMock.js',
15+
'^@/assets/(.*)$': '<rootDir>/assets/$1',
16+
'^@/(.*)$': '<rootDir>/src/$1',
17+
'^@callstack/react-native-brownfield$': path.join(
18+
__dirname,
19+
'../../packages/react-native-brownfield/src/index.ts'
20+
),
21+
'^@callstack/brownfield-navigation$': path.join(
22+
__dirname,
23+
'../../packages/brownfield-navigation/src/index.ts'
24+
),
25+
'^@callstack/brownie$': path.join(
26+
__dirname,
27+
'../../packages/brownie/src/index.ts'
28+
),
29+
},
30+
transformIgnorePatterns: [
31+
'node_modules/(?!((jest-)?react-native|@react-native(-community)?|@callstack/brownfield-example-shared-tests|expo|@expo|expo-modules-core)/)',
32+
],
33+
};

0 commit comments

Comments
 (0)