or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

application-creation.mdcontext-session-mocking.mdenvironment-configuration.mdhttp-client-mocking.mdhttp-testing-utilities.mdindex.mdlogging-assertions.mdmock-restoration.mdservice-mocking.md
tile.json

http-client-mocking.mddocs/

HTTP Client Mocking

Complete HTTP client mocking system with urllib integration, supporting URL patterns, method filtering, and comprehensive response configuration.

Capabilities

HTTP Client Request Mocking

Mock HTTP client requests with flexible URL matching and response configuration.

/**
 * Mock HTTP client requests
 * @param {string|RegExp} mockUrl - URL pattern to mock
 * @param {string|string[]} [mockMethod] - HTTP methods to mock
 * @param {MockHttpClientResult} mockResult - Mock response configuration
 * @returns {Application} Application instance
 */
app.mockHttpclient(mockUrl, mockMethod, mockResult);

/**
 * Mock HTTP client requests (method overload without method parameter)
 * @param {string|RegExp} mockUrl - URL pattern to mock
 * @param {MockHttpClientResult} mockResult - Mock response configuration
 * @returns {Application} Application instance
 */
app.mockHttpclient(mockUrl, mockResult);

type MockHttpClientResult = ResultObject | ResultFunction | string;

interface ResultObject {
  /** Response data (string, object, or Buffer) */
  data?: string | object | Buffer;
  /** HTTP status code */
  status?: number;
  /** Response headers */
  headers?: any;
  /** Response delay in milliseconds */
  delay?: number;
  /** Keep mock persistent across multiple requests */
  persist?: boolean;
  /** Number of times to repeat the mock */
  repeats?: number;
}

type ResultFunction = (url?: string, opts?: any) => ResultObject | string | void;

Usage Examples:

// Mock API endpoint with JSON response
app.mockHttpclient('https://api.example.com/users', {
  data: [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
  ],
  status: 200,
  headers: { 'content-type': 'application/json' }
});

// Mock with string response
app.mockHttpclient('https://api.example.com/status', 'OK');

// Mock with specific HTTP methods
app.mockHttpclient('https://api.example.com/users', ['POST', 'PUT'], {
  data: { success: true },
  status: 201
});

// Mock with RegExp URL pattern
app.mockHttpclient(/^https:\/\/api\.example\.com\/users\/\d+$/, {
  data: { id: 123, name: 'Alice' }
});

// Mock with delay
app.mockHttpclient('https://slow-api.example.com/data', {
  data: { result: 'slow response' },
  delay: 1000
});

Dynamic Response Mocking

Create dynamic responses based on request parameters and URL.

/**
 * Result function for dynamic responses
 * @param {string} [url] - Requested URL
 * @param {Object} [opts] - Request options
 * @returns {ResultObject|string|void} Response configuration
 */
type ResultFunction = (url?: string, opts?: any) => ResultObject | string | void;

Usage Examples:

// Dynamic response based on URL
app.mockHttpclient(/^https:\/\/api\.example\.com\/users\/(\d+)$/, (url) => {
  const userId = url.match(/\/users\/(\d+)$/)[1];
  return {
    data: { id: parseInt(userId), name: `User ${userId}` },
    status: 200
  };
});

// Dynamic response based on request options
app.mockHttpclient('https://api.example.com/search', (url, opts) => {
  const query = opts.data ? opts.data.q : '';
  return {
    data: {
      query,
      results: query ? [`Result for ${query}`] : []
    }
  };
});

// Conditional responses
app.mockHttpclient('https://api.example.com/auth', (url, opts) => {
  const authHeader = opts.headers && opts.headers.authorization;
  if (authHeader === 'Bearer valid-token') {
    return { data: { authenticated: true }, status: 200 };
  } else {
    return { data: { error: 'Unauthorized' }, status: 401 };
  }
});

// Response based on request method
app.mockHttpclient('https://api.example.com/data', (url, opts) => {
  if (opts.method === 'GET') {
    return { data: { items: [] } };
  } else if (opts.method === 'POST') {
    return { data: { id: 123, created: true }, status: 201 };
  }
  return { status: 405 };
});

Persistent and Repeating Mocks

Configure mocks to persist across multiple requests or repeat a specific number of times.

interface ResultObject {
  /** Keep mock persistent across multiple requests */
  persist?: boolean;
  /** Number of times to repeat the mock */
  repeats?: number;
}

Usage Examples:

// Persistent mock (stays active for multiple requests)
app.mockHttpclient('https://api.example.com/config', {
  data: { version: '1.0', features: ['a', 'b', 'c'] },
  persist: true
});

// Limited repeats
app.mockHttpclient('https://api.example.com/limited', {
  data: { message: 'Limited availability' },
  repeats: 3
});

// Simulate rate limiting
let requestCount = 0;
app.mockHttpclient('https://api.example.com/rate-limited', (url, opts) => {
  requestCount++;
  if (requestCount <= 5) {
    return { data: { success: true } };
  } else {
    return { 
      data: { error: 'Rate limit exceeded' }, 
      status: 429,
      headers: { 'retry-after': '60' }
    };
  }
});

Mock Agent Integration

Direct integration with urllib MockAgent for advanced HTTP mocking scenarios.

/**
 * Get mock HTTP agent for urllib
 * @returns {MockAgent} MockAgent instance from urllib
 */
app.mockAgent();

/**
 * Restore mock HTTP agent
 * @returns {Promise<void>} Promise that resolves when agent is restored
 */
app.mockAgentRestore();

Usage Examples:

// Get mock agent for advanced configuration
const mockAgent = app.mockAgent();

// Configure agent-level mocking
mockAgent.disableNetConnect();
mockAgent.enableNetConnect('127.0.0.1');

// Create pool for specific origin
const pool = mockAgent.get('https://api.example.com');
pool.intercept({
  path: '/users',
  method: 'GET'
}).reply(200, { users: [] });

// Restore agent after tests
afterEach(async () => {
  await app.mockAgentRestore();
});

Response Headers and Status Codes

Comprehensive control over response headers and HTTP status codes.

Usage Examples:

// Custom response headers
app.mockHttpclient('https://api.example.com/data', {
  data: { message: 'Success' },
  status: 200,
  headers: {
    'content-type': 'application/json',
    'x-rate-limit-remaining': '99',
    'x-response-time': '150ms',
    'cache-control': 'no-cache'
  }
});

// Error responses with specific status codes
app.mockHttpclient('https://api.example.com/protected', {
  data: { error: 'Forbidden' },
  status: 403,
  headers: {
    'www-authenticate': 'Bearer realm="api"'
  }
});

// Redirect responses
app.mockHttpclient('https://api.example.com/old-endpoint', {
  status: 301,
  headers: {
    'location': 'https://api.example.com/new-endpoint'
  }
});

// Content-type specific responses
app.mockHttpclient('https://api.example.com/xml', {
  data: '<response><status>ok</status></response>',
  headers: { 'content-type': 'application/xml' }
});

Binary and Buffer Response Mocking

Mock responses with binary data and Buffer objects.

Usage Examples:

// Mock binary response
app.mockHttpclient('https://api.example.com/image', {
  data: Buffer.from('fake-image-data', 'binary'),
  headers: { 'content-type': 'image/png' }
});

// Mock file download
app.mockHttpclient('https://api.example.com/download', {
  data: Buffer.from('file content here'),
  headers: {
    'content-type': 'application/octet-stream',
    'content-disposition': 'attachment; filename="data.txt"'
  }
});

// Mock with base64 data
const imageBuffer = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==', 'base64');
app.mockHttpclient('https://api.example.com/pixel', {
  data: imageBuffer,
  headers: { 'content-type': 'image/png' }
});

Request Matching and Filtering

Advanced request matching with URL patterns, method filtering, and header inspection.

Usage Examples:

// Match specific query parameters
app.mockHttpclient('https://api.example.com/search', (url, opts) => {
  const urlObj = new URL(url);
  const page = urlObj.searchParams.get('page') || '1';
  const limit = urlObj.searchParams.get('limit') || '10';
  
  return {
    data: {
      page: parseInt(page),
      limit: parseInt(limit),
      results: [`Item ${page}-1`, `Item ${page}-2`]
    }
  };
});

// Method-specific responses
app.mockHttpclient('https://api.example.com/resource', 'GET', {
  data: { id: 1, name: 'Resource' }
});
app.mockHttpclient('https://api.example.com/resource', 'POST', {
  data: { id: 2, name: 'New Resource' },
  status: 201
});

// Multiple method matching
app.mockHttpclient('https://api.example.com/flexible', ['GET', 'HEAD'], {
  data: { available: true }
});

// Header-based responses
app.mockHttpclient('https://api.example.com/versioned', (url, opts) => {
  const version = opts.headers && opts.headers['api-version'];
  if (version === 'v2') {
    return { data: { version: 2, features: ['new', 'improved'] } };
  } else {
    return { data: { version: 1, features: ['basic'] } };
  }
});

Legacy Method Support

Support for legacy method names and backward compatibility.

/**
 * Legacy method name for mockHttpclient (deprecated)
 * @deprecated Use app.mockHttpclient instead
 */
app.mockUrllib(...args);

Usage Examples:

// Legacy method (still supported but deprecated)
app.mockUrllib('https://api.example.com/legacy', {
  data: { deprecated: true }
});
// Equivalent to: app.mockHttpclient('https://api.example.com/legacy', { data: { deprecated: true } })