3.8 KiB
3.8 KiB
Subscription/Recurly Test Plan (Rails 8 Branch)
Objective
Close subscription lifecycle regressions by adding executable tests in web and ruby that do not depend on live Recurly network calls.
What Exists
- Webhook coverage exists (request + model) and is active.
- Legacy Recurly suites were revived and are now active:
ruby/spec/jam_ruby/recurly_client_spec.rbruby/spec/jam_ruby/models/user_subscriptions_spec.rb
- Active live Recurly integration coverage now exists in (opt-out via
SKIP_LIVE_RECURLY=1):ruby/spec/jam_ruby/integration/recurly_live_integration_spec.rb
Priority 1: API Subscription Lifecycle (web/spec/requests)
Add request specs for ApiRecurlyController with RecurlyClient stubbed.
1.1 Plan-first then payment
POST /api/recurly/change_subscriptionwith paid plan and no billing info:- expect desired plan is set and response indicates payment method still needed.
POST /api/recurly/update_paymentwith token:- expect
handle_create_subscriptioncalled with user’s desired plan. - expect success payload includes plan metadata and
has_billing_info = true.
- expect
1.2 Payment-first then plan
POST /api/recurly/update_paymentfirst (no desired plan yet):- expect no failure and billing info persisted.
- Then
POST /api/recurly/change_subscriptionto paid plan:- expect desired plan update call and success response.
1.3 Negative paths
change_subscriptionwith unchanged plan:- expect 422 and
No change made to plan.
- expect 422 and
update_paymentwhen client raisesRecurlyClientError:- expect 404 + serialized error payload.
Priority 2: Sync Decision Tree (ruby/spec/jam_ruby/models)
Add focused unit specs for RecurlyClient#sync_subscription with Recurly API mocked.
2.1 Unchanged/good-standing path
- account exists, not past_due, active subscription, desired == effective.
- expect sync code
good_standing_unchangedand no plan mutation.
2.2 Canceled/expired path
- no active subscription (or expired).
- expect effective plan set to free (
nil) and sync codeno_subscription_or_expired.
2.3 Past-due path
- account
has_past_due_invoice = true. - expect effective plan dropped to free and sync code
is_past_due_changed.
2.4 Trial and free-month behavior
- user in trial with desired gold and active account.
- verify trial code path + post-trial behavior once time advances (use
Timecoportravel_todepending what is stable in this suite).
Priority 3: Hourly Job Integration (ruby/spec/jam_ruby/resque or model-level)
- Validate
JamRuby::HourlyJob.performtriggersUser.hourly_check. - Validate
User.subscription_synconly selects intended users and calls client sync. - Validate
User.subscription_transaction_syncadvancesGenericState.recurly_transactions_last_sync_atusing mocked transaction stream.
Priority 4: Browser Coverage (web/spec/features)
Add high-value feature coverage for subscription management screen:
- plan-first flow shows payment-needed state and routes to update payment.
- payment-first flow then selecting plan results in active paid subscription state.
Use stubs/fakes around RecurlyClient in feature env to avoid external dependency.
Execution Order
- Request specs for
ApiRecurlyController(fast, high signal). RecurlyClient#sync_subscriptionspecs (logic-heavy, deterministic).- Hourly sync integration coverage.
- Browser feature tests for UX flow parity.
Definition of Done
- New tests are active (not
xdescribe/commented out). - Both plan-first and payment-first lifecycles are covered.
- Hourly sync scenarios for unchanged, canceled/expired, and past-due are covered.
- First-free-month/gold behavior has explicit time-based assertions.
docs/dev/subscriptions.mdupdated with links to new spec files and scenarios.