本文へ移動
cccskills
無料GitHub で公開

detox

Detox is a gray-box end-to-end testing framework for React Native apps: it runs Jest tests against the app on an iOS simulator or Android emulator and waits for the app to go idle before each step. Use when the user wants to set up Detox, write or fix React Native E2E tests, debug a test that hangs or cannot find an element, or run Detox in CI. Also use when the user mentions "detox," "React Native E2E," "gray-box testing," "detox build," or "Wix Detox." For black-box testing of any mobile app, see appium; for simple YAML UI flows, see maestro.

インストール方法を見る

含まれるファイル(2)

  • SKILL.md13.9 KB
  • _scores.json1.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Detox

Overview

Detox is the gray-box end-to-end testing framework for React Native apps by Wix. Tests are written in JavaScript, run by Jest on your machine, and drive the real app on an iOS simulator or Android emulator. Because Detox runs inside the app as well, it knows when animations, timers and network requests are in flight and waits for the app to become idle before every action and assertion, which removes most timing flakiness without sleep calls. The price is setup: Detox needs a test build of the app per platform and a few native changes on Android.

Instructions

Initial Assessment

  1. Platform — iOS, Android, or both? iOS tests only run on macOS.
  2. React Native version — bare React Native or Expo? Detox has no Expo-specific support, and the Expo guide that the Detox docs link to now covers Maestro; treat Detox on Expo as community-maintained.
  3. CI — Which CI provider? (GitHub Actions, CircleCI, Bitrise)
  4. Current state — New project or adding tests to existing app?

Setup

# Run in the React Native project root
npm install "jest@^29" --save-dev      # pin the major so an old lockfile cannot pull Jest 26
npm install detox --save-dev

# iOS only (macOS): simulator control tool required by Detox
brew tap wix/brew
brew install applesimutils

# Creates .detoxrc.js, e2e/jest.config.js and e2e/starter.test.js
npx detox init

npm install -g detox-cli is optional: it only lets you type detox instead of npx detox.

Configuration

// .detoxrc.js — apps (how to build, where the binary is), devices, and their combinations
/** @type {Detox.DetoxConfig} */
module.exports = {
  testRunner: {
    args: { $0: 'jest', config: 'e2e/jest.config.js' },
    jest: { setupTimeout: 120000 },
  },
  apps: {
    'ios.debug': {
      type: 'ios.app',
      binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/FieldNotes.app',
      build: 'xcodebuild -workspace ios/FieldNotes.xcworkspace -scheme FieldNotes -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
    },
    'ios.release': {
      type: 'ios.app',
      binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/FieldNotes.app',
      build: 'xcodebuild -workspace ios/FieldNotes.xcworkspace -scheme FieldNotes -configuration Release -sdk iphonesimulator -derivedDataPath ios/build',
    },
    'android.debug': {
      type: 'android.apk',
      binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
      build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
      reversePorts: [8081],
    },
  },
  devices: {
    simulator: { type: 'ios.simulator', device: { type: 'iPhone 16' } },
    emulator: { type: 'android.emulator', device: { avdName: 'Pixel_7_API_34' } },
  },
  configurations: {
    'ios.sim.debug': { device: 'simulator', app: 'ios.debug' },
    'ios.sim.release': { device: 'simulator', app: 'ios.release' },
    'android.emu.debug': { device: 'emulator', app: 'android.debug' },
  },
};

A simulator of that type must already exist (applesimutils --list): Detox clones an existing one and fails with Failed to find a device when there is none. detox init writes iPhone 15, which the GitHub macos-15 image does not have. avdName must be one that emulator -list-avds prints. detox build only runs the build string of the chosen configuration; if it fails, the fix is in the Xcode or Gradle command, not in Detox.

Jest Config for Detox

// e2e/jest.config.js — generated by `detox init`
module.exports = {
  rootDir: '..',
  testMatch: ['<rootDir>/e2e/**/*.test.js'],
  testTimeout: 120000,
  maxWorkers: 1,
  globalSetup: 'detox/runners/jest/globalSetup',
  globalTeardown: 'detox/runners/jest/globalTeardown',
  reporters: ['detox/runners/jest/reporter'],
  testEnvironment: 'detox/runners/jest/testEnvironment',
  verbose: true,
};

Android native setup

iOS needs no project changes. A bare Android project needs these build-script changes and three more below:

 // android/build.gradle
 allprojects {
   repositories {
     google()
+    maven { url("$rootDir/../node_modules/detox/Detox-android") }
   }
 }

 // android/app/build.gradle
   defaultConfig {
+    testBuildType System.getProperty('testBuildType', 'debug')
+    testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
   }
   dependencies {
+    androidTestImplementation('com.wix:detox:+')
   }

Also: the Kotlin Gradle plugin on the buildscript classpath; a DetoxTest.java instrumentation test under android/app/src/androidTest/java/ in your app's package (copy it from the Detox "Project Setup" page and change the package line); and a network_security_config.xml that permits cleartext traffic to 10.0.2.2 and localhost, registered with android:networkSecurityConfig in AndroidManifest.xml. Release builds must add Detox's ProGuard file (node_modules/detox/android/detox/proguard-rules-app.pro), otherwise the test hangs or crashes at launch.

