Core ConceptsScenarios & Recordings

Scenarios & Recordings

A scenario is a named collection of recorded API interactions. A recording captures a single HTTP request and its corresponding response.


What is a Scenario?

A scenario represents a complete test case or user flow. It contains:

  • A unique name identifying the scenario
  • A description explaining what it tests
  • An array of recordings (request/response pairs)
  • Timestamps for creation and last update
import { createScenario } from '@mockmaster/msw-adapter'
 
const scenario = createScenario('user-login', 'Successful user login flow')
 
console.log(scenario)
// {
//   name: 'user-login',
//   description: 'Successful user login flow',
//   recordings: [],
//   createdAt: 1234567890,
//   updatedAt: 1234567890
// }

Creating Scenarios

Empty Scenario

Start with an empty scenario and add recordings:

import { createScenario, addRecordingToScenario, createRecording } from '@mockmaster/msw-adapter'
 
let scenario = createScenario('checkout-flow', 'Complete checkout process')
 
// Add recordings one by one
const cartRecording = createRecording(
  { method: 'GET', url: 'https://api.example.com/cart', path: '/cart', timestamp: Date.now() },
  { status: 200, body: { items: [], total: 0 }, timestamp: Date.now() }
)
 
scenario = addRecordingToScenario(scenario, cartRecording)

From OpenAPI Spec

Generate scenarios automatically from OpenAPI specs:

import { generateScenariosFromSpec } from '@mockmaster/cli'
import { parseYaml } from '@mockmaster/openapi'
 
const spec = parseYaml(`
openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
paths:
  /users:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                type: array
`)
 
const scenarios = generateScenariosFromSpec(spec, 'user-api')
// Returns array of scenarios with realistic data

Managing Recordings

Adding Recordings

Use addRecordingToScenario to add recordings:

import { createScenario, addRecordingToScenario, createRecording } from '@mockmaster/msw-adapter'
 
let scenario = createScenario('user-api', 'User CRUD operations')
 
// Add GET /users
const listRecording = createRecording(
  { method: 'GET', url: 'https://api.example.com/users', path: '/users', timestamp: Date.now() },
  { status: 200, body: [{ id: 1, name: 'Alice' }], timestamp: Date.now() }
)
scenario = addRecordingToScenario(scenario, listRecording)
 
// Add GET /users/:id
const getRecording = createRecording(
  { method: 'GET', url: 'https://api.example.com/users/1', path: '/users/:id', timestamp: Date.now() },
  { status: 200, body: { id: 1, name: 'Alice' }, timestamp: Date.now() }
)
scenario = addRecordingToScenario(scenario, getRecording)
 
console.log(scenario.recordings.length) // 2

Accessing Recordings

Recordings are stored in the recordings array:

scenario.recordings.forEach((recording, index) => {
  console.log(`Recording ${index + 1}:`)
  console.log('  Method:', recording.request.method)
  console.log('  Path:', recording.request.path)
  console.log('  Status:', recording.response.status)
})

Storing Scenarios

Save to Disk

Write scenarios to JSON files:

import { writeScenario } from '@mockmaster/cli'
 
await writeScenario('./scenarios', scenario)
// Saves to: ./scenarios/user-api.json

Load from Disk

Read scenarios from JSON files:

import { readScenario } from '@mockmaster/cli'
 
const scenario = await readScenario('./scenarios', 'user-api')
// Loads from: ./scenarios/user-api.json

JSON Format

Scenarios are stored as JSON files:

{
  "name": "checkout-flow",
  "description": "Complete checkout process",
  "recordings": [
    {
      "request": {
        "method": "GET",
        "url": "https://api.example.com/cart",
        "path": "/cart",
        "timestamp": 1234567890
      },
      "response": {
        "status": 200,
        "body": {
          "items": [
            { "id": 1, "name": "Product", "price": 29.99 }
          ]
        },
        "headers": {
          "content-type": "application/json"
        },
        "timestamp": 1234567890
      }
    }
  ],
  "createdAt": 1234567890,
  "updatedAt": 1234567891
}

Organizing Scenarios

By Feature

Organize scenarios by feature or module:

