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
Advances time in manual mode.
Examples
PaperTiger.advance_time(seconds: 3600)
PaperTiger.advance_time(days: 30)
PaperTiger.advance_time(86400) # 1 day
@spec clock_mode() :: atom()
Returns the current clock mode.
Examples
PaperTiger.clock_mode()
#=> :real
@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
@spec flush(atom()) :: :ok | {:error, :unknown_resource}
@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.
@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
@spec now() :: integer()
Returns the current Unix timestamp according to the configured clock.
Examples
PaperTiger.now()
#=> 1234567890
@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.
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"]
)
Sets the clock mode.
Modes
:real- Use system time:accelerated- Time runs faster (specify:multiplieroption):manual- Manual control (specify:timestampoption)
Examples
PaperTiger.set_clock_mode(:real)
PaperTiger.set_clock_mode(:accelerated, multiplier: 10)
PaperTiger.set_clock_mode(:manual, timestamp: 1234567890)
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)
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)