Pactwork

Storybook addon for Pactwork - Control API scenarios, latency, and network states directly from stories

View on GithubNew to Storybook?Get started

@pactwork/storybook-addon

Storybook addon for Pactwork - Control API scenarios, latency, and network states directly from stories

npm version Storybook 10 ESM only

Features

  • Toolbar Controls - Scenario picker, latency presets, and network state toggle directly in Storybook's top toolbar
  • Scenario Selection - Switch between API response scenarios in stories via parameters
  • Latency Control - Add artificial delay to simulate slow networks (None, 200ms, 1s, 3s presets)
  • Network Simulation - Test online, offline, and timeout states
  • Addon Panel - Observability panel showing current state, request logs, and available handlers
  • TypeScript Support - Full type safety with autocomplete for parameters
  • CSF Factories - Storybook 10 compatible with definePreviewAddon

Requirements

  • Storybook 10.x (ESM-only)
  • Node.js >=20.11.0
  • Pactwork 1.1.0+
  • MSW 2.0+

Installation

npm install -D @pactwork/storybook-addon

Setup

1. Add to Storybook configuration

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
  addons: [
    '@storybook/addon-essentials',
    '@pactwork/storybook-addon', // Add pactwork addon
  ],
  // ... other config
};

export default config;

2. Initialize in preview.ts

// .storybook/preview.ts
import { initPactwork } from '@pactwork/storybook-addon';
import { handlers, handlerMeta, scenarios } from '../mocks';
import { worker } from '../mocks/browser';

// Start MSW worker
await worker.start({ onUnhandledRequest: 'bypass' });

// Initialize pactwork addon
initPactwork(worker, {
  handlers,
  handlerMeta,
  scenarios,
  debug: true, // Optional: log transformations to console
});

export default {
  // ... your preview config
};

3. (Alternative) CSF Factories Setup

For Storybook 10's recommended CSF Factories pattern:

// .storybook/preview.ts
import pactworkAddon from '@pactwork/storybook-addon';
import { definePreview } from '@storybook/react';

export default definePreview({
  addons: [pactworkAddon()],
});

Usage

Story Parameters

Control API behavior per-story using parameters.pactwork:

// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  component: Button,
};

export default meta;
type Story = StoryObj<typeof Button>;

// Default story - uses normal API responses
export const Default: Story = {};

// Loading state - 2 second delay
export const Loading: Story = {
  parameters: {
    pactwork: {
      scenario: 'getUser.loading',
      latency: 2000,
    },
  },
};

// Error state
export const Error: Story = {
  parameters: {
    pactwork: {
      scenario: 'getUser.serverError',
    },
  },
};

// Not found state
export const NotFound: Story = {
  parameters: {
    pactwork: {
      scenario: 'getUser.notFound',
    },
  },
};

// Empty list
export const EmptyList: Story = {
  parameters: {
    pactwork: {
      scenario: 'listUsers.empty',
    },
  },
};

// Network timeout
export const NetworkTimeout: Story = {
  parameters: {
    pactwork: {
      networkError: 'timeout',
    },
  },
};

// Multiple scenarios
export const ComplexState: Story = {
  parameters: {
    pactwork: {
      scenarios: ['getUser.loading', 'listUsers.empty'],
      latency: 500,
    },
  },
};

Toolbar

When Storybook is running, you'll see a Pactwork icon in the top toolbar. Click it to open the controls dropdown:

  • Scenario - Select from available scenarios or reset to default
  • Latency - Quick presets: None, 200ms, 1s, 3s
  • Network - Toggle between Online, Offline, and Timeout states
  • Reset All - Clear all active transformations

The toolbar button shows a status summary when any transformation is active.

Addon Panel

The "Pactwork" tab in the addon panel provides observability:

  • Current State - Shows active scenario, latency, and network state
  • Request Log - Live log of intercepted API requests with method, path, status, and timing
  • Handler List - View all available handlers and their scenario counts

API Reference

PactworkParameters

Property Type Description
scenario string Scenario to apply. Format: 'operationId.scenarioName'
scenarios string[] Multiple scenarios to apply simultaneously
latency number | LatencyOptions Delay in ms or { min, max } for random range
networkError 'timeout' | 'abort' | 'network-error' Network error to simulate
operations string[] Specific operations to apply transformations to
disabled boolean Disable all pactwork transformations

initPactwork(worker, config)

Initialize the addon with your MSW worker and pactwork configuration.

initPactwork(worker, {
  handlers: HttpHandler[],      // MSW handlers from pactwork generate
  handlerMeta: HandlerMetaMap,  // Handler metadata for O(1) lookups
  scenarios: Record<string, ScenarioMap>, // Available scenarios by operationId
  defaultLatency?: number,      // Default latency for all handlers
  debug?: boolean,              // Log transformations to console
});

Exported Functions

Function Description
initPactwork Initialize addon with MSW worker and config
setWorker Manually set MSW worker reference
setGlobalConfig Manually set global configuration
getGlobalConfig Get current global configuration
resetHandlers Reset all handlers to original state
pactworkDecorator The Storybook decorator instance

Channel Events

For advanced integrations, the addon uses these channel events:

Event Direction Description
pactwork/scenario-change Toolbar → Preview Scenario selection changed
pactwork/latency-change Toolbar → Preview Latency value changed
pactwork/network-change Toolbar → Preview Network state changed
pactwork/state-update Preview → Panel Current state updated
pactwork/handlers-ready Preview → Toolbar/Panel Handler info available
pactwork/reset Toolbar → Preview Reset all transformations

Storybook 10 Migration

This addon is built specifically for Storybook 10.x. Key changes from previous Storybook versions:

Change Before (SB 8/9) After (SB 10)
Module format CJS + ESM dual ESM-only
Entry points exportEntries previewEntries + managerEntries
Path resolution require.resolve() import.meta.resolve()
Addon export Manual annotations definePreviewAddon()
Node target 18.0 20.19+

Upgrading from MSW addon

If you're migrating from msw-storybook-addon:

// Before (msw-storybook-addon)
export const handlers = [
  http.get('/api/user', () => HttpResponse.json({ name: 'John' })),
];

// After (pactwork)
// 1. Generate handlers with pactwork CLI
npx pactwork generate --spec openapi.yaml --output ./mocks

// 2. Use generated handlers with scenarios
import { handlers, handlerMeta, scenarios } from './mocks';

// 3. Configure addon
initPactwork(worker, { handlers, handlerMeta, scenarios });

// 4. Use scenarios in stories
parameters: {
  pactwork: { scenario: 'getUser.notFound' }
}

Troubleshooting

Panel not showing handlers

Make sure initPactwork is called after worker.start() in preview.ts.

Scenarios not applying

Check that the scenario string matches the format operationId.scenarioName exactly.

TypeScript errors

Ensure you have the correct peer dependencies:

npm install -D storybook@^10.0.0 msw@^2.0.0 pactwork@^1.1.0

ESM errors

This package is ESM-only. Make sure your project supports ES modules:

// package.json
{
  "type": "module"
}

License

MIT

Made by
  • adrozdenko
    adrozdenko
Work with
    Angular
    Preact
    React
    Svelte
    Vue
    Web Components
Tags