[ Documentation ]
Your First Test

Your First Test

Peach supports two test runners. Maestro owns YAML tests; Detox runs imperative Jest specs through the Peach driver.

Maestro YAML

Connect your app using the Quick Start, then run peach describe to see its current text and test IDs. This example assumes a Welcome screen with a Get Started button that opens Home. Replace those selectors with the corresponding controls in your app and save .maestro/smoke.yaml:

- launchApp: {}
- waitFor:
text: 'Welcome'
timeout: 10000
- tapOn: 'Get Started'
- waitForAnimationToEnd: true
- assertVisible: 'Home'
- takeScreenshot: home-screen

Run it:

terminal
peach maestro test .maestro/smoke.yaml

Detox-style tests

The same illustrative screen names apply to the Detox example. Replace them with your app’s selectors and create e2e/my-app.test.ts:

import { by, device, element, expect, waitFor } from 'detox'
beforeAll(async () => {
await device.launchApp()
await waitFor(element(by.text('Welcome'))).toBeVisible().withTimeout(10000)
})
test('shows home screen', async () => {
await expect(element(by.text('Welcome'))).toBeVisible()
await element(by.text('Get Started')).tap()
await expect(element(by.text('Home'))).toBeVisible()
})

Jest runs from your project, so add its dev dependencies once, then run:

terminal
npm i -D peachsim jest
peach detox --app 8081

--app names the app each device.launchApp() opens: your dev server’s port or a bundle URL.

The driver includes its browser dependency and downloads Chromium on its first launch when needed. Use waitFor for content revealed after an app splash or an asynchronous load.

Existing Detox suites use the same command unchanged. Peach auto-detects the configuration and remaps import { by, device, element, expect } from 'detox' to its driver.

Test bridge API

All test drivers access the node tree through window.__sootsimTest:

// find elements
findByText(text) findById(id) findByTestId(testId)
findByLabel(label) findByRole(role) findAllByRole(role)
// inspect elements
getStyle(id) getLayout(id) getAbsolutePosition(id)
isVisible(id) getNodeCount()
// query
queryAll({ type?, hasText?, hasId?, hasRole?, hasLabel? })
// debug
dumpTree(maxDepth?) dumpAccessibilityTree(maxDepth?)
waitForTree()

Where to go next