or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

browser-setup.mdcli.mdgraphql-handlers.mdhttp-handlers.mdindex.mdnodejs-setup.mdreact-native-setup.mdresponse-creation.mdutilities.mdwebsocket-handlers.md
tile.json

tessl/npm-msw

Seamless REST/GraphQL API mocking library for browser and Node.js.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/msw@2.11.x

To install, run

npx @tessl/cli install tessl/npm-msw@2.11.0

index.mddocs/

Mock Service Worker (MSW)

Mock Service Worker (MSW) is an API mocking library that intercepts HTTP, GraphQL, and WebSocket requests at the network level using Service Workers in browsers and low-level interception in Node.js. Unlike traditional mocking libraries that stub fetch or axios functions, MSW operates transparently without modifying application code, allowing developers to reuse the same mock definitions across unit tests, integration tests, end-to-end tests, and local development.

Package Information

  • Package Name: msw
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install msw

Core Imports

import { http, HttpResponse, setupWorker } from "msw";
import { setupServer } from "msw/node";

For CommonJS:

const { http, HttpResponse, setupWorker } = require("msw");
const { setupServer } = require("msw/node");

Environment-specific imports:

// Browser-specific
import { setupWorker } from "msw/browser";

// Node.js-specific  
import { setupServer } from "msw/node";

// React Native-specific
import { setupServer } from "msw/native";

// Core-only imports
import { http } from "msw/core/http";
import { graphql } from "msw/core/graphql";
import { ws } from "msw/core/ws";

Basic Usage

import { http, HttpResponse, setupWorker } from "msw";

// Define request handlers
const handlers = [
  // REST API handlers
  http.get('/api/user', () => {
    return HttpResponse.json({ name: 'John Doe', id: 123 });
  }),

  http.post('/api/login', async ({ request }) => {
    const { username, password } = await request.json();
    
    if (username === 'admin' && password === 'secret') {
      return HttpResponse.json({ token: 'abc123' });
    }
    
    return HttpResponse.json(
      { error: 'Invalid credentials' },
      { status: 401 }
    );
  }),

  // GraphQL handlers
  graphql.query('GetUser', () => {
    return HttpResponse.json({
      data: { user: { name: 'John Doe' } }
    });
  }),
];

// Browser setup
const worker = setupWorker(...handlers);
worker.start();

// Node.js setup (for testing)
const server = setupServer(...handlers);
server.listen();

Architecture

MSW is built around several key components:

  • Request Handlers: Define how to intercept and respond to specific requests using Express-like routing
  • Setup APIs: Platform-specific APIs (setupWorker, setupServer) that configure and control request interception
  • Response Utilities: HttpResponse class and utilities for creating realistic mock responses
  • Network Interception: Service Workers (browser) or low-level interceptors (Node.js) that capture requests transparently
  • Multi-Environment Support: Same handler definitions work across browser, Node.js, and React Native environments

Capabilities

HTTP Request Handling

Intercept and mock HTTP requests using Express-like routing syntax with support for parameters, wildcards, and custom predicates.

interface HttpRequestHandler {
  <Params, RequestBodyType, ResponseBodyType>(
    predicate: string | RegExp | ((info: { request: Request; parsedResult: any }) => boolean),
    resolver: (info: {
      request: Request;
      params: Params;
      cookies: Record<string, string>;
    }) => Response | Promise<Response>,
    options?: { once?: boolean }
  ): HttpHandler;
}

const http: {
  all: HttpRequestHandler;
  get: HttpRequestHandler;
  post: HttpRequestHandler;
  put: HttpRequestHandler;
  delete: HttpRequestHandler;
  patch: HttpRequestHandler;
  head: HttpRequestHandler;
  options: HttpRequestHandler;
};

HTTP Handlers

GraphQL Request Handling

Intercept and mock GraphQL operations by query/mutation name or operation type, with support for typed responses and scoped endpoints.

