Real stacks
When you need it
Test an app that is more than one process, a frontend, an API and a worker, with every outside call emulated.
Most apps are more than one process. A frontend calls an API, the API hands slow work to a background worker, and all three talk to Stripe, a database and a job queue. danwo can start the whole stack, put every process behind its proxy, and test it end to end.
When you need it
Use the setup that matches what your app is:
| Your app | Use |
|---|---|
One process with a dev command (npm run dev) | appEnvironment, what danwo init writes |
| A frontend, an API, workers | stackEnvironment |
| Background jobs on Inngest | inngestService |
| Its own Postgres or Redis | data proxies |
You can mix them: a stack with an Inngest worker and a Postgres database is one config.
How it fits together
- danwo starts every app in the order you give, each with its own command and folder.
- Each app is pointed at the proxy. Their calls to
api.stripe.comorapi.clerk.comreach emulators. Your code doesn't change. - Local services stay local. The apps reach each other, the Inngest dev server and your databases on this machine as usual.
- Everything is recorded. Every app's calls, webhooks, sockets and log lines go into the test's flight record.
A small stack
Here is a frontend that calls an API, with Stripe emulated and every other outside host blocked:
import { defineConfig, stackEnvironment, stripeService } from "@danwo/sdk"
export default defineConfig({
testDir: "tests",
readiness: { mode: "page+backend", settle: true },
environment: () =>
stackEnvironment({
unmatched: "block",
services: [stripeService()],
apps: [
{
name: "web",
command: "npm run dev",
cwd: "apps/web",
url: "http://localhost:3000",
dependsOn: ["api"],
env: ({ api }) => ({ VITE_API_URL: api ?? "" }),
},
{
name: "api",
command: "npm start",
cwd: "apps/api",
url: "http://localhost:4000",
ready: { path: "/health" },
},
],
}),
})danwo starts the API first and waits until /health answers. Then it starts the web app, with the
API's address in VITE_API_URL. The browser opens the first app in the list, the web app.
Tests stay the same. A test opens pages and clicks buttons as before; the stack runs underneath.