Writing Tests

// e2e/login.test.js — element(), by, expect, waitFor and device are Detox globals
describe('Login Flow', () => {
  beforeAll(async () => {
    await device.launchApp({ newInstance: true });
  });
  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('should login successfully with valid credentials', async () => {
    await element(by.id('email-input')).typeText('maya.chen@fieldnotes.app');
    await element(by.id('password-input')).typeText(process.env.E2E_USER_PASSWORD);
    await element(by.id('login-button')).tap();
    await expect(element(by.id('home-screen'))).toBeVisible();
    await expect(element(by.text('Welcome back'))).toBeVisible();
  });
  it('should show error for invalid credentials', async () => {
    await element(by.id('email-input')).typeText('maya.chen@fieldnotes.app');
    await element(by.id('password-input')).typeText('not-the-password');
    await element(by.id('login-button')).tap();
    await expect(element(by.id('error-message'))).toHaveText('Invalid credentials');
    await expect(element(by.id('home-screen'))).not.toBeVisible();
  });
});

by.id matches the React Native testID prop, which only works when it reaches a native component (View, Text, TextInput, Pressable); a custom component must forward it. Other matchers: by.text, by.label, by.type, combined with .and(), .withAncestor(), .withDescendant() and .atIndex(). Negate any assertion with .not; toBeNotVisible() and toNotExist() are deprecated.

Scrolling and Lists

// e2e/feed.test.js — scroll until an item appears, then pull to refresh
it('should load more items and refresh', async () => {
  await waitFor(element(by.id('feed-item-10'))).toBeVisible().whileElement(by.id('feed-list')).scroll(300, 'down');
  await element(by.id('feed-list')).scrollTo('top');
  await element(by.id('feed-list')).swipe('down', 'slow');   // pull to refresh
  await waitFor(element(by.id('refresh-indicator'))).not.toBeVisible().withTimeout(5000);
});

scroll(offset, direction) moves by points, scrollTo('bottom') jumps to an edge, swipe(direction) performs the gesture. A waitFor without withTimeout or whileElement does nothing.

Running Tests

npx detox build --configuration ios.sim.debug
npm start                                        # debug builds need Metro running in another terminal
npx detox test --configuration ios.sim.debug
npx detox test -c ios.sim.debug e2e/login.test.js            # one file
npx detox test -c ios.sim.debug --retries 2                  # re-run failing files
npx detox test -c ios.sim.debug --reuse                      # keep the installed app, faster reruns
npx detox test -c android.emu.debug --headless               # no emulator window
npx detox test -c ios.sim.release --record-logs failing --take-screenshots failing --record-videos failing
npx detox test -c ios.sim.debug --loglevel verbose --debug-synchronization 5000

Artifacts go to artifacts/ unless --artifacts-location says otherwise. Jest flags such as -t "login" pass through.

CI Integration

# .github/workflows/detox.yml — release build on an iOS simulator
name: Detox E2E
on: [push]
jobs:
  detox-ios:
    runs-on: macos-15
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: npm ci
      - run: brew tap wix/brew && brew install applesimutils
      - run: cd ios && pod install
      - run: npx detox build --configuration ios.sim.release
      - run: npx detox test --configuration ios.sim.release --cleanup --headless --retries 2 --record-logs failing --take-screenshots failing
        env:
          E2E_USER_PASSWORD: ${{ secrets.E2E_USER_PASSWORD }}
      - uses: actions/upload-artifact@v7
        if: failure()
        with:
          name: detox-artifacts
          path: artifacts

Test a release build in CI: it bundles the JavaScript, so no Metro server is needed. Android emulators need hardware virtualization (KVM) on the runner.

Examples

Example 1: Add a login test to an existing app and run it on iOS

User request: "We have Detox installed. Add an E2E test for the login screen and run it on the simulator."

Add testIDs to the screen, then create e2e/login.test.js from "Writing Tests" above:

<TextInput testID="email-input" value={email} onChangeText={setEmail} autoCapitalize="none" />
<TextInput testID="password-input" value={password} onChangeText={setPassword} secureTextEntry />
<Pressable testID="login-button" onPress={submit}><Text>Log in</Text></Pressable>
npx detox build -c ios.sim.debug
npm start &                       # Metro, stop it afterwards with: kill %1
E2E_USER_PASSWORD="$FIELDNOTES_E2E_PASSWORD" npx detox test -c ios.sim.debug e2e/login.test.js

Result: the simulator boots, the app is installed and launched, and Jest lists both tests of Login Flow as passed. If a testID is missing or not forwarded, the run fails with Test Failed: No elements found for “MATCHER(id == “login-button”)”; rerun with --loglevel verbose to print the view hierarchy.

Example 2: A test hangs on a screen with a spinner

User request: "Our Detox test just sits on the dashboard and times out. The app works fine by hand."

npx detox test -c ios.sim.debug e2e/dashboard.test.js --debug-synchronization 5000

The log names what keeps the app busy:

detox[90417] i The app is busy with the following tasks:
• UI elements are busy:
  - View animations pending: 2.
