defmodule Tarakan.Billing.StripeStub do @moduledoc """ Test double for `Tarakan.Billing.Stripe`. Serves deterministic default responses for the endpoints the market flow uses. Tests can override behaviour per process: Tarakan.Billing.StripeStub.respond_with({:error, :card_declined}) Tarakan.Billing.StripeStub.respond_with(fn :post, "/v1/refunds", _body -> ... end) Tarakan.Billing.StripeStub.reset() """ @behaviour Tarakan.Billing.Stripe @impl true def request(method, path, body_or_params \\ nil) do case Process.get(:stripe_stub_response) do nil -> default_response(method, path, body_or_params) fun when is_function(fun, 3) -> fun.(method, path, body_or_params) response -> response end end @doc "Overrides the stubbed response for the current test process." def respond_with(response_or_fun), do: Process.put(:stripe_stub_response, response_or_fun) @doc "Restores the default responses for the current test process." def reset, do: Process.delete(:stripe_stub_response) defp default_response(:post, "/v1/checkout/sessions", _body) do id = "cs_test_#{System.unique_integer([:positive])}" {:ok, %{ "id" => id, "url" => "https://checkout.stripe.com/c/pay/#{id}", "payment_intent" => "pi_#{id}", "status" => "open" }} end defp default_response(:get, "/v1/checkout/sessions/" <> id, _params) do {:ok, %{"id" => id, "payment_intent" => "pi_#{id}", "status" => "complete"}} end defp default_response(:post, "/v1/refunds", body) do payment_intent = body[:payment_intent] || body["payment_intent"] {:ok, %{ "id" => "re_test_#{System.unique_integer([:positive])}", "payment_intent" => payment_intent, "status" => "succeeded" }} end defp default_response(:post, "/v1/billing_portal/sessions", body) do customer = case body do map when is_map(map) -> map[:customer] || map["customer"] list when is_list(list) -> Enum.find_value(list, fn {:customer, value} -> value {"customer", value} -> value _other -> nil end) _other -> nil end {:ok, %{ "id" => "bps_test_#{System.unique_integer([:positive])}", "customer" => customer, "url" => "https://billing.stripe.com/p/session/test_#{System.unique_integer([:positive])}" }} end defp default_response(_method, _path, _body), do: {:error, :unexpected_request} end