Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
Expand Down
223 changes: 221 additions & 2 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
e2e-android:
name: E2E Android
runs-on: ubuntu-22.04
timeout-minutes: 30
if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android')) }}
env:
HARNESS_DEBUG: true

steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -108,6 +108,7 @@ jobs:
e2e-ios:
name: E2E iOS
runs-on: macos-latest
timeout-minutes: 30
if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios')) }}
steps:
- name: Checkout code
Expand Down Expand Up @@ -194,10 +195,10 @@ jobs:
e2e-web:
name: E2E Web
runs-on: ubuntu-22.04
timeout-minutes: 30
if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'web')) }}
env:
HARNESS_DEBUG: true

steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -237,3 +238,221 @@ jobs:
with:
runner: chromium
projectRoot: apps/playground

crash-validate-android:
name: Crash Validation Android
runs-on: ubuntu-22.04
timeout-minutes: 30
if: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android') }}
env:
HARNESS_DEBUG: true

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
fetch-depth: 0

- name: Reclaim disk space
uses: AdityaGarg8/remove-unwanted-software@v5
with:
remove-dotnet: true
remove-haskell: true
remove-codeql: true
remove-docker-images: true

- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: latest

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24.10.0'
cache: 'pnpm'

- name: Metro cache
uses: actions/cache@v4
with:
path: apps/playground/node_modules/.cache/rn-harness/metro-cache
key: metro-cache-${{ hashFiles('apps/playground/node_modules/.cache/rn-harness/metro-cache/**/*') }}
restore-keys: |
metro-cache

- name: Install dependencies
run: |
pnpm install

- name: Build packages
run: |
pnpm nx run-many -t build --projects="packages/*"

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

- name: Restore APK from cache
id: cache-apk-restore
uses: actions/cache/restore@v4
with:
path: apps/playground/android/app/build/outputs/apk/debug/app-debug.apk
key: apk-playground

- name: Build Android app
if: steps.cache-apk-restore.outputs.cache-hit != 'true'
working-directory: apps/playground
run: |
pnpm nx run @react-native-harness/playground:build-android --tasks=assembleDebug

- name: Save APK to cache
if: steps.cache-apk-restore.outputs.cache-hit != 'true' && success()
uses: actions/cache/save@v4
with:
path: apps/playground/android/app/build/outputs/apk/debug/app-debug.apk
key: apk-playground

- name: Run React Native Harness (expect crash)
id: crash-test
continue-on-error: true
uses: ./actions/android
with:
app: android/app/build/outputs/apk/debug/app-debug.apk
runner: android-crash-pre-rn
projectRoot: apps/playground
harnessArgs: --testPathPattern smoke

- name: Verify crash was detected
shell: bash
run: |
if [ "${{ steps.crash-test.outcome }}" != "failure" ]; then
echo "ERROR: Expected harness to fail (crash not detected)"
exit 1
fi
echo "Crash was correctly detected by the harness"

- name: Verify crash artifacts exist
shell: bash
run: |
CRASH_DIR="apps/playground/.harness/crash-reports"
if [ -d "$CRASH_DIR" ] && [ "$(ls -A "$CRASH_DIR" 2>/dev/null)" ]; then
echo "Crash report artifacts found:"
ls -la "$CRASH_DIR"
else
echo "ERROR: No crash report artifacts found in $CRASH_DIR"
exit 1
fi

crash-validate-ios:
name: Crash Validation iOS
runs-on: macos-latest
timeout-minutes: 30
if: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios') }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
fetch-depth: 0

- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: latest

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24.10.0'
cache: 'pnpm'

- name: Metro cache
uses: actions/cache@v4
with:
path: apps/playground/node_modules/.cache/rn-harness/metro-cache
key: metro-cache-${{ hashFiles('apps/playground/node_modules/.cache/rn-harness/metro-cache/**/*') }}
restore-keys: |
metro-cache

- name: Install Watchman
run: brew install watchman

- name: Install dependencies
run: |
pnpm install

- name: Build packages
run: |
pnpm nx run-many -t build --projects="packages/*"

- name: Restore app from cache
id: cache-app-restore
uses: actions/cache/restore@v4
with:
path: ./apps/playground/ios/build/Build/Products/Debug-iphonesimulator/HarnessPlayground.app
key: ios-app-playground

- name: CocoaPods cache
if: steps.cache-app-restore.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: |
./apps/playground/ios/Pods
~/Library/Caches/CocoaPods
~/.cocoapods
key: playground-${{ runner.os }}-pods-${{ hashFiles('./apps/playground/ios/Podfile.lock') }}
restore-keys: |
playground-${{ runner.os }}-pods-