interface GraphQLRequestHandler {
  <Query, Variables>(
    predicate: string | DocumentNode | ((info: { query: any; variables: any }) => boolean),
    resolver: (info: {
      query: Query;
      variables: Variables;
      request: Request;
    }) => Response | Promise<Response>,
    options?: { once?: boolean }
  ): GraphQLHandler;
}

const graphql: {
  query: GraphQLRequestHandler;
  mutation: GraphQLRequestHandler;
  operation: (resolver: any) => GraphQLHandler;
  link: (url: string) => typeof graphql;
};

GraphQL Handlers

WebSocket Connection Handling

Intercept and mock WebSocket connections with event-based API for handling connection lifecycle and message broadcasting.

interface WebSocketLink {
  clients: Set<WebSocketClient>;
  addEventListener<EventType extends keyof WebSocketHandlerEventMap>(
    event: EventType,
    listener: (...args: WebSocketHandlerEventMap[EventType]) => void
  ): WebSocketHandler;
  broadcast(data: WebSocketData): void;
  broadcastExcept(
    clients: WebSocketClient | WebSocketClient[],
    data: WebSocketData
  ): void;
}

const ws: {
  link: (url: string) => WebSocketLink;
};

WebSocket Handlers

Browser Environment Setup

Service Worker-based request interception for browser environments with lifecycle control and runtime handler management.

interface SetupWorker {
  start(options?: StartOptions): Promise<ServiceWorkerRegistration | undefined>;
  stop(): void;
  use(...handlers: RequestHandler[]): void;
  resetHandlers(...handlers?: RequestHandler[]): void;
  restoreHandlers(): void;
  listHandlers(): ReadonlyArray<RequestHandler>;
  events: LifeCycleEventEmitter;
}

function setupWorker(...handlers: RequestHandler[]): SetupWorker;

Browser Setup

Node.js Environment Setup

Low-level request interception for Node.js environments using HTTP/HTTPS module patching, ideal for testing scenarios.

interface SetupServer {
  listen(options?: { onUnhandledRequest?: 'bypass' | 'warn' | 'error' }): void;
  close(): void;
  use(...handlers: RequestHandler[]): void;
  resetHandlers(...handlers?: RequestHandler[]): void;
  restoreHandlers(): void;
  listHandlers(): ReadonlyArray<RequestHandler>;
  events: LifeCycleEventEmitter;
}

function setupServer(...handlers: RequestHandler[]): SetupServer;

Node.js Setup

React Native Environment Setup

Request interception for React Native applications using fetch and XMLHttpRequest interceptors, compatible with popular HTTP libraries.

interface SetupServerCommonApi {
  listen(options?: { onUnhandledRequest?: 'bypass' | 'warn' | 'error' }): void;
  close(): void;
  use(...handlers: RequestHandler[]): void;
  resetHandlers(...handlers?: RequestHandler[]): void;
  restoreHandlers(): void;
  listHandlers(): ReadonlyArray<RequestHandler>;
  events: LifeCycleEventEmitter;
}

function setupServer(...handlers: RequestHandler[]): SetupServerCommonApi;

React Native Setup

Response Creation

Enhanced Response class with convenience methods for creating various response types with proper headers and content handling.

class HttpResponse<BodyType> extends Response {
  constructor(body?: BodyType | null, init?: HttpResponseInit);
  
  static text(body?: string, init?: HttpResponseInit): HttpResponse<string>;
  static json<T>(body?: T, init?: HttpResponseInit): HttpResponse<T>;
  static xml(body?: string, init?: HttpResponseInit): HttpResponse<string>;
  static html(body?: string, init?: HttpResponseInit): HttpResponse<string>;
  static arrayBuffer(body?: ArrayBuffer, init?: HttpResponseInit): HttpResponse<ArrayBuffer>;
  static formData(body?: FormData, init?: HttpResponseInit): HttpResponse<FormData>;
  static error(): HttpResponse<any>;
}

interface HttpResponseInit extends ResponseInit {
  type?: ResponseType;
}

Response Creation

