Skip to content

Commit 8dc1b8e

Browse files
committed
feat: add e2e tests with maestro
1 parent 3644da5 commit 8dc1b8e

File tree

6 files changed

+167
-40
lines changed

6 files changed

+167
-40
lines changed

.github/workflows/build.yml

+104-37
Original file line numberDiff line numberDiff line change
@@ -7,79 +7,146 @@ on:
77
branches: [main]
88

99
jobs:
10-
android:
11-
name: Build Android App
12-
runs-on: ubuntu-latest
10+
ios-build:
11+
name: iOS Build
12+
runs-on: macos-latest
13+
defaults:
14+
run:
15+
working-directory: example
1316

1417
env:
1518
SKIP_YARN_COREPACK_CHECK: 0
1619

1720
steps:
18-
- uses: actions/checkout@v4
19-
20-
- name: Setup Java
21-
uses: actions/setup-java@v4
22-
with:
23-
distribution: 'zulu'
24-
java-version: '17'
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
2523

2624
- name: Setup Node.js
2725
uses: actions/setup-node@v4
2826
with:
29-
node-version: 'lts/*'
27+
node-version: '22'
3028
cache: 'yarn'
29+
cache-dependency-path: example/yarn.lock
30+
31+
- name: Setup Ruby
32+
uses: ruby/setup-ruby@v1
33+
with:
34+
ruby-version: '3.2'
35+
bundler-cache: true
36+
37+
- name: Cache CocoaPods
38+
uses: actions/cache@v4
39+
with:
40+
path: |
41+
example/swift/Pods
42+
key: ${{ runner.os }}-pods-${{ hashFiles('example/swift/Podfile.lock') }}
43+
restore-keys: |
44+
${{ runner.os }}-pods-
3145
3246
- name: Install root dependencies
3347
run: yarn install
3448

3549
- name: Install example dependencies
50+
run: yarn install
51+
52+
- name: Install pods
3653
run: |
37-
cd example
38-
yarn install
39-
cd ..
54+
cd swift
55+
pod install
4056
41-
- name: Build Android App
57+
- name: Install Maestro CLI
4258
run: |
43-
cd example/kotlin
44-
./gradlew assembleDebug
59+
curl -Ls "https://get.maestro.mobile.dev" | bash
60+
brew tap facebook/fb
61+
brew install facebook/fb/idb-companion
4562
46-
ios:
47-
name: Build iOS App
48-
runs-on: macos-latest
63+
- name: Add Maestro to path
64+
run: echo "${HOME}/.maestro/bin" >> $GITHUB_PATH
65+
66+
- name: Start packager
67+
run: yarn start &
68+
69+
- name: Build iOS App (Release)
70+
run: |
71+
cd swift
72+
xcodebuild -workspace SwiftExample.xcworkspace -scheme SwiftExample -configuration Release -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15' build CODE_SIGNING_ALLOWED=NO
73+
74+
- name: Setup iOS simulator
75+
run: |
76+
UDID=$(xcrun simctl list devices | grep "iPhone" | grep "Booted" | head -1 | grep -E -o -i "([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})")
77+
if [ -z "$UDID" ]; then
78+
UDID=$(xcrun simctl list devices available | grep "iPhone" | head -1 | grep -E -o -i "([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})")
79+
xcrun simctl boot "${UDID}"
80+
fi
81+
open -a Simulator
82+
xcrun simctl launch "${UDID}" com.callstack.reactnativebrownfield.SwiftExample
83+
84+
- name: Run iOS tests
85+
run: |
86+
export MAESTRO_DRIVER_STARTUP_TIMEOUT=1500000
87+
export MAESTRO_WAIT_TIMEOUT=10000
88+
yarn test:e2e:ios
89+
90+
android-build:
91+
name: Android Build
92+
runs-on: ubuntu-latest
93+
defaults:
94+
run:
95+
working-directory: example
4996

5097
env:
5198
SKIP_YARN_COREPACK_CHECK: 0
5299

53100
steps:
54-
- uses: actions/checkout@v4
101+
- name: Checkout repository
102+
uses: actions/checkout@v4
55103

56104
- name: Setup Node.js
57105
uses: actions/setup-node@v4
58106
with:
59-
node-version: 'lts/*'
107+
node-version: '22'
60108
cache: 'yarn'
109+
cache-dependency-path: example/yarn.lock
61110

