From 4a4a52656b102eaa2d76423f2e925b67877051d8 Mon Sep 17 00:00:00 2001 From: Andrew Goldis Date: Wed, 23 Sep 2026 14:25:50 -0700 Subject: [PATCH 1/5] feat: add a Detox + Jest example that reports to Currents Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01915SucXVV7T3pGvJxemJwh --- .github/workflows/jest-detox.yml | 94 + README.md | 39 +- generic-reporter/jest/detox/.detoxrc.js | 43 + generic-reporter/jest/detox/.gitignore | 79 + generic-reporter/jest/detox/.watchmanconfig | 1 + generic-reporter/jest/detox/App.tsx | 96 + generic-reporter/jest/detox/README.md | 88 + .../jest/detox/android/app/build.gradle | 124 + .../jest/detox/android/app/debug.keystore | Bin 0 -> 2257 bytes .../jest/detox/android/app/proguard-rules.pro | 10 + .../java/com/detoxdemo/DetoxTest.java | 29 + .../android/app/src/main/AndroidManifest.xml | 28 + .../main/java/com/detoxdemo/MainActivity.kt | 22 + .../java/com/detoxdemo/MainApplication.kt | 27 + .../res/drawable/rn_edit_text_material.xml | 37 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3056 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5024 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2096 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2858 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4569 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7098 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6464 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10676 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9250 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15523 bytes .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/styles.xml | 9 + .../main/res/xml/network_security_config.xml | 7 + .../jest/detox/android/build.gradle | 29 + .../jest/detox/android/gradle.properties | 44 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 46175 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + generic-reporter/jest/detox/android/gradlew | 248 + .../jest/detox/android/gradlew.bat | 98 + .../jest/detox/android/settings.gradle | 6 + generic-reporter/jest/detox/app.json | 4 + generic-reporter/jest/detox/babel.config.js | 3 + .../jest/detox/e2e/counter.test.js | 30 + .../jest/detox/e2e/jest.config.js | 12 + generic-reporter/jest/detox/e2e/login.test.js | 22 + generic-reporter/jest/detox/e2e/signIn.js | 9 + .../jest/detox/e2e/signOut.test.js | 18 + generic-reporter/jest/detox/index.js | 9 + generic-reporter/jest/detox/metro.config.js | 11 + generic-reporter/jest/detox/package-lock.json | 15158 ++++++++++++++++ generic-reporter/jest/detox/package.json | 37 + generic-reporter/jest/detox/tsconfig.json | 8 + 47 files changed, 16470 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/jest-detox.yml create mode 100644 generic-reporter/jest/detox/.detoxrc.js create mode 100644 generic-reporter/jest/detox/.gitignore create mode 100644 generic-reporter/jest/detox/.watchmanconfig create mode 100644 generic-reporter/jest/detox/App.tsx create mode 100644 generic-reporter/jest/detox/README.md create mode 100644 generic-reporter/jest/detox/android/app/build.gradle create mode 100644 generic-reporter/jest/detox/android/app/debug.keystore create mode 100644 generic-reporter/jest/detox/android/app/proguard-rules.pro create mode 100644 generic-reporter/jest/detox/android/app/src/androidTest/java/com/detoxdemo/DetoxTest.java create mode 100644 generic-reporter/jest/detox/android/app/src/main/AndroidManifest.xml create mode 100644 generic-reporter/jest/detox/android/app/src/main/java/com/detoxdemo/MainActivity.kt create mode 100644 generic-reporter/jest/detox/android/app/src/main/java/com/detoxdemo/MainApplication.kt create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/drawable/rn_edit_text_material.xml create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/values/strings.xml create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/values/styles.xml create mode 100644 generic-reporter/jest/detox/android/app/src/main/res/xml/network_security_config.xml create mode 100644 generic-reporter/jest/detox/android/build.gradle create mode 100644 generic-reporter/jest/detox/android/gradle.properties create mode 100644 generic-reporter/jest/detox/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 generic-reporter/jest/detox/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 generic-reporter/jest/detox/android/gradlew create mode 100644 generic-reporter/jest/detox/android/gradlew.bat create mode 100644 generic-reporter/jest/detox/android/settings.gradle create mode 100644 generic-reporter/jest/detox/app.json create mode 100644 generic-reporter/jest/detox/babel.config.js create mode 100644 generic-reporter/jest/detox/e2e/counter.test.js create mode 100644 generic-reporter/jest/detox/e2e/jest.config.js create mode 100644 generic-reporter/jest/detox/e2e/login.test.js create mode 100644 generic-reporter/jest/detox/e2e/signIn.js create mode 100644 generic-reporter/jest/detox/e2e/signOut.test.js create mode 100644 generic-reporter/jest/detox/index.js create mode 100644 generic-reporter/jest/detox/metro.config.js create mode 100644 generic-reporter/jest/detox/package-lock.json create mode 100644 generic-reporter/jest/detox/package.json create mode 100644 generic-reporter/jest/detox/tsconfig.json diff --git a/.github/workflows/jest-detox.yml b/.github/workflows/jest-detox.yml new file mode 100644 index 0000000..cf7fbed --- /dev/null +++ b/.github/workflows/jest-detox.yml @@ -0,0 +1,94 @@ +name: Jest + Detox + +on: + push: + branches: [main] + paths: + ["generic-reporter/jest/detox/**", ".github/workflows/jest-detox.yml"] + pull_request: + paths: + ["generic-reporter/jest/detox/**", ".github/workflows/jest-detox.yml"] + workflow_dispatch: + +jobs: + android: + runs-on: ubuntu-latest + timeout-minutes: 60 + defaults: + run: + working-directory: generic-reporter/jest/detox + env: + CURRENTS_PROJECT_ID: X7niCl + CURRENTS_RECORD_KEY: ${{ secrets.CURRENTS_RECORD_KEY }} + CURRENTS_CI_BUILD_ID: ${{ github.repository }}-detox-${{ github.run_id }}-${{ github.run_attempt }} + + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-node@v6 + with: + node-version: 24 + cache: npm + cache-dependency-path: generic-reporter/jest/detox/package-lock.json + + - uses: actions/setup-java@v6 + with: + distribution: temurin + java-version: 17 + + - uses: gradle/actions/setup-gradle@v6 + + - run: npm ci + + - name: Build the app + run: npx detox build --configuration android.att.release + + - name: Enable KVM for the emulator + working-directory: . + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Run the tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 34 + target: google_apis + arch: x86_64 + disable-animations: true + working-directory: generic-reporter/jest/detox + script: npx detox test --configuration android.att.release --retries 1 --headless + + # A pull_request run checks out a merge commit GitHub creates, so without + # this step Currents shows "Merge into " as the commit message. + # `currents upload` reads the COMMIT_INFO_* variables before git. + - name: Use the pull request commit for Currents + if: ${{ !cancelled() && github.event_name == 'pull_request' }} + env: + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + HEAD_REF: ${{ github.event.pull_request.head.ref }} + run: | + git fetch --depth=1 origin "$HEAD_SHA" + { + echo "COMMIT_INFO_SHA=$HEAD_SHA" + echo "COMMIT_INFO_BRANCH=$HEAD_REF" + echo "COMMIT_INFO_AUTHOR=$(git log -1 --format=%an "$HEAD_SHA")" + echo "COMMIT_INFO_EMAIL=$(git log -1 --format=%ae "$HEAD_SHA")" + echo "COMMIT_INFO_MESSAGE<> "$GITHUB_ENV" + + # Runs after `detox test` exits, when Detox has finished writing the + # videos and logs. + - name: Upload the results to Currents + if: ${{ !cancelled() && env.CURRENTS_RECORD_KEY != '' }} + run: npx currents upload + + - name: Keep the Detox artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v7 + with: + name: detox-artifacts + path: generic-reporter/jest/detox/artifacts diff --git a/README.md b/README.md index 0313195..dd38513 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,20 @@ Examples demonstrating Playwright integration with Currents, including sharding, ### CI -| Example | Description | -| :-------------------------------------------------------- | :-------------------------------------------------------------------- | -| [**AWS CodeBuild**](playwright/ci/aws-codebuild/) | Run Playwright tests in AWS CodeBuild | -| [**Azure DevOps**](playwright/ci/azure-devops/) | Integration with Azure DevOps pipelines | -| [**Buildkite**](playwright/ci/buildkite/) | Run Playwright tests in Buildkite | -| [**CircleCI**](playwright/ci/circleci/) | Run Playwright tests in CircleCI | -| [**GitHub Actions**](playwright/ci/github-actions/) | Comprehensive GitHub Actions workflow | -| [**GitHub Actions — Basic Setup**](playwright/ci/github-actions/setup-ci/) | Standard CI setup with sharding and reporting | -| [**GitHub Actions — Orchestration**](playwright/ci/github-actions/orchestration/) | Optimized parallel execution with load balancing | -| [**GitHub Actions — Rerun Failed**](playwright/ci/github-actions/rerun-failed/) | Rerun only failed tests from a previous build | -| [**GitHub Actions — Visual Testing**](playwright/ci/github-actions/argos/) | Integration with Argos for visual regression testing | -| [**GitLab CI**](gitlab/) | Playwright + Currents on GitLab CI ([source on GitLab](https://gitlab.com/currents.dev/gitlab-playwright-currents)) | -| [**Jenkins**](playwright/ci/jenkins/jenkins-last-failed/) | Advanced Jenkins setup with Docker, Sharding, and "Last Failed" rerun | -| [**Nx Monorepo**](playwright/ci/nx/) | Playwright in an Nx workspace | +| Example | Description | +| :-------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------ | +| [**AWS CodeBuild**](playwright/ci/aws-codebuild/) | Run Playwright tests in AWS CodeBuild | +| [**Azure DevOps**](playwright/ci/azure-devops/) | Integration with Azure DevOps pipelines | +| [**Buildkite**](playwright/ci/buildkite/) | Run Playwright tests in Buildkite | +| [**CircleCI**](playwright/ci/circleci/) | Run Playwright tests in CircleCI | +| [**GitHub Actions**](playwright/ci/github-actions/) | Comprehensive GitHub Actions workflow | +| [**GitHub Actions — Basic Setup**](playwright/ci/github-actions/setup-ci/) | Standard CI setup with sharding and reporting | +| [**GitHub Actions — Orchestration**](playwright/ci/github-actions/orchestration/) | Optimized parallel execution with load balancing | +| [**GitHub Actions — Rerun Failed**](playwright/ci/github-actions/rerun-failed/) | Rerun only failed tests from a previous build | +| [**GitHub Actions — Visual Testing**](playwright/ci/github-actions/argos/) | Integration with Argos for visual regression testing | +| [**GitLab CI**](gitlab/) | Playwright + Currents on GitLab CI ([source on GitLab](https://gitlab.com/currents.dev/gitlab-playwright-currents)) | +| [**Jenkins**](playwright/ci/jenkins/jenkins-last-failed/) | Advanced Jenkins setup with Docker, Sharding, and "Last Failed" rerun | +| [**Nx Monorepo**](playwright/ci/nx/) | Playwright in an Nx workspace | ### Features @@ -52,8 +52,9 @@ Examples demonstrating Cypress integration with Currents. Examples for other test runners using Currents' generic reporters. -| Example | Description | -| :------------------------------------------------------------------- | :-------------------------------------- | -| [**Jest**](generic-reporter/jest/github-actions/) | Reporting Jest results to Currents | -| [**JUnit XML**](generic-reporter/junit/junit-xml/) | Uploading generic JUnit XML reports | -| [**Node.js / JUnit**](generic-reporter/junit/nodejs-github-actions/) | Node.js project reporting JUnit results | +| Example | Description | +| :------------------------------------------------------------------- | :------------------------------------------------------------------- | +| [**Jest**](generic-reporter/jest/github-actions/) | Reporting Jest results to Currents | +| [**Detox + Jest**](generic-reporter/jest/detox/) | React Native Detox tests with videos, screenshots, steps and retries | +| [**JUnit XML**](generic-reporter/junit/junit-xml/) | Uploading generic JUnit XML reports | +| [**Node.js / JUnit**](generic-reporter/junit/nodejs-github-actions/) | Node.js project reporting JUnit results | diff --git a/generic-reporter/jest/detox/.detoxrc.js b/generic-reporter/jest/detox/.detoxrc.js new file mode 100644 index 0000000..f2262fa --- /dev/null +++ b/generic-reporter/jest/detox/.detoxrc.js @@ -0,0 +1,43 @@ +/** @type {Detox.DetoxConfig} */ +module.exports = { + testRunner: { + args: { + $0: "jest", + config: "e2e/jest.config.js", + }, + jest: { + setupTimeout: 240000, + }, + }, + artifacts: { + plugins: { + // Logs also make Detox write detox.trace.json, which becomes the test steps in Currents. + log: "all", + screenshot: "failing", + video: "failing", + }, + }, + apps: { + "android.release": { + type: "android.apk", + binaryPath: "android/app/build/outputs/apk/release/app-release.apk", + build: + "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release", + }, + }, + devices: { + emulator: { + type: "android.emulator", + device: { avdName: process.env.DETOX_AVD_NAME || "Pixel_7_API_34" }, + }, + // An emulator that is already running, such as the one CI starts. + attached: { + type: "android.attached", + device: { adbName: ".*" }, + }, + }, + configurations: { + "android.emu.release": { device: "emulator", app: "android.release" }, + "android.att.release": { device: "attached", app: "android.release" }, + }, +}; diff --git a/generic-reporter/jest/detox/.gitignore b/generic-reporter/jest/detox/.gitignore new file mode 100644 index 0000000..26115f5 --- /dev/null +++ b/generic-reporter/jest/detox/.gitignore @@ -0,0 +1,79 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +**/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +*.keystore +!debug.keystore +.kotlin/ + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +**/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage + +# Yarn +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Detox and Currents output +artifacts/ +.currents/ diff --git a/generic-reporter/jest/detox/.watchmanconfig b/generic-reporter/jest/detox/.watchmanconfig new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/generic-reporter/jest/detox/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/generic-reporter/jest/detox/App.tsx b/generic-reporter/jest/detox/App.tsx new file mode 100644 index 0000000..acdcaeb --- /dev/null +++ b/generic-reporter/jest/detox/App.tsx @@ -0,0 +1,96 @@ +import { useState } from "react"; +import { Button, StyleSheet, Text, TextInput, View } from "react-native"; +import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"; + +const PASSWORD = "currents"; + +function App() { + const [user, setUser] = useState(null); + + return ( + + + {user ? ( + setUser(null)} /> + ) : ( + + )} + + + ); +} + +function Login({ onLogin }: { onLogin: (email: string) => void }) { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(false); + + const submit = () => { + if (email && password === PASSWORD) { + onLogin(email); + } else { + setError(true); + } + }; + + return ( + + Sign in + + + {error && ( + + Wrong email or password + + )} +