• 1 network requests with URLs:
  - URL #1: https://api.fieldnotes.app/v1/sync/poll

Exclude the long-polling endpoint from synchronization, and if a looping animation stays, wait manually around that one screen:

await device.launchApp({ newInstance: true });
await device.setURLBlacklist(['.*/v1/sync/poll.*']);

await device.disableSynchronization();
await element(by.id('tab-dashboard')).tap();
await waitFor(element(by.id('dashboard-total'))).toBeVisible().withTimeout(8000);
await element(by.id('tab-settings')).tap();
await device.enableSynchronization();   // only after leaving the busy screen

Result: the test no longer waits for the polling request, and the dashboard assertion passes within the 8-second window instead of timing out.

Guidelines

  • Match by testID (by.id) rather than by text: IDs survive copy changes and translations.
  • Start each test from a known state: device.launchApp({ newInstance: true }) is the safest, device.reloadReactNative() is faster but can glitch in complex apps, and launchApp({ delete: true }) or { resetAppState: true } clears stored data.
  • Do not add sleeps. If Detox waits forever, find the busy resource with --debug-synchronization: an endless loader, a looping animation, a setTimeout polling loop (use setInterval, which Detox ignores) or a long-lived request (blacklist its URL). Disabling synchronization is the last resort and is re-enabled on every new app launch.
  • Keep maxWorkers: 1 until the suite is stable; more workers boot more simulators and need tests that do not share accounts or server state.
  • Use --retries in CI to absorb rare device hiccups, but treat a test that needs retries locally as a bug.
  • On Android prefer AOSP emulator images (system-images;android-34;default;x86_64) over Google API images; they are lighter and more stable for automation.
  • Keep test credentials in environment variables or CI secrets and point tests at a staging backend, never at production accounts.
  • Permission dialogs: on iOS grant them at launch with device.launchApp({ permissions: { notifications: 'YES', location: 'inuse' } }), or tap them through the experimental iOS-only system.element(by.system.label('Allow')).tap(). There is no system API on Android yet.
  • Limits: Detox does not run on physical iOS devices and cannot drive other apps. For cross-app flows or apps that are not React Native, choose Appium or Maestro.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Scripts and configures production rendering in Autodesk 3ds Max with the V-Ray and Corona renderers: output size and files, render elements, denoising, light mix, batch and command-line rendering, and network rendering. Use when a user asks to set up a production render, render several cameras in one batch, render from the command line or on a render farm, add render passes for compositing, or cut render time for archviz and product shots.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1652026年10月4日 更新

Covers scripting Autodesk 3ds Max, the 3D modeling and rendering application, with MAXScript and Python (pymxs): scene manipulation, object creation, material assignment, camera and light setup, batch operations, and file I/O. Use when tasks involve automating repetitive 3ds Max workflows, batch processing scenes, running scripts headless with 3dsmaxbatch, creating custom tools, or scripting scene setup for archviz, product visualization, or VFX.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1652026年10月4日 更新

3proxy

無料

3proxy is a small open-source proxy server that runs HTTP/HTTPS, SOCKS4/5, SNI and TCP/UDP port-mapping proxies from one config file. Use when a user asks to set up an HTTP or SOCKS5 proxy, add proxy users and passwords, write 3proxy access rules, chain or rotate upstream (parent) proxies, limit bandwidth, connections or monthly traffic per user, run 3proxy in Docker, or fix a 3proxy.cfg that will not start.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1652026年10月4日 更新

Builds Agent2Agent (A2A) servers and clients, the open protocol (originally from Google, now under the Linux Foundation) that lets AI agents from different frameworks call each other. Use when the user wants to create an A2A-compliant agent, build an Agent Card, implement task management, connect agents across frameworks, set up agent discovery, handle streaming responses, implement push notifications, or orchestrate multi-agent workflows. Trigger words: a2a, agent to agent, agent2agent, a2a protocol, a2a server, a2a client, agent card, agent interoperability, agent collaboration, multi-agent, agent discovery, a2a sdk, a2a task.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1652026年10月4日 更新

Plans a controlled experiment (A/B test) so its result can be trusted: writes the hypothesis, picks one primary metric and the guardrails, computes sample size and run time, specifies how visitors are assigned and when exposure is logged, and reads out the result with a confidence interval. Use when someone says "set up an A/B test", "split test this page", "how many visitors do I need", "how long should the experiment run", "is this result significant", "can I stop the test early", or wants to test a headline, price, layout or onboarding change against the current version.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1652026年10月4日 更新

ably

無料

Ably is a hosted realtime messaging service: clients publish and subscribe to named channels over WebSockets, see who is present, replay message history, and resume after a dropped connection. Use when a user asks to "add realtime updates", "push live notifications to the browser", "show who is online", "add a chat room with typing indicators", "publish from a serverless function", or "authenticate Ably clients without exposing the API key". Covers the ably 2.x JavaScript SDK (Realtime and REST), JWT token authentication, presence, history and rewind, batch publishing, and the @ably/chat 1.x SDK.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1652026年10月4日 更新

TerminalSkills のスキルをすべて見る

このスキルの問題を報告する