Skip to content

Commit cf95e2d

Browse files
feat: Add Harness tests (#121)
* chore: add-harness-tests * chore: add-harness-tests * chore: regenerate nitrogen output for 0.35.5 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: improve network inspector * chore: remove bun.lock * chore: add nitro image tests * chore: lint * chore: lint * chore: lint * chore: fix ios * chore: fix ios * chore: fix nitro image * chore: fix nitro image * chore: fix nitro image * chore: fix nitro image --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 2acd8e8 commit cf95e2d

32 files changed

Lines changed: 1810 additions & 173 deletions

.github/workflows/build-ios.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ env:
5656
jobs:
5757
build:
5858
name: Build iOS Example App
59-
runs-on: macOS-15
59+
runs-on: macOS-26
6060
steps:
6161
- uses: actions/checkout@v6
6262
- uses: oven-sh/setup-bun@v2
@@ -84,8 +84,8 @@ jobs:
8484
bundler-cache: true
8585
working-directory: example
8686

87-
- name: Select Xcode 16.4
88-
run: sudo xcode-select -s "/Applications/Xcode_16.4.app/Contents/Developer"
87+
- name: Select Xcode 26.2
88+
run: sudo xcode-select -s "/Applications/Xcode_26.2.app/Contents/Developer"
8989

9090
- name: Restore Pods cache
9191
uses: actions/cache@v5
@@ -102,7 +102,7 @@ jobs:
102102
uses: actions/cache@v5
103103
with:
104104
path: example/ios/build
105-
key: ${{ runner.os }}-dd-${{ hashFiles('example/ios/Podfile.lock', 'example/Gemfile.lock', 'example/package.json', 'package.json', 'bun.lock') }}-xcode16.4
105+
key: ${{ runner.os }}-dd-${{ hashFiles('example/ios/Podfile.lock', 'example/Gemfile.lock', 'example/package.json', 'package.json', 'bun.lock') }}-xcode26.2
106106
restore-keys: |
107107
${{ runner.os }}-dd-
108108
@@ -117,7 +117,7 @@ jobs:
117117
-scheme NitroImageExample \
118118
-sdk iphonesimulator \
119119
-configuration Debug \
120-
-destination 'platform=iOS Simulator,name=iPhone 16' \
120+
-destination 'platform=iOS Simulator,name=iPhone 17' \
121121
-showBuildTimingSummary \
122122
ONLY_ACTIVE_ARCH=YES \
123123
build \
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: Harness Android
2+
3+
concurrency:
4+
group: harness-android-${{ github.ref }}
5+
cancel-in-progress: ${{ github.ref_name != 'main' }}
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
device_api_level:
11+
description: "Android API level for the emulator"
12+
required: false
13+
default: "35"
14+
type: string
15+
device_arch:
16+
description: "Device architecture (x86_64, arm64-v8a)"
17+
required: false
18+
default: "x86_64"
19+
type: choice
20+
options:
21+
- x86_64
22+
- arm64-v8a
23+
device_profile:
24+
description: "Device profile"
25+
required: false
26+
default: "pixel_7"
27+
type: string
28+
avd_name:
29+
description: "AVD name"
30+
required: false
31+
default: "Pixel_8_API_35"
32+
type: string
33+
push:
34+
branches:
35+
- main
36+
paths:
37+
- ".github/workflows/harness-android.yml"
38+
- "example/android/**"
39+
- "packages/react-native-nitro-image/android/**"
40+
- "packages/react-native-nitro-web-image/android/**"
41+
- "packages/react-native-nitro-image/src/**"
42+
- "packages/react-native-nitro-web-image/src/**"
43+
- "packages/react-native-nitro-image/nitrogen/**"
44+
- "packages/react-native-nitro-web-image/nitrogen/**"
45+
- "**/bun.lock"
46+
- "**/react-native.config.js"
47+
- "example/__tests__/**"
48+
- "example/rn-harness.config.mjs"
49+
pull_request:
50+
paths:
51+
- ".github/workflows/harness-android.yml"
52+
- "example/android/**"
53+
- "packages/react-native-nitro-image/android/**"
54+
- "packages/react-native-nitro-web-image/android/**"
55+
- "packages/react-native-nitro-image/src/**"
56+
- "packages/react-native-nitro-web-image/src/**"
57+
- "packages/react-native-nitro-image/nitrogen/**"
58+
- "packages/react-native-nitro-web-image/nitrogen/**"
59+
- "**/bun.lock"
60+
- "**/react-native.config.js"
61+
- "example/__tests__/**"
62+
- "example/rn-harness.config.mjs"
63+
64+
env:
65+
DEVICE_API_LEVEL: ${{ github.event.inputs.device_api_level || '35' }}
66+
DEVICE_ARCH: ${{ github.event.inputs.device_arch || 'x86_64' }}
67+
DEVICE_PROFILE: ${{ github.event.inputs.device_profile || 'pixel_7' }}
68+
AVD_NAME: ${{ github.event.inputs.avd_name || 'Pixel_8_API_35' }}
69+
70+
jobs:
71+
harness_android:
72+
name: Harness Android
73+
runs-on: ubuntu-latest
74+
steps:
75+
- uses: actions/checkout@v4
76+
with:
77+
fetch-depth: 1
78+
submodules: recursive
79+
80+
- name: Reclaim disk space
81+
uses: AdityaGarg8/remove-unwanted-software@v5
82+
with:
83+
remove-dotnet: true
84+
remove-haskell: true
85+
remove-codeql: true
86+
remove-docker-images: true
87+
88+
- uses: oven-sh/setup-bun@v2
89+
90+
- name: Install npm dependencies
91+
run: bun install
92+
93+
- name: Setup JDK 17
94+
uses: actions/setup-java@v4
95+
with:
96+
distribution: "zulu"
97+
java-version: 17
98+
java-package: jdk
99+
100+
- name: Restore Gradle cache
101+
uses: actions/cache@v4
102+
with:
103+
path: |
104+
~/.gradle/caches
105+
~/.gradle/wrapper
106+
example/android/.gradle
107+
example/android/app/.cxx
108+
key: ${{ runner.os }}-gradle-${{ env.DEVICE_ARCH }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
109+
restore-keys: |
110+
${{ runner.os }}-gradle-${{ env.DEVICE_ARCH }}-
111+
${{ runner.os }}-gradle-
112+
113+
- name: Build Android app
114+
working-directory: example/android
115+
run: ./gradlew :app:assembleDebug --no-daemon --build-cache -PreactNativeArchitectures=${{ env.DEVICE_ARCH }}
116+
117+
- name: Enable KVM group perms
118+
run: |
119+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
120+
sudo udevadm control --reload-rules
121+
sudo udevadm trigger --name-match=kvm
122+
ls /dev/kvm
123+
124+
- name: AVD cache
125+
uses: actions/cache@v4
126+
id: avd-cache
127+
with:
128+
path: |
129+
~/.android/avd/*
130+
~/.android/adb*
131+
key: avd-${{ env.DEVICE_API_LEVEL }}-${{ env.DEVICE_ARCH }}
132+
133+
- name: Create AVD and generate snapshot for caching
134+
if: steps.avd-cache.outputs.cache-hit != 'true'
135+
uses: reactivecircus/android-emulator-runner@v2
136+
with:
137+
api-level: ${{ env.DEVICE_API_LEVEL }}
138+
arch: ${{ env.DEVICE_ARCH }}
139+
profile: ${{ env.DEVICE_PROFILE }}
140+
disk-size: 1G
141+
heap-size: 1G
142+
force-avd-creation: false
143+
avd-name: ${{ env.AVD_NAME }}
144+
disable-animations: true
145+
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
146+
script: echo "Generated AVD snapshot for caching."
147+
148+
- name: Run Harness E2E tests
149+
uses: reactivecircus/android-emulator-runner@v2
150+
with:
151+
working-directory: example
152+
api-level: ${{ env.DEVICE_API_LEVEL }}
153+
arch: ${{ env.DEVICE_ARCH }}
154+
force-avd-creation: false
155+
avd-name: ${{ env.AVD_NAME }}
156+
disable-animations: true
157+
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
158+
script: |
159+
adb install -r "./android/app/build/outputs/apk/debug/app-debug.apk"
160+
bun run test:harness --harnessRunner android
161+
162+
- name: Stop Gradle Daemon
163+
working-directory: example/android
164+
run: ./gradlew --stop

.github/workflows/harness-ios.yml

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
name: Harness iOS
2+
3+
concurrency:
4+
group: harness-ios-${{ github.ref }}
5+
cancel-in-progress: ${{ github.ref_name != 'main' }}
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
device_model:
11+
description: "iOS Simulator device model"
12+
required: false
13+
default: "iPhone 17 Pro"
14+
type: string
15+
ios_version:
16+
description: "iOS version"
17+
required: false
18+
default: "26.2"
19+
type: string
20+
xcode_version:
21+
description: "Xcode version"
22+
required: false
23+
default: "26.2.0"
24+
type: string
25+
push:
26+
branches:
27+
- main
28+
paths:
29+
- ".github/workflows/harness-ios.yml"
30+
- "example/ios/**"
31+
- "packages/react-native-nitro-image/ios/**"
32+
- "packages/react-native-nitro-web-image/ios/**"
33+
- "packages/react-native-nitro-image/src/**"
34+
- "packages/react-native-nitro-web-image/src/**"
35+
- "packages/react-native-nitro-image/nitrogen/**"
36+
- "packages/react-native-nitro-web-image/nitrogen/**"
37+
- "**/Podfile.lock"
38+
- "**/*.podspec"
39+
- "**/bun.lock"
40+
- "**/react-native.config.js"
41+
- "example/__tests__/**"
42+
- "example/rn-harness.config.mjs"
43+
pull_request:
44+
paths:
45+
- ".github/workflows/harness-ios.yml"
46+
- "example/ios/**"
47+
- "packages/react-native-nitro-image/ios/**"
48+
- "packages/react-native-nitro-web-image/ios/**"
49+
- "packages/react-native-nitro-image/src/**"
50+
- "packages/react-native-nitro-web-image/src/**"
51+
- "packages/react-native-nitro-image/nitrogen/**"
52+
- "packages/react-native-nitro-web-image/nitrogen/**"
53+
- "**/Podfile.lock"
54+
- "**/*.podspec"
55+
- "**/bun.lock"
56+
- "**/react-native.config.js"
57+
- "example/__tests__/**"
58+
- "example/rn-harness.config.mjs"
59+
60+
env:
61+
DEVICE_MODEL: ${{ github.event.inputs.device_model || 'iPhone 17 Pro' }}
62+
IOS_VERSION: ${{ github.event.inputs.ios_version || '26.2' }}
63+
XCODE_VERSION: ${{ github.event.inputs.xcode_version || '26.2.0' }}
64+
USE_CCACHE: 1
65+
DEVELOPER_DIR: /Applications/Xcode_${{ github.event.inputs.xcode_version || '26.2.0' }}.app/Contents/Developer
66+
67+
jobs:
68+
harness_ios:
69+
name: Harness iOS
70+
runs-on: macOS-26
71+
steps:
72+
- uses: actions/checkout@v4
73+
with:
74+
fetch-depth: 1
75+
submodules: recursive
76+
77+
- uses: oven-sh/setup-bun@v2
78+
79+
- name: Install npm dependencies
80+
run: bun install
81+
82+
- name: Install Ccache
83+
uses: hendrikmuhs/ccache-action@v1.2
84+
with:
85+
max-size: 1.5G
86+
key: ${{ runner.os }}-ccache-nitroimage-ios
87+
create-symlink: true
88+
89+
- name: Setup ccache behavior
90+
run: |
91+
echo "CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros" >> $GITHUB_ENV
92+
echo "CCACHE_FILECLONE=true" >> $GITHUB_ENV
93+
echo "CCACHE_DEPEND=true" >> $GITHUB_ENV
94+
echo "CCACHE_INODECACHE=true" >> $GITHUB_ENV
95+
96+
- name: Setup Ruby (bundle)
97+
uses: ruby/setup-ruby@v1
98+
with:
99+
ruby-version: 3.2.0
100+
bundler-cache: true
101+
working-directory: example
102+
103+
- name: Select Xcode ${{ env.XCODE_VERSION }}
104+
run: sudo xcode-select -s "/Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer"
105+
106+
- name: Restore Pods cache
107+
uses: actions/cache@v4
108+
with:
109+
path: example/ios/Pods
110+
key: ${{ runner.os }}-pods-nitroimage-${{ hashFiles('**/Podfile.lock', '**/Gemfile.lock') }}
111+
restore-keys: |
112+
${{ runner.os }}-pods-nitroimage-
113+
114+
- name: Install Pods
115+
working-directory: example
116+
run: bundle exec pod install --project-directory=ios
117+
118+
- name: Restore DerivedData cache
119+
uses: actions/cache@v4
120+
with:
121+
path: example/ios/build
122+
key: ${{ runner.os }}-dd-nitroimage-${{ hashFiles('**/Podfile.lock', '**/Gemfile.lock', '**/package.json', '**/bun.lock') }}-xcode${{ env.XCODE_VERSION }}
123+
restore-keys: |
124+
${{ runner.os }}-dd-nitroimage-
125+
126+
- name: Build iOS app
127+
working-directory: example/ios
128+
run: |
129+
set -o pipefail
130+
xcodebuild \
131+
CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \
132+
-derivedDataPath build -UseModernBuildSystem=YES \
133+
-workspace NitroImageExample.xcworkspace \
134+
-scheme NitroImageExample \
135+
-sdk iphonesimulator \
136+
-configuration Debug \
137+
-destination 'platform=iOS Simulator,name=${{ env.DEVICE_MODEL }}' \
138+
-showBuildTimingSummary \
139+
ONLY_ACTIVE_ARCH=YES \
140+
build \
141+
CODE_SIGNING_ALLOWED=NO | xcbeautify --renderer github-actions
142+
143+
- name: Setup iOS Simulator
144+
uses: futureware-tech/simulator-action@v5
145+
with:
146+
model: ${{ env.DEVICE_MODEL }}
147+
os: iOS
148+
os_version: ${{ env.IOS_VERSION }}
149+
wait_for_boot: true
150+
erase_before_boot: false
151+
152+
- name: Install app
153+
run: |
154+
xcrun simctl install booted example/ios/build/Build/Products/Debug-iphonesimulator/NitroImageExample.app
155+
156+
- name: Run Harness E2E tests
157+
working-directory: example
158+
run: |
159+
bun run test:harness --harnessRunner ios

.github/workflows/run-nitrogen.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ jobs:
3737
run: bun web-image specs
3838

3939
- name: Verify no files have changed after nitrogen
40-
run: git diff --exit-code HEAD -- . ':(exclude)bun.lockb'
40+
run: git diff --exit-code HEAD -- . ':(exclude)bun.lockb' ':(exclude)bun.lock'

biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.3.14/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.4.13/schema.json",
33
"vcs": {
44
"enabled": true,
55
"clientKind": "git",

0 commit comments

Comments
 (0)