Skip to content

Writing Scenarios Overview

Scenarist scenarios are declarative TypeScript objects that describe what mock responses to return. This guide helps you navigate the scenario features and choose the right ones for your tests.

FeatureWhat It EnablesWhen to Use
Basic StructureDefine mock responses for HTTP requestsEvery scenario needs this
Request MatchingReturn different responses for same URL based on request contentDifferent responses for different users, tiers, or request data
Pattern MatchingMatch using regex, contains, startsWith, endsWithCampaign codes, user agents, email domains, dynamic values
Response SequencesReturn different responses on successive callsPolling, async job status, multi-step workflows
Stateful MocksCapture data from requests, inject into later responsesShopping carts, user profiles, accumulated data
Default ScenariosDefine baseline mocks, override only what changesDRY scenarios, avoid duplication
Combining FeaturesUse all features togetherComplex realistic workflows
TypeScript PatternsType-safe scenario definitionsAutocomplete, compile-time errors

Start here: Every scenario needs the Basic Structure - this defines your mocks with method, URL, and response.

Then ask yourself:

“I need different responses for the same URL”

Section titled ““I need different responses for the same URL””

Based on request content? Use Request Matching

  • Different pricing for premium vs standard users
  • Different responses based on API version header
  • Different data based on query parameters

Based on how many times it’s called? Use Response Sequences

  • Job status: pending → processing → complete
  • Polling patterns
  • Retry scenarios

Use Pattern Matching for:

  • Campaign codes: x-campaign: summer-premium-2024
  • User agents: Mobile, Chrome, Safari
  • Email domains: @company.com
  • File extensions: .pdf, .jpg

”I need responses to reflect earlier requests”

Section titled “”I need responses to reflect earlier requests””

Use Stateful Mocks for:

  • Shopping cart that accumulates items
  • User profile that reflects submitted data
  • Session data that persists across requests

”I’m duplicating mocks across scenarios”

Section titled “”I’m duplicating mocks across scenarios””

Use Default Scenarios to:

  • Define happy path once in ‘default’
  • Override only what changes in specialized scenarios
  • Keep scenarios DRY

See Combining Features for examples of using multiple features together.

A minimal scenario with all required fields:

import type { ScenaristScenario } from '@scenarist/express-adapter';
export const myScenario: ScenaristScenario = {
id: 'my-scenario', // Unique identifier
name: 'My Scenario', // Human-readable name
description: 'What this scenario tests',
mocks: [
{
method: 'GET',
url: 'https://api.example.com/user',
response: {
status: 200,
body: { id: 1, name: 'Test User' },
},
},
],
};

Scenarist enforces declarative patterns - scenarios describe WHAT to return, not HOW to decide. No imperative functions with hidden if/else logic. This leads to:

  1. Visible intent - Match criteria show what matters
  2. Composable features - Specificity-based selection, automatic fallback
  3. Testable scenarios - Can validate statically with TypeScript

Learn more about the philosophy →