62-
- name: Setup Ruby
63-
uses: ruby/setup-ruby@v1
111+
- name: Setup Java
112+
uses: actions/setup-java@v4
64113
with:
65-
ruby-version: '3.2'
66-
bundler-cache: true
114+
distribution: 'zulu'
115+
java-version: '17'
67116

68117
- name: Install root dependencies
69118
run: yarn install
70119

71120
- name: Install example dependencies
72-
run: |
73-
cd example
74-
yarn install
75-
cd ..
121+
run: yarn install
76122

77-
- name: Install pods
78-
run: |
79-
cd example/swift
80-
pod install
123+
- name: Start packager
124+
run: yarn start &
81125

82-
- name: Build iOS App
126+
- name: Install Maestro CLI
83127
run: |
84-
cd example/swift
85-
xcodebuild -workspace SwiftExample.xcworkspace -scheme SwiftExample -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15' build CODE_SIGNING_ALLOWED=NO
128+
curl -Ls "https://get.maestro.mobile.dev" | bash
129+
130+
- name: Add Maestro to path
131+
run: echo "${HOME}/.maestro/bin" >> $GITHUB_PATH
132+
133+
- name: Create AVD and generate snapshot for caching
134+
uses: reactivecircus/android-emulator-runner@v2
135+
with:
136+
target: aosp_atd
137+
api-level: 30
138+
arch: x86
139+
ram-size: 4096M
140+
channel: canary
141+
profile: pixel
142+
avd-name: Pixel_3a_API_30_AOSP
143+
force-avd-creation: false
144+
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
145+
emulator-boot-timeout: 12000
146+
disable-animations: false
147+
working-directory: example/kotlin
148+
script: |
149+
chmod +x ./gradlew
150+
./gradlew :app:installRelease
151+
cd ..
152+
yarn test:e2e:android

example/kotlin/app/src/main/java/com/callstack/kotlinexample/MainActivity.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ fun HomeScreen(
8484
verticalArrangement = Arrangement.Center
8585
) {
8686
Text(
87-
"React Native Brownfield Example",
87+
"React Native Brownfield",
8888
fontSize = 30.sp,
8989
modifier = Modifier.padding(15.dp),
9090
textAlign = TextAlign.Center
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
appId: com.callstack.kotlinexample
2+
3+
---
4+
- launchApp
5+
- assertVisible: "React Native Brownfield"
6+
- tapOn: "Navigate to React Native Fragment with Compose"
7+
8+
- assertVisible: "React Native Screen"
9+
10+
- tapOn: "Push next screen"
11+
12+
- assertVisible: "React Native Screen"
13+
14+
- tapOn: "Go back"
15+
16+
- assertVisible: "React Native Screen"
17+
18+
- tapOn: "Go back"
19+
20+
- assertVisible: "React Native Brownfield"
21+
22+
- tapOn: "Navigate to React Native Fragment Activity"
23+
24+
- assertVisible: "React Native Screen"
25+
26+
- tapOn: "Push next screen"
27+
28+
- assertVisible: "React Native Screen"
29+
30+
- tapOn: "Go back"
31+
32+
- assertVisible: "React Native Screen"
33+
34+
- tapOn: "Go back"
35+
36+
- assertVisible: "React Native Brownfield"
37+

example/maestro-tests/ios_test.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
appId: com.callstack.reactnativebrownfield.SwiftExample
2+
3+
---
4+
- launchApp
5+
6+
- assertVisible: "React Native Brownfield"
7+
- tapOn: "Push React Native screen"
8+
9+
- assertVisible: "React Native Screen"
10+
11+
- tapOn: "Push next screen"
12+
13+
- assertVisible: "React Native Screen"
14+
15+
- tapOn: "Go back"
16+
17+
- assertVisible: "React Native Screen"
18+
19+
- tapOn: "Go back"
20+
21+
- assertVisible: "React Native Brownfield"

example/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"scripts": {
66
"android": "react-native run-android",
77
"ios": "react-native run-ios",
8-
"start": "react-native start"
8+
"start": "react-native start",
9+
"test:e2e:ios": "maestro test ./maestro-tests/ios_test.yml",
10+
"test:e2e:android": "maestro test ./maestro-tests/android_test.yml"
911
},
1012
"dependencies": {
1113
"react": "19.0.0",

example/swift/App.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ struct ContentView: View {
2020
var body: some View {
2121
NavigationView {
2222
VStack {
23-
Text("React Native Brownfield App")
23+
Text("React Native Brownfield")
2424
.font(.title)
2525
.bold()
2626
.padding()

0 commit comments

Comments
 (0)