- name: Install CocoaPods
if: steps.cache-app-restore.outputs.cache-hit != 'true'
working-directory: apps/playground/ios
run: |
pod install

- name: Build iOS app
if: steps.cache-app-restore.outputs.cache-hit != 'true'
working-directory: apps/playground
run: |
pnpm react-native build-ios --buildFolder ./build --verbose

- name: Save app to cache
if: steps.cache-app-restore.outputs.cache-hit != 'true' && success()
uses: actions/cache/save@v4
with:
path: ./apps/playground/ios/build/Build/Products/Debug-iphonesimulator/HarnessPlayground.app
key: ios-app-playground

- name: Run React Native Harness (expect crash)
id: crash-test
continue-on-error: true
uses: ./actions/ios
with:
app: ios/build/Build/Products/Debug-iphonesimulator/HarnessPlayground.app
runner: ios-crash-pre-rn
projectRoot: apps/playground
harnessArgs: --testPathPattern smoke

- name: Verify crash was detected
shell: bash
run: |
if [ "${{ steps.crash-test.outcome }}" != "failure" ]; then
echo "ERROR: Expected harness to fail (crash not detected)"
exit 1
fi
echo "Crash was correctly detected by the harness"

- name: Verify crash artifacts exist
shell: bash
run: |
CRASH_DIR="apps/playground/.harness/crash-reports"
if [ -d "$CRASH_DIR" ] && [ "$(ls -A "$CRASH_DIR" 2>/dev/null)" ]; then
echo "Crash report artifacts found:"
ls -la "$CRASH_DIR"
else
echo "ERROR: No crash report artifacts found in $CRASH_DIR"
exit 1
fi
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ yarn-error.log

# testing
/coverage
.harness/
vite.config.*.timestamp*
vitest.config.*.timestamp*

Expand All @@ -128,4 +129,3 @@ npm-debug.*
*.orig.*
web-build/
cache/

14 changes: 13 additions & 1 deletion actions/android/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ inputs:
required: false
type: boolean
default: 'true'
harnessArgs:
description: Additional arguments to pass to the Harness CLI
required: false
type: string
default: ''
runs:
using: 'composite'
steps:
Expand Down Expand Up @@ -136,7 +141,7 @@ runs:
script: |
echo $(pwd)
adb install -r ${{ inputs.app }}
${{ steps.detect-pm.outputs.runner }}react-native-harness --harnessRunner ${{ inputs.runner }}
${{ steps.detect-pm.outputs.runner }}react-native-harness --harnessRunner ${{ inputs.runner }} ${{ inputs.harnessArgs }}
- name: Upload visual test artifacts
if: always() && inputs.uploadVisualTestArtifacts == 'true'
uses: actions/upload-artifact@v4
Expand All @@ -146,3 +151,10 @@ runs:
${{ inputs.projectRoot }}/**/__image_snapshots__/**/*-diff.png
${{ inputs.projectRoot }}/**/__image_snapshots__/**/*-actual.png
if-no-files-found: ignore
- name: Upload crash report artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: harness-crash-reports-android
path: ${{ inputs.projectRoot }}/.harness/crash-reports/**/*
if-no-files-found: ignore
14 changes: 13 additions & 1 deletion actions/ios/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ inputs:
required: false
type: boolean
default: 'true'
harnessArgs:
description: Additional arguments to pass to the Harness CLI
required: false
type: string
default: ''
runs:
using: 'composite'
steps:
Expand Down Expand Up @@ -63,7 +68,7 @@ runs:
- name: Run E2E tests
shell: bash
working-directory: ${{ inputs.projectRoot }}
run: ${{ steps.detect-pm.outputs.runner }}react-native-harness --harnessRunner ${{ inputs.runner }}
run: ${{ steps.detect-pm.outputs.runner }}react-native-harness --harnessRunner ${{ inputs.runner }} ${{ inputs.harnessArgs }}
- name: Upload visual test artifacts
if: always() && inputs.uploadVisualTestArtifacts == 'true'
uses: actions/upload-artifact@v4
Expand All @@ -73,3 +78,10 @@ runs:
${{ inputs.projectRoot }}/**/__image_snapshots__/**/*-diff.png
${{ inputs.projectRoot }}/**/__image_snapshots__/**/*-actual.png
if-no-files-found: ignore
- name: Upload crash report artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: harness-crash-reports-ios
path: ${{ inputs.projectRoot }}/.harness/crash-reports/**/*
if-no-files-found: ignore
Loading
Loading