Snapshot
idb, uiautomator, or the DOM. The live accessibility tree, every step.
semantic e2e · ios / android / web
You write the test flow. Convoy captures the screen, matches the control, gates the score, and executes the step.
01 — system
Convoy does not look up a test ID. It snapshots the screen, keeps the labelled controls, and scores the phrase against what is actually there.
idb, uiautomator, or the DOM. The live accessibility tree, every step.
Role, name, bounds. Unlabelled chrome is dropped before matching.
Presence first, then target. Which control is this phrase talking about?
Pass, ambiguous, or not found. A wrong control is never tapped quietly.
Retry until the next screen settles. Default window: 20 seconds.
02 — authoring
YAML handles flows and branches with which. TypeScript is
for loops, platform splits, and extra setup. If two controls could
fit, tighten the phrase from convoy inspect.
name: driver signs in platforms: [ios] tags: [smoke] steps: - type: ${USERNAME} into: Email / Username - tap: Continue - type: ${PASSWORD} into: Password - tap: Log in - which: logged in on another device: - tap: Continue Anyway the home screen: [] - see: the home screen
import { e2e } from "convoy-e2e"; e2e.serial("driver signs in", { platforms: ["ios"] }, (step) => { step("signs in", async (t) => { await t.type(process.env.USERNAME, { into: "Email / Username" }); await t.tap("Continue"); await t.type(process.env.PASSWORD, { into: "Password" }); await t.tap("Log in"); const screen = await t.which([ "logged in on another device", "the home screen", ]); if (screen === "logged in on another device") { await t.tap("Continue Anyway"); } await t.see("the home screen"); }); });
Drive there, or run until the suite fails on that step.
npx convoy inspect when two controls could fit. Tighten the phrase.
npx convoy capture --name login-screen writes a fixture and a PNG.
Ambiguous → rephrase. Not found → the control is gone. Traces: .convoy/runs/.
03 — gates
Scores, on-screen labels, next action. Not a stack trace about a missing CSS selector.
The control matched. Proceed.
Two or more controls fit. Tighten the phrase.
Missing, unlabelled, or still loading. Often a product bug.
The window elapsed. The screen never arrived.
04 — surfaces
npx convoy doctor prints whatever this machine is missing.
Simulator, .app, idb. Convoy boots, installs, launches.
adb and a device that is already running. It will not start an AVD.
Playwright Chromium and a base URL. Optionally spawn the app server.
Recorded JSON. No device, no key. Offline authoring and unit tests.
05 — start
# your application repository
npm install -D convoy-e2e
npx convoy init --platform ios --yes
npx convoy doctor
npx convoy run
TYPESAFE_API_KEY and app secrets live in .env.
Commit convoy.config.json. Never a UDID or a password in JSON.
Matching stays host-side via Jev. The API key never enters an iOS, Android, or web binary. No key → local heuristic, fine for fixtures, not for a real app.
Reference:
README.
Agents: agent/ skills.
.env, sample test. Never overwrites an existing .env..convoy/captures/.*.e2e.yaml / *.e2e.ts, or a file, or a folder.--platform --tag --headed --headless --shard 1/4 --junit