PaperTiger (PaperTiger v1.0.2)

Copy Markdown View Source

PaperTiger - A stateful mock Stripe server for testing.

Quick Start

# Start the server
{:ok, _pid} = PaperTiger.start()

# Make API calls via HTTP
response = HTTP.post!("/v1/customers", ...)

# Clean up between tests
PaperTiger.flush()

Time Control

PaperTiger supports three clock modes for deterministic testing:

  • :real - Use system time (default)
  • :accelerated - Time moves faster (useful for subscription billing tests)
  • :manual - Freeze time and advance manually

Examples

# Manual time control
PaperTiger.set_clock_mode(:manual, timestamp: 1234567890)
PaperTiger.advance_time(3600)  # Advance 1 hour

# Accelerated time (10x speed)
PaperTiger.set_clock_mode(:accelerated, multiplier: 10)

Resource Cleanup

# Flush specific resource
PaperTiger.flush(:customers)

# Flush all resources
PaperTiger.flush()

Summary

Functions

Advances time in manual mode.

Returns the current clock mode.

Flushes (clears) all resources or a specific resource type.

Flushes (clears) all resources across all namespaces.

Returns the port PaperTiger will use.

Returns the current Unix timestamp according to the configured clock.

Registers webhook endpoints from application configuration.

Registers a webhook endpoint for test orchestration.

Sets the clock mode.

Starts the PaperTiger application.

Returns configuration for stripity_stripe to use PaperTiger as the Stripe API backend.

Functions

advance_time(amount)

@spec advance_time(integer() | keyword()) :: :ok

Advances time in manual mode.

Examples

PaperTiger.advance_time(seconds: 3600)
PaperTiger.advance_time(days: 30)
PaperTiger.advance_time(86400)  # 1 day

clock_mode()

@spec clock_mode() :: atom()

Returns the current clock mode.

Examples

PaperTiger.clock_mode()
#=> :real

flush()

@spec flush() :: :ok

Flushes (clears) all resources or a specific resource type.

PaperTiger supports namespace-based isolation (used by PaperTiger.Test) so multiple test suites can run concurrently. flush/0 clears data only for the current namespace (default :global).

If you need to wipe all namespaces, use flush_all/0.

Examples

PaperTiger.flush()  # Clear all resources in current namespace
PaperTiger.flush(:customers)  # Clear only customers

flush(arg1)

@spec flush(atom()) :: :ok | {:error, :unknown_resource}

flush_all()

@spec flush_all() :: :ok

Flushes (clears) all resources across all namespaces.

This is the legacy behavior of flush/0. Prefer flush/0 when running tests concurrently with PaperTiger.Test sandboxing.

get_port()

@spec get_port() :: integer()

Returns the port PaperTiger will use.

If PaperTiger is already running, returns the actual port in use. If not started yet, it resolves and caches the port so config and runtime stay consistent.

Examples

PaperTiger.get_port()
#=> 59342

now()

@spec now() :: integer()

Returns the current Unix timestamp according to the configured clock.

Examples

PaperTiger.now()
#=> 1234567890

register_configured_webhooks()

@spec register_configured_webhooks() :: {:ok, [map()]}

Registers webhook endpoints from application configuration.

This function reads webhook endpoints from the :paper_tiger, :webhooks config and registers them automatically. Useful for setting up test webhooks at startup.

Configuration

# In config/test.exs
config :paper_tiger,
  webhooks: [
    [url: "http://localhost:4000/webhooks/stripe"],
    [url: "http://localhost:4000/webhooks/events", events: ["invoice.paid"]]
  ]

Examples

# Register all configured webhooks
PaperTiger.register_configured_webhooks()
#=> {:ok, [%{id: "we_..."}, %{id: "we_..."}]}

Returns

{:ok, webhooks} where webhooks is a list of registered webhook maps.

register_webhook(opts)

@spec register_webhook(keyword()) :: {:ok, map()}

Registers a webhook endpoint for test orchestration.

This is used by the POST /_config/webhooks endpoint for test setup.

Parameters

  • :url - Webhook endpoint URL (required)
  • :secret - Webhook signing secret (default: "whsec_paper_tiger_test")
  • :events - List of event types to subscribe to (default: ["*"] for all events)

Examples

# Register with all events
PaperTiger.register_webhook(url: "http://localhost:4000/webhooks/stripe")

# Register with specific events
PaperTiger.register_webhook(
  url: "http://localhost:4000/webhooks/stripe",
  secret: "whsec_custom",
  events: ["customer.created", "invoice.paid"]
)

set_clock_mode(mode, opts \\ [])

@spec set_clock_mode(
  atom(),
  keyword()
) :: :ok

Sets the clock mode.

Modes

  • :real - Use system time
  • :accelerated - Time runs faster (specify :multiplier option)
  • :manual - Manual control (specify :timestamp option)

Examples

PaperTiger.set_clock_mode(:real)
PaperTiger.set_clock_mode(:accelerated, multiplier: 10)
PaperTiger.set_clock_mode(:manual, timestamp: 1234567890)

start(opts \\ [])

@spec start(keyword()) :: {:ok, pid()} | {:error, term()}

Starts the PaperTiger application.

Options

  • :port - HTTP port (default: random port 59000-60000, checked for availability)
  • :clock_mode - Time mode (default: :real)

Examples

{:ok, _pid} = PaperTiger.start()
{:ok, _pid} = PaperTiger.start(port: 4002, clock_mode: :manual)

stripity_stripe_config(opts \\ [])

@spec stripity_stripe_config(keyword()) :: keyword()

Returns configuration for stripity_stripe to use PaperTiger as the Stripe API backend.

This helper generates the configuration needed to point stripity_stripe at PaperTiger instead of the real Stripe API. Use this in your config files or test setup to simplify integration.

Options

  • :port - PaperTiger port (default: resolve and cache before startup)
  • :host - PaperTiger host (default: "localhost")
  • :webhook_secret - Webhook signing secret (default: "whsec_paper_tiger_test")
  • :sandbox - Enable sandbox isolation for concurrent tests (default: true)

Sandbox Mode

When sandbox: true (the default), the returned config includes http_module: PaperTiger.StripityStripeHackney, which injects namespace headers for test isolation. This allows tests to run concurrently without data leakage between tests.

Set sandbox: false if you want global (non-isolated) mode, though this is rarely needed.

Examples

# In config/test.exs (recommended)
config :stripity_stripe, PaperTiger.stripity_stripe_config()

# With custom options
config :stripity_stripe, PaperTiger.stripity_stripe_config(port: 4002)

# Disable sandbox (not recommended for concurrent tests)
config :stripity_stripe, PaperTiger.stripity_stripe_config(sandbox: false)

Returns

Keyword list with:

  • :api_key - Mock API key
  • :public_key - Mock publishable key
  • :api_base_url - URL pointing to PaperTiger
  • :webhook_signing_key - Webhook signing secret
  • :http_module - Custom HTTP module for sandbox isolation (when sandbox: true)