Community examples aren't actively verified by the e2e team so exercise extra caution when running.

Appduct for e2e
Call your app's Appduct tools from e2e tests, and let e2e's agent call them during agent steps. Set up state without tapping through the UI, and check what the app holds instead of only what it shows.
Requirements
- An app that registers tools with an Appduct SDK, in a debug build. Web pages load
@appduct/webfrom a development build. - e2e 0.21 or newer, with its web or mobile engine.
- Web, iOS simulator or Android emulator targets.
- For iOS and Android, the app's URL scheme in
.appduct/config.jsonat your e2e project root, as theappductCLI reads it.
Getting started
npm install -D @appduct/e2eAdd the appduct fixture to your test in one place:
// tests/fixtures.ts
import { test as base } from "e2e";
import { withAppduct } from "@appduct/e2e";
export const test = withAppduct(base);base can also be an engine's test, such as the one from @e2e-dev/mobile, or a test you already extended with fixtures of your own. Then write tests with it:
// tests/cart.e2e.ts
import { expect } from "e2e";
import { test } from "./fixtures.ts";
test("a seeded cart checks out", async ({ app, appduct, screen }) => {
await app.open();
await appduct.call("seed_cart", { items: 3 });
await screen.getByRole("button", { name: "Check out" }).tap();
expect(await appduct.call("order_status")).toEqual({ status: "paid" });
});The first appduct call in a test connects to the app the test opened. A test that never uses appduct doesn't connect.
Let the agent call your tools
Add appductTools() to an agent's tools in e2e.config.ts:
import type { E2EConfig } from "e2e";
import { appductTools } from "@appduct/e2e";
export default {
// targets: …
agents: { default: { model, tools: appductTools() } },
} satisfies E2EConfig;The agent gets appduct_tools, which lists the app's tools, and appduct_call, which calls one. They work in tests written with a test from withAppduct.
The appduct fixture
| Member | What it does |
|---|---|
call(name, args?, options?) | Calls a tool and returns its result. Waits up to 10 seconds for a tool the app hasn't registered yet. |
tools() | Lists the app's tools. Waits up to 10 seconds for the app to register its first. |
waitForEvent(name, options?) | Resolves with the next event the app posts under name. |
Errors are AppductErrors from appduct/client, with the same type the CLI reports.
Things to know
- The connection lasts as long as the app does. A test that keeps the app running, such as the next test in a
serialgroup, reuses the previous test's connection. Afterapp.open(),app.restart()or a reload, the next call connects to the new app and ends the old connection, soappduct sessions lsdoesn't fill up with dead sessions. - A new iOS simulator asks once before the first link opens the app. The fixture accepts iOS's "Open in …?" question for you, which shows as a
device.alertstep in that test's report. The simulator doesn't ask again. - Agent steps that call
appduct_callrun live. e2e can't replay a call that may change app state from its cache.
Made with ❤️ at Callstack
appduct is an open source project and will always remain free to use. If you think it's cool, please star it 🌟. Callstack is a group of React and React Native geeks, contact us at hello@callstack.com if you need any help with these or just want to say hi!
Like the project? ⚛️ Join the team who does amazing stuff for clients and drives React Native Open Source! 🔥