jam-cloud/web/ai/tasks/test-subscriptions-plan.md

79 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.rb`
- `ruby/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_subscription` with paid plan and no billing info:
- expect desired plan is set and response indicates payment method still needed.
- `POST /api/recurly/update_payment` with token:
- expect `handle_create_subscription` called with users desired plan.
- expect success payload includes plan metadata and `has_billing_info = true`.
### 1.2 Payment-first then plan
- `POST /api/recurly/update_payment` first (no desired plan yet):
- expect no failure and billing info persisted.
- Then `POST /api/recurly/change_subscription` to paid plan:
- expect desired plan update call and success response.
### 1.3 Negative paths
- `change_subscription` with unchanged plan:
- expect 422 and `No change made to plan`.
- `update_payment` when client raises `RecurlyClientError`:
- 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_unchanged` and no plan mutation.
### 2.2 Canceled/expired path
- no active subscription (or expired).
- expect effective plan set to free (`nil`) and sync code `no_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 `Timecop` or `travel_to` depending what is stable in this suite).
## Priority 3: Hourly Job Integration (`ruby/spec/jam_ruby/resque` or model-level)
- Validate `JamRuby::HourlyJob.perform` triggers `User.hourly_check`.
- Validate `User.subscription_sync` only selects intended users and calls client sync.
- Validate `User.subscription_transaction_sync` advances `GenericState.recurly_transactions_last_sync_at` using 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
1. Request specs for `ApiRecurlyController` (fast, high signal).
2. `RecurlyClient#sync_subscription` specs (logic-heavy, deterministic).
3. Hourly sync integration coverage.
4. 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.md` updated with links to new spec files and scenarios.