Command Line Interface

CLI tool for initializing and managing MSW Service Worker files in browser environments.

# Initialize MSW in project
msw init [publicDir] [--save] [--cwd <directory>]

# Examples:
msw init public/ --save
msw init ./static
msw init --cwd /path/to/project

CLI Documentation

Request Utilities

Utilities for handling request flow, including delays, bypassing MSW interception, and passthrough behavior.

function delay(duration?: number | 'real' | 'infinite'): Promise<void>;
function bypass(input: string | URL | Request, init?: RequestInit): Request;
function passthrough(): HttpResponse<any>;
function getResponse(
  handlers: Array<RequestHandler>,
  request: Request,
  resolutionContext?: ResponseResolutionContext
): Promise<Response | undefined>;

Request Utilities

Types

// Core handler types
type RequestHandler = HttpHandler | GraphQLHandler | WebSocketHandler;

interface RequestHandlerOptions {
  once?: boolean;
}

// HTTP types
interface HttpHandler {
  predicate: string | RegExp | HttpCustomPredicate;
  resolver: HttpResponseResolver;
  options: RequestHandlerOptions;
}

type HttpCustomPredicate = (info: {
  request: Request;
  parsedResult: HttpRequestParsedResult;
}) => boolean;

interface HttpRequestParsedResult {
  match: Match;
  query: RequestQuery;
}

type RequestQuery = Record<string, string | string[]>;

// GraphQL types  
interface GraphQLHandler {
  operationType: 'query' | 'mutation' | 'all';
  predicate: string | DocumentNode | GraphQLCustomPredicate;
  resolver: GraphQLResponseResolver;
}

type GraphQLCustomPredicate = (info: {
  query: any;
  variables: Record<string, any>;
  operationType: string;
  operationName?: string;
}) => boolean;

// WebSocket types
interface WebSocketHandler {
  url: string | RegExp;
  eventHandlers: Map<string, Function[]>;
}

type WebSocketData = string | ArrayBuffer | Blob;

// Setup types
interface StartOptions {
  serviceWorker?: {
    url?: string;
    options?: RegistrationOptions;
  };
  quiet?: boolean;
  onUnhandledRequest?: 'bypass' | 'warn' | 'error';
}

// Path matching types
type Path = string | RegExp;
type PathParams<T extends string = string> = Record<T, string>;

interface Match {
  matches: boolean;
  params: Record<string, string>;
}

// Response types
type DefaultBodyType = string | number | boolean | null | undefined | ArrayBuffer | Blob | FormData | ReadableStream;
type JsonBodyType = Record<string, any> | any[];

// Lifecycle types
interface LifeCycleEventsMap {
  'request:start': [args: { request: Request; requestId: string }];
  'request:match': [args: { request: Request; requestId: string }];
  'request:unhandled': [args: { request: Request; requestId: string }];
  'request:end': [args: { request: Request; requestId: string }];
  'response:mocked': [args: { response: Response; request: Request; requestId: string }];
  'response:bypass': [args: { response: Response; request: Request; requestId: string }];
  'unhandledException': [args: { error: Error; request: Request; requestId: string }];
}

type LifeCycleEventEmitter = {
  on<EventType extends keyof LifeCycleEventsMap>(
    event: EventType,
    listener: (...args: LifeCycleEventsMap[EventType]) => void
  ): void;
  removeListener<EventType extends keyof LifeCycleEventsMap>(
    event: EventType,  
    listener: (...args: LifeCycleEventsMap[EventType]) => void
  ): void;
  removeAllListeners(event?: keyof LifeCycleEventsMap): void;
};

// Utility types
type DelayMode = 'real' | 'infinite';
type ResponseResolutionContext = {
  baseUrl?: string;
};

// Deprecated types (for backward compatibility)
/** @deprecated Use HttpResponse instead */
type StrictResponse<BodyType> = HttpResponse<BodyType>;

// Legacy type aliases
type DefaultRequestMultipartBody = Record<string, string | File>;