Phase 3 test factories (D3-79..85).
First-class subscription-state factories that route through the
Accrue.Processor.Fake adapter and derive timestamps from
Accrue.Clock.utc_now/0. Nine states are covered:
customer/1subscription/1— primitive, takes a:statusoverridetrialing_subscription/1active_subscription/1past_due_subscription/1incomplete_subscription/1canceled_subscription/1canceling_subscription/1(active + cancel_at_period_end)grace_period_subscription/1(canceled but within period)trial_ending_subscription/1(trial_end within 72h)
Factories live in lib/ (not test/) so the Phase 8 mix accrue.seed
task can use them in :dev. They have no side effects beyond calling
the configured processor, which in test/dev is the in-memory Fake.
Usage
%{subscription: sub} = Accrue.Test.Factory.active_subscription()Every factory returns a map with :customer, :subscription, and
:items keys (except customer/1 which returns %{customer:, owner_id:}).
Test-clock safety
All timestamps derive from Accrue.Clock.utc_now/0, which in the test
env routes through Accrue.Processor.Fake.now/0. Advancing the fake
clock therefore advances all factory-produced timestamps in the same
direction — no hidden wall-clock calls that would skew relative to
the test clock.
Summary
Functions
Active subscription (post-trial).
Fully-canceled subscription. Builds an active sub and then calls
Accrue.Billing.cancel/2, so the state transitions through the real
cancel path (not just a raw status flip).
"Canceling" subscription — active with cancel_at_period_end: true
and a future current_period_end. Passes Subscription.canceling?/1.
Creates a Customer row backed by a freshly-minted Fake customer.
"Grace period" subscription — canceled, but current_period_end
still in the future so the host app can keep granting access.
Incomplete subscription (initial payment not confirmed).
Past-due subscription (failed renewal).
Primitive subscription factory. Use the status-named variants below in tests; this is the underlying dispatch point.
Trialing subscription with trial_end within 72 hours, for testing
the trial.ending_soon notifier path.
Trialing subscription (14-day trial).
Functions
Active subscription (post-trial).
@spec canceled_subscription(map()) :: %{ customer: Accrue.Billing.Customer.t(), subscription: Accrue.Billing.Subscription.t(), items: [struct()] }
Fully-canceled subscription. Builds an active sub and then calls
Accrue.Billing.cancel/2, so the state transitions through the real
cancel path (not just a raw status flip).
@spec canceling_subscription(map()) :: %{ customer: Accrue.Billing.Customer.t(), subscription: Accrue.Billing.Subscription.t(), items: [struct()] }
"Canceling" subscription — active with cancel_at_period_end: true
and a future current_period_end. Passes Subscription.canceling?/1.
@spec customer(map()) :: %{ customer: Accrue.Billing.Customer.t(), owner_id: String.t() }
Creates a Customer row backed by a freshly-minted Fake customer.
Returns %{customer: %Customer{}, owner_id: String.t()}. Accepts an
optional attrs map with :owner_id, :owner_type, and :email
overrides.
@spec grace_period_subscription(map()) :: %{ customer: Accrue.Billing.Customer.t(), subscription: Accrue.Billing.Subscription.t(), items: [struct()] }
"Grace period" subscription — canceled, but current_period_end
still in the future so the host app can keep granting access.
Incomplete subscription (initial payment not confirmed).
Past-due subscription (failed renewal).
@spec subscription(map()) :: %{ customer: Accrue.Billing.Customer.t(), subscription: Accrue.Billing.Subscription.t(), items: [struct()] }
Primitive subscription factory. Use the status-named variants below in tests; this is the underlying dispatch point.
Accepts :status, :price_id, :owner_id, and :trial_end (a
Duration tuple understood by Accrue.Billing.subscribe/3).
@spec trial_ending_subscription(map()) :: %{ customer: Accrue.Billing.Customer.t(), subscription: Accrue.Billing.Subscription.t(), items: [struct()] }
Trialing subscription with trial_end within 72 hours, for testing
the trial.ending_soon notifier path.
Trialing subscription (14-day trial).