Test helpers for running PaperTiger tests concurrently.
Provides a sandbox mechanism similar to Ecto.Adapters.SQL.Sandbox that
isolates test data by namespace, allowing tests to run with async: true.
Usage
defmodule MyApp.StripeTest do
use ExUnit.Case, async: true
setup :checkout_paper_tiger
test "creates a customer" do
# Data is isolated to this test process
{:ok, customer} = PaperTiger.TestClient.create_customer(%{...})
end
endHow It Works
When checkout_paper_tiger/1 is called:
- Stores the test process PID as a namespace in the process dictionary
- All subsequent PaperTiger operations scope data to that namespace
- On test exit, only that namespace's data is cleaned up
This allows multiple tests to run concurrently without interfering with each other's data.
Summary
Functions
Asserts that a webhook was delivered with the given event type.
Returns HTTP headers for authenticated sandbox requests.
Returns the base URL for PaperTiger HTTP requests.
Checks out a PaperTiger sandbox for the current test.
Cleans up all data for the given namespace.
Clears all collected webhook deliveries for the current namespace.
Returns the current namespace, or :global if not in a sandboxed test.
Enables webhook collection mode for the current test.
Gets all webhook deliveries collected during the test.
Gets webhook deliveries filtered by event type.
Asserts that no webhook was delivered with the given event type.
Returns HTTP headers needed for sandbox isolation.
Functions
Asserts that a webhook was delivered with the given event type.
This is a convenience helper that combines getting deliveries and asserting. Returns the matching deliveries for further assertions.
Example
test "customer creation triggers webhook" do
{:ok, customer} = Stripe.Customer.create(%{email: "test@example.com"})
[delivery] = PaperTiger.Test.assert_webhook_delivered("customer.created")
assert delivery.event_data.object.email == "test@example.com"
end
Returns HTTP headers for authenticated sandbox requests.
Combines authorization header with sandbox namespace headers. Use this helper for most HTTP requests to PaperTiger.
Options
:api_key- Override the default API key (default: "sk_test_mock")
Example
Req.post(base_url("/v1/customers"),
form: [email: "test@example.com"],
headers: auth_headers()
)
# With custom API key
Req.get(url, headers: auth_headers(api_key: "sk_test_custom"))
Returns the base URL for PaperTiger HTTP requests.
Uses the configured port from application config.
Example
iex> PaperTiger.Test.base_url()
"http://localhost:4001"
iex> PaperTiger.Test.base_url("/v1/customers")
"http://localhost:4001/v1/customers"
@spec checkout_paper_tiger(map()) :: :ok
Checks out a PaperTiger sandbox for the current test.
Use as a setup callback:
setup :checkout_paper_tigerOr call directly in setup block:
setup do
PaperTiger.Test.checkout_paper_tiger(%{})
:ok
endChild Process Support
This function also sets a shared namespace via Application env, which allows child processes (like Phoenix LiveView) to use the same sandbox. This is essential for integration tests where Stripe calls happen in spawned processes.
Returns :ok for use with ExUnit's setup callbacks.
@spec cleanup_namespace(pid() | :global) :: :ok
Cleans up all data for the given namespace.
Called automatically on test exit when using checkout_paper_tiger/1.
@spec clear_delivered_webhooks() :: :ok
Clears all collected webhook deliveries for the current namespace.
Useful when testing multiple operations and wanting to verify webhooks from a specific action.
Example
test "verifies webhooks for second operation only" do
{:ok, _} = Stripe.Customer.create(%{email: "first@example.com"})
PaperTiger.Test.clear_delivered_webhooks()
{:ok, _} = Stripe.Customer.create(%{email: "second@example.com"})
# Only sees the second customer's webhook
assert [%{event_type: "customer.created"}] = PaperTiger.Test.get_delivered_webhooks()
end
@spec current_namespace() :: pid() | :global
Returns the current namespace, or :global if not in a sandboxed test.
@spec enable_webhook_collection() :: :ok
Enables webhook collection mode for the current test.
Call this in your test setup to capture webhooks instead of delivering them. Automatically restores the previous mode on test exit.
Example
setup do
:ok = checkout_paper_tiger(%{})
:ok = enable_webhook_collection()
:ok
end
test "creates customer and triggers webhook" do
{:ok, _customer} = Stripe.Customer.create(%{email: "test@example.com"})
[delivery] = PaperTiger.Test.assert_webhook_delivered("customer.created")
assert delivery.event_data.object.email == "test@example.com"
end
@spec get_delivered_webhooks() :: [map()]
Gets all webhook deliveries collected during the test.
Only works when webhook_mode: :collect is configured.
Returns a list of delivery records sorted by creation time (oldest first).
Example
setup do
Application.put_env(:paper_tiger, :webhook_mode, :collect)
on_exit(fn -> Application.delete_env(:paper_tiger, :webhook_mode) end)
:ok
end
test "creates customer and triggers webhook" do
{:ok, _customer} = Stripe.Customer.create(%{email: "test@example.com"})
deliveries = PaperTiger.Test.get_delivered_webhooks()
assert [%{event_type: "customer.created"}] = deliveries
end
Gets webhook deliveries filtered by event type.
Supports wildcard patterns like "customer." or "invoice.payment_".
Examples
# Get all customer.created events
get_delivered_webhooks("customer.created")
# Get all customer events
get_delivered_webhooks("customer.*")
# Get all invoice payment events
get_delivered_webhooks("invoice.payment_*")
@spec refute_webhook_delivered(String.t()) :: :ok
Asserts that no webhook was delivered with the given event type.
Example
test "soft delete doesn't trigger delete webhook" do
{:ok, customer} = Stripe.Customer.create(%{email: "test@example.com"})
PaperTiger.Test.clear_delivered_webhooks()
soft_delete_customer(customer)
PaperTiger.Test.refute_webhook_delivered("customer.deleted")
end
Returns HTTP headers needed for sandbox isolation.
Include these headers in HTTP requests to PaperTiger to ensure data is scoped to the current test's namespace.
Example
Req.post(url, headers: PaperTiger.Test.sandbox_headers())
# Or merge with other headers:
Req.get(url,
headers: [{"authorization", "Bearer sk_test_mock"}] ++ PaperTiger.Test.sandbox_headers()
)