Skills Development Mocking Flexport API for Development

Mocking Flexport API for Development

v20260423
flexport-local-dev-loop
This guide establishes a fast, reproducible local development workflow for integrating with Flexport logistics. Since an official SDK is unavailable, it utilizes a typed HTTP client wrapper combined with mock responses. This setup allows developers to quickly set up, test, and iterate on shipment data handling, ensuring robust development cycles without relying on live API access.
Get Skill
86 downloads
Overview

Flexport Local Dev Loop

Overview

Set up a fast, reproducible local development workflow for Flexport integrations. Since Flexport has no official SDK, the dev loop centers on a typed HTTP client wrapper with mock responses for testing.

Instructions

Step 1: Project Structure

flexport-integration/
├── src/
│   ├── flexport/
│   │   ├── client.ts          # Typed Flexport API client
│   │   ├── types.ts           # API response types
│   │   └── mock-data.ts       # Test fixtures
│   └── index.ts
├── tests/
│   ├── flexport.test.ts       # Unit tests with mocks
│   └── integration.test.ts   # Live API tests (CI only)
├── .env.local                 # Local secrets (git-ignored)
├── .env.example
└── package.json

Step 2: Typed Client Wrapper

// src/flexport/types.ts
interface FlexportShipment {
  id: string;
  status: 'booked' | 'in_transit' | 'arrived' | 'delivered';
  freight_type: 'ocean' | 'air' | 'trucking';
  origin_port: { code: string; name: string };
  destination_port: { code: string; name: string };
  cargo_ready_date: string;
  estimated_arrival_date: string;
}

interface FlexportResponse<T> {
  data: { records: T[]; total_count: number };
}

// src/flexport/client.ts
export class FlexportClient {
  private base = 'https://api.flexport.com';
  private headers: Record<string, string>;

  constructor(apiKey: string) {
    this.headers = {
      'Authorization': `Bearer ${apiKey}`,
      'Flexport-Version': '2',
      'Content-Type': 'application/json',
    };
  }

  async listShipments(page = 1, per = 25): Promise<FlexportResponse<FlexportShipment>> {
    const res = await fetch(`${this.base}/shipments?page=${page}&per=${per}`, {
      headers: this.headers,
    });
    if (!res.ok) throw new Error(`Flexport ${res.status}: ${await res.text()}`);
    return res.json();
  }
}

Step 3: Mock Data for Testing

// src/flexport/mock-data.ts
export const mockShipment: FlexportShipment = {
  id: 'shp_test_001',
  status: 'in_transit',
  freight_type: 'ocean',
  origin_port: { code: 'CNSHA', name: 'Shanghai' },
  destination_port: { code: 'USLAX', name: 'Los Angeles' },
  cargo_ready_date: '2025-04-01',
  estimated_arrival_date: '2025-05-15',
};

export function mockFlexportFetch(path: string) {
  if (path.includes('/shipments')) {
    return { data: { records: [mockShipment], total_count: 1 } };
  }
  throw new Error(`No mock for ${path}`);
}

Step 4: Vitest Unit Tests

// tests/flexport.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { FlexportClient } from '../src/flexport/client';
import { mockShipment } from '../src/flexport/mock-data';

describe('FlexportClient', () => {
  beforeEach(() => {
    vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
      ok: true,
      json: () => Promise.resolve({ data: { records: [mockShipment], total_count: 1 } }),
    }));
  });

  it('lists shipments', async () => {
    const client = new FlexportClient('test-key');
    const result = await client.listShipments();
    expect(result.data.records).toHaveLength(1);
    expect(result.data.records[0].freight_type).toBe('ocean');
  });

  it('sends correct auth header', async () => {
    const client = new FlexportClient('test-key');
    await client.listShipments();
    expect(fetch).toHaveBeenCalledWith(
      expect.stringContaining('/shipments'),
      expect.objectContaining({ headers: expect.objectContaining({ 'Flexport-Version': '2' }) }),
    );
  });
});

Step 5: Dev Scripts

{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "test": "vitest",
    "test:watch": "vitest --watch",
    "test:integration": "FLEXPORT_LIVE=1 vitest tests/integration.test.ts"
  }
}

Resources

Next Steps

See flexport-sdk-patterns for production-ready code patterns.

Info
Category Development
Name flexport-local-dev-loop
Version v20260423
Size 4.53KB
Updated At 2026-04-28
Language