# Test an integration
Offline tests execute your real flow against a scripted website. They cannot contact the live site.
## Run tests
```sh
npx playwright install chromium
browserlayer test example
```
## Complete example
`tests/page-title.test.ts`:
```ts
import { test } from "vitest";
import { compile } from "@browserlayer/sdk/compiler";
import { testIntegration } from "@browserlayer/sdk/testing";
const { integration } = await compile(
"integrations/example",
".browserlayer/test-artifact",
);
test("reads a page title", async () => {
await using app = await testIntegration(integration, {
origin: "https://example.test",
site: async (site) => {
const request = await site.request("GET", "/");
await request.respond({
contentType: "text/html",
body: "
My account",
});
},
});
const run = await app.run("page-title", { url: "https://example.test/" });
await run.expectCompleted({ title: "My account" });
await app.expectSiteCompleted();
});
```
## Input and failures
```ts
await run.expectInput("verification");
await run.answer({ code: "123456" });
await run.expectCompleted({ authenticated: true });
```
| Assertion | Checks |
| ------------------------- | ------------------------------------------------- |
| `expectInput(name)` | Flow is waiting at that named input |
| `answer(values)` | Submit to the current request |
| `expectCompleted(output)` | Exact final output |
| `expectFailed(code)` | Structured failure |
| `expectSiteCompleted()` | Website script finished without missing exchanges |
## Sync tests
Supply `runtime.sync` using `runtimeSync(store, "test", manifest)` from `@browserlayer/sync`, with `sqliteSyncStore` in a temporary directory. Assert published changes from the store, not just a completed run. Close the store during cleanup.
`testIntegration` supplies isolated in-memory reference mappings by default. Use `runtime.references` from the persistent reference store when testing restart, storage or isolation behavior.
## Live verification
```sh
browserlayer connections create atlas-demo --local --wait
browserlayer run atlas-demo cancel-booking --local \
--connection --input '{"bookingId":""}' --wait
```
Live runs change the actual website. Use a test account and explicitly choose any mutations. macOS offline tests use sandbox-exec; Linux needs user/network namespaces. Unsupported isolation fails closed.