Part 5: Testing
Deploy once per test file
Section titled “Deploy once per test file”import { expect } from "bun:test";import * as Boat from "@alchemy.run/boat";import * as Cloudflare from "@alchemy.run/cloudflare";import * as Test from "@alchemy.run/test/Bun";import * as Alchemy from "alchemy";import * as Effect from "effect/Effect";import * as HttpClientRequest from "effect/http/HttpClientRequest";import * as Layer from "effect/Layer";import Stack from "../alchemy.run.ts";
const { test, beforeAll, afterAll, deploy, destroy } = Test.make({ providers: Layer.mergeAll(Cloudflare.providers(), Boat.providers()), state: Alchemy.localState(),});
const stack = beforeAll(deploy(Stack));afterAll.skipIf(!!process.env.NO_DESTROY)(destroy(Stack));The test deploys the Stack to a stage of its own, snapshot included, and destroys it afterwards.
Check a sandbox starts from Golden
Section titled “Check a sandbox starts from Golden”test( "starts each sandbox from the Golden snapshot", Effect.gen(function* () { const { url } = yield* stack; const res = yield* Test.executeWhenReady( HttpClientRequest.post(`${url}/run`).pipe(HttpClientRequest.bodyText("pnpm --version")), ); const body = (yield* res.json) as { exitCode: number }; expect(body.exitCode).toBe(0); }), { timeout: 180_000 },);pnpm is only there if the sandbox started from Golden. The Worker deletes the sandbox when the request ends, so none is left behind.
Run it
Section titled “Run it”bun testbun testbun testbun testSet NO_DESTROY=1 to keep the deployment, and the snapshot, between runs while you iterate. Each run starts sandboxes, which count against your plan’s starts per minute and per hour.
Part 6 deploys more copies, from CI.