scenarios/
├── auth/
│   ├── login-success.json
│   ├── login-failure.json
│   ├── logout.json
│   └── refresh-token.json
├── users/
│   ├── list-users.json
│   ├── get-user.json
│   ├── create-user.json
│   └── update-user.json
└── products/
    ├── list-products.json
    └── get-product.json

By User Flow

Organize by user flows or test cases:

scenarios/
├── new-user-signup.json
├── existing-user-login.json
├── checkout-with-coupon.json
└── profile-update.json

By Environment

Create environment-specific scenarios:

scenarios/
├── development/
│   └── user-api.json
├── staging/
│   └── user-api.json
└── production/
    └── user-api.json

Scenario Naming Conventions

Use clear, descriptive names:

Good Names

  • user-registration-success
  • login-with-invalid-credentials
  • checkout-flow-with-discount
  • api-user-crud-operations

Avoid

  • test1
  • scenario
  • temp
  • x

Version Control

Commit Scenarios

Always commit scenario JSON files to version control:

git add scenarios/
git commit -m "Add user authentication scenarios"

Update When APIs Change

When APIs change, update scenarios:

# Re-generate from updated OpenAPI spec
node scripts/generate-scenarios.ts
 
# Review changes
git diff scenarios/
 
# Commit updates
git add scenarios/
git commit -m "Update scenarios for API v2"

Code Review

Include scenario files in code reviews:

  • Verify recordings match expected API behavior
  • Check for realistic test data
  • Ensure error cases are covered

Best Practices

1. Descriptive Names

Use names that clearly describe what the scenario tests:

// Good
createScenario('user-login-success', 'User logs in with valid credentials')
createScenario('user-login-invalid-password', 'Login fails with wrong password')
 
// Bad
createScenario('test1', 'test')
createScenario('user', 'user stuff')

2. Detailed Descriptions

Write descriptions that explain the scenario’s purpose:

createScenario(
  'checkout-flow',
  'Complete checkout process: add items to cart, apply discount code, and complete payment'
)

3. One Scenario Per Flow

Keep scenarios focused on a single user flow or test case:

// Good - focused scenarios
createScenario('user-registration', 'New user signs up')
createScenario('user-login', 'Existing user logs in')
 
// Bad - too broad
createScenario('user-auth', 'All auth stuff')

4. Include Error Cases

Create scenarios for both success and error cases:

createScenario('create-user-success', '201 Created')
createScenario('create-user-validation-error', '400 Bad Request')
createScenario('create-user-duplicate-email', '409 Conflict')

5. Keep Scenarios Updated

Update scenarios when:

  • API endpoints change
  • Response formats change
  • New fields are added
  • Error messages change

Complete Example

import {
  createScenario,
  addRecordingToScenario,
  createRecording
} from '@mockmaster/msw-adapter'
import { writeScenario } from '@mockmaster/cli'
 
async function createAuthScenarios() {
  // Login success scenario
  let loginSuccess = createScenario(
    'login-success',
    'User logs in with valid credentials'
  )
 
  const loginRecording = createRecording(
    {
      method: 'POST',
      url: 'https://api.example.com/auth/login',
      path: '/auth/login',
      body: { email: 'user@example.com', password: 'password123' },
      timestamp: Date.now()
    },
    {
      status: 200,
      body: {
        accessToken: 'eyJhbGc...',
        user: { id: 1, email: 'user@example.com', name: 'Test User' }
      },
      timestamp: Date.now()
    }
  )
 
  loginSuccess = addRecordingToScenario(loginSuccess, loginRecording)
  await writeScenario('./scenarios/auth', loginSuccess)
 
  // Login failure scenario
  let loginFailure = createScenario(
    'login-failure',
    'Login fails with invalid credentials'
  )
 
  const loginFailureRecording = createRecording(
    {
      method: 'POST',
      url: 'https://api.example.com/auth/login',
      path: '/auth/login',
      body: { email: 'user@example.com', password: 'wrong' },
      timestamp: Date.now()
    },
    {
      status: 401,
      body: { error: 'Invalid credentials' },
      timestamp: Date.now()
    }
  )
 
  loginFailure = addRecordingToScenario(loginFailure, loginFailureRecording)
  await writeScenario('./scenarios/auth', loginFailure)
 
  console.log('✓ Auth scenarios created successfully!')
}
 
createAuthScenarios().catch(console.error)

Next Steps