CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-msw

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

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

react-native-setup.mddocs/

React Native Setup

React Native environment setup using fetch and XMLHttpRequest interception for API mocking in React Native applications.

Capabilities

Setup Server Function

Sets up request interception in React Native applications using fetch and XMLHttpRequest interceptors.

/**
 * Sets up a requests interception in React Native with the given request handlers
 * @param handlers - List of request handlers
 * @returns SetupServerCommonApi instance for managing request interception
 */
function setupServer(...handlers: Array<RequestHandler>): SetupServerCommonApi;

interface SetupServerCommonApi {
  /** Start request interception with optional configuration */
  listen(options?: { onUnhandledRequest?: 'bypass' | 'warn' | 'error' }): void;
  /** Stop request interception and restore original behavior */
  close(): void;
  /** Add new request handlers at runtime */
  use(...handlers: Array<RequestHandler>): void;
  /** Replace current handlers with new ones */
  resetHandlers(...handlers?: Array<RequestHandler>): void;
  /** Restore original handlers */
  restoreHandlers(): void;
  /** Get list of currently active handlers */
  listHandlers(): ReadonlyArray<RequestHandler>;
  /** Event emitter for lifecycle events */
  events: LifeCycleEventEmitter;
}

Usage Examples:

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

// Define request handlers
const 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 }
    );
  })
];

// Create and start server
const server = setupServer(...handlers);
server.listen();

// Your React Native app will now have API calls intercepted
// No additional setup required - works with fetch, axios, etc.

React Native Integration Patterns

Common patterns for integrating MSW in React Native applications.

Test Environment Setup:

// In your test setup file (e.g., jest.setup.js)
import { setupServer } from 'msw/native';
import { handlers } from './mocks/handlers';

const server = setupServer(...handlers);

beforeAll(() => {
  server.listen({ onUnhandledRequest: 'error' });
});

afterEach(() => {
  server.resetHandlers();
});

afterAll(() => {
  server.close();
});

export { server };

Development Environment Setup:

// In your App.js or index.js (development only)
import { setupServer } from 'msw/native';
import { handlers } from './mocks/handlers';

if (__DEV__) {
  const server = setupServer(...handlers);
  server.listen({
    onUnhandledRequest: 'bypass', // Allow unmocked requests in development
  });
  
  // Optional: Enable request logging
  server.events.on('request:start', ({ request }) => {
    console.log('MSW intercepted:', request.method, request.url);
  });
}

Dynamic Handler Management:

import { setupServer } from "msw/native";

const server = setupServer();
server.listen();

// Add handlers for specific test scenarios
function enableUserMocking() {
  server.use(
    http.get('/api/user', () => HttpResponse.json({ name: 'Test User' })),
    http.post('/api/user', () => new Response('Created', { status: 201 }))
  );
}

// Remove specific handlers
function disableUserMocking() {
  server.resetHandlers(
    // Keep only non-user handlers
    ...originalHandlers.filter(handler => !handler.predicate.includes('/api/user'))
  );
}

// Restore to original state
function resetAllMocking() {
  server.restoreHandlers();
}

Error Simulation:

import { setupServer } from "msw/native";
import { http, HttpResponse, delay } from "msw";

const server = setupServer();
server.listen();

// Simulate network errors
function simulateNetworkErrors() {
  server.use(
    http.get('/api/data', async () => {
      await delay(100);
      return HttpResponse.error();
    }),
    
    http.post('/api/submit', async () => {
      await delay(2000);
      return new Response('Server Error', { status: 500 });
    })
  );
}

// Simulate slow network
function simulateSlowNetwork() {
  server.use(
    http.all('*', async () => {
      await delay(3000); // 3 second delay
      return HttpResponse.json({ data: 'Slow response' });
    })
  );
}

Lifecycle Events

React Native setup supports the same lifecycle events as Node.js setup for monitoring request interception.

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 }];
}

Event Monitoring Example:

import { setupServer } from "msw/native";

const server = setupServer(...handlers);
server.listen();

// Monitor all requests
server.events.on('request:start', ({ request, requestId }) => {
  console.log(`[${requestId}] ${request.method} ${request.url}`);
});

// Monitor successful mocks
server.events.on('response:mocked', ({ request, response, requestId }) => {
  console.log(`[${requestId}] Mocked ${request.url} -> ${response.status}`);
});

// Monitor unhandled requests
server.events.on('request:unhandled', ({ request, requestId }) => {
  console.warn(`[${requestId}] Unhandled request: ${request.method} ${request.url}`);
});

// Monitor errors
server.events.on('unhandledException', ({ error, request, requestId }) => {
  console.error(`[${requestId}] Handler error for ${request.url}:`, error);
});

Platform Differences

React Native setup differs from browser and Node.js environments in specific ways:

Network Layer:

  • Uses FetchInterceptor and XMLHttpRequestInterceptor instead of Service Workers or HTTP module patching
  • Intercepts both fetch() calls and XMLHttpRequest instances
  • Compatible with popular HTTP libraries like axios, fetch, and React Native's built-in networking

Installation:

  • No Service Worker file copying required (unlike browser setup)
  • No additional CLI commands needed
  • Works immediately after calling server.listen()

Limitations:

  • No WebSocket interception support (React Native WebSocket implementation varies)
  • Some advanced networking features may not be intercepted depending on the React Native version
  • Native networking modules (like those used by some third-party libraries) may bypass interception

Best Practices:

  • Use in development and testing environments only
  • Call server.close() when your app unmounts or tests complete
  • Use onUnhandledRequest: 'bypass' in development to allow real API calls
  • Use onUnhandledRequest: 'error' in tests to catch missing mocks

Types

// Server setup types
type SetupServerCommonApi = {
  listen(options?: { onUnhandledRequest?: 'bypass' | 'warn' | 'error' }): void;
  close(): void;
  use(...handlers: Array<RequestHandler>): void;
  resetHandlers(...handlers?: Array<RequestHandler>): void;
  restoreHandlers(): void;
  listHandlers(): ReadonlyArray<RequestHandler>;
  events: LifeCycleEventEmitter;
};

// Handler types (same as other environments)
type RequestHandler = HttpHandler | GraphQLHandler | WebSocketHandler;

// Event emitter types
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;
};

docs

browser-setup.md

cli.md

graphql-handlers.md

http-handlers.md

index.md

nodejs-setup.md

react-native-setup.md

response-creation.md

utilities.md

websocket-handlers.md

tile.json