Accrue.Test.Factory (accrue v1.0.0)

Copy Markdown View Source

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:

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(attrs \\ %{})

Active subscription (post-trial).

canceled_subscription(attrs \\ %{})

@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).

canceling_subscription(attrs \\ %{})

@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.

customer(attrs \\ %{})

@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.

grace_period_subscription(attrs \\ %{})

@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(attrs \\ %{})

Incomplete subscription (initial payment not confirmed).

past_due_subscription(attrs \\ %{})

Past-due subscription (failed renewal).

subscription(attrs \\ %{})

@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).

trial_ending_subscription(attrs \\ %{})

@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(attrs \\ %{})

Trialing subscription (14-day trial).