Skip to content
Merged
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
102 changes: 102 additions & 0 deletions .github/workflows/jest-detox.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
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:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
permissions:
contents: read
runs-on: ubuntu-latest
timeout-minutes: 60
defaults:
run:
working-directory: generic-reporter/jest/detox
env:
CURRENTS_PROJECT_ID: X7niCl
HAS_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 <sha> into <sha>" 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"
# A random delimiter: a commit message line equal to a fixed one would end the
# value early and add the lines after it as variables.
delimiter="EOF_$(openssl rand -hex 16)"
{
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<<$delimiter"
git log -1 --format=%B "$HEAD_SHA"
echo "$delimiter"
} >> "$GITHUB_ENV"

# Runs after `detox test` exits, when Detox has finished writing the
# videos and logs.
- name: Upload the results to Currents
# Pull requests from forks get no secrets and skip the upload.
if: ${{ !cancelled() && env.HAS_RECORD_KEY == 'true' }}
env:
CURRENTS_RECORD_KEY: ${{ secrets.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
39 changes: 20 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 |
43 changes: 43 additions & 0 deletions generic-reporter/jest/detox/.detoxrc.js
Original file line number Diff line number Diff line change
@@ -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 currents upload sends with the run.
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: {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"android.emu.release": { device: "emulator", app: "android.release" },
"android.att.release": { device: "attached", app: "android.release" },
},
};
79 changes: 79 additions & 0 deletions generic-reporter/jest/detox/.gitignore
Original file line number Diff line number Diff line change
@@ -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/
1 change: 1 addition & 0 deletions generic-reporter/jest/detox/.watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
96 changes: 96 additions & 0 deletions generic-reporter/jest/detox/App.tsx
Original file line number Diff line number Diff line change
@@ -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<string | null>(null);

return (
<SafeAreaProvider>
<SafeAreaView style={styles.container}>
{user ? (
<Counter user={user} onLogout={() => setUser(null)} />
) : (
<Login onLogin={setUser} />
)}
</SafeAreaView>
</SafeAreaProvider>
);
}

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 (
<View style={styles.screen}>
<Text style={styles.title}>Sign in</Text>
<TextInput
testID="email"
style={styles.input}
placeholder="Email"
autoCapitalize="none"
value={email}
onChangeText={setEmail}
/>
<TextInput
testID="password"
style={styles.input}
placeholder="Password"
secureTextEntry
value={password}
onChangeText={setPassword}
/>
{error && (
<Text testID="login-error" style={styles.error}>
Wrong email or password
</Text>
)}
<Button testID="login" title="Sign in" onPress={submit} />
</View>
);
}

function Counter({ user, onLogout }: { user: string; onLogout: () => void }) {
const [count, setCount] = useState(0);

return (
<View style={styles.screen}>
<Text testID="welcome" style={styles.title}>
Hi, {user}
</Text>
<Text testID="count" style={styles.count}>
{count}
</Text>
<Button
testID="increment"
title="Add one"
onPress={() => setCount((c) => c + 1)}
/>
<Button testID="reset" title="Reset" onPress={() => setCount(0)} />
<Button testID="logout" title="Sign out" onPress={onLogout} />
</View>
);
}

const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: "#fff" },
screen: { flex: 1, justifyContent: "center", padding: 24, gap: 12 },
title: { fontSize: 24, fontWeight: "600", textAlign: "center" },
count: { fontSize: 48, textAlign: "center" },
input: { borderWidth: 1, borderColor: "#ccc", borderRadius: 6, padding: 10 },
error: { color: "#c00", textAlign: "center" },
});

export default App;
Loading
Loading