Test Reality.
Control the Rest.
Playwright tests that hit your real server. Your Server Components, routes, middleware, and business logic execute for real. Scenarist mocks only external APIs—switchable per test.
Built for full-stack frameworks
const successScenario = {
id: 'payment_success',
mocks: [{
url: 'https://api.stripe.com/*',
method: 'POST',
response: {
status: 200,
body: { paid: true }
}
}]
}; test('checkout flow', async ({ page }) => {
await switchScenario(page, 'payment_success');
// Hits real Next.js backend
await page.goto('/checkout');
await page.click('#pay-button');
// Real DB, Real Middleware, Mocked Stripe
await expect(page).toHaveURL('/success');
}); Why Scenarist?
The Testing Gap
Fast like unit tests, realistic like integration tests
Parallel Execution
Isolated test state means unlimited parallelism
Behavior Testing
Test scenarios, not implementation details
Only mock what you don't control
Scenarist acts as a precision scalpel. It slices off external dependencies while leaving your application logic perfectly intact.
Executes For Real
Mocked by Scenarist
Next.js Adapters
Full support for both App Router and Pages Router. Test React Server Components, Server Actions, and API Routes with real execution—your async components fetch data for real, only external APIs are mocked.
Express Adapter
Full Express support. Routes, middleware, error handlers—all run for real. More adapters planned.
View docsInstant Runtime Switching
Switch scenarios instantly without restarting your server. Tests run in parallel with isolated state—fast like unit tests, realistic like integration tests.
Type-Safe
Built for Playwright. TypeScript autocomplete for your scenario IDs. Never debug a typo again.
No Framework Mocking
No mocking next/headers. No mocking req.session. Your app code runs as-is.
Playwright Helpers
Each test gets a unique ID. Call switchScenario(page, 'premium-user') and all requests from that test use your scenario. Run tests in parallel—each isolated, each with different API responses.