Skip to content

E2E: subscription purchase (Stripe test mode)

e2e/subscription.spec.ts (Playwright, bun run test:e2e) drives the whole buying process for the All-in monthly plan against a real deployment: signup → /subscribe → Stripe hosted Checkout with the 4242 4242 4242 4242 test card → /subscribe/success → webhook activates the org → the paywall gate reports subscribed: true → Stripe issued a paid invoice for the charge.

The deterministic counterpart — the webhook status machine including the invoicing failure path (invoice.payment_failedpast_due) — lives in apps/api/subscriptions/routes/subscriptions.webhooks.routes.test.ts and runs in bun run test:unit with real signature verification (no network).

The target must run Stripe test mode end-to-end — that is what the preview env context provisions via deploy/coolify/coolify.preview.env:

  • STRIPE_SECRET_KEY = sk_test_…, test-mode STRIPE_PRICE_ALLIN_MONTHLY/_YEARLY
  • A test-mode webhook endpoint pointed at https://<target-api>/api/subscriptions/webhooks/stripe, its whsec_… in STRIPE_WEBHOOK_SECRET. Activation is webhook-driven, not redirect-driven — if Stripe can’t reach the endpoint the test times out at “subscription never became active”.
  • A throwaway database (platform_preview) — each run signs up a fresh user/org.
Terminal window
# Against a preview deployment
E2E_DASHBOARD_URL=https://<preview-dashboard-domain> \
E2E_API_URL=https://<preview-api-domain> \
E2E_STRIPE_SECRET_KEY=sk_test_… \
bun run test:e2e
# Against local dev (webhook needs a tunnel)
stripe listen --forward-to localhost:3000/api/subscriptions/webhooks/stripe # terminal 1
E2E_DASHBOARD_URL=http://localhost:5000 E2E_API_URL=http://localhost:3000 \
E2E_STRIPE_SECRET_KEY=sk_test_… bun run test:e2e # terminal 2
  • Without E2E_DASHBOARD_URL/E2E_API_URL the suite skips (CI-safe).
  • E2E_STRIPE_SECRET_KEY is optional; it enables the paid-invoice assertion via the Stripe API. A non-sk_test_ key is refused, as is E2E_API_URL=…platform-api.viite.ai (prod).
  • Stripe’s hosted checkout DOM varies by locale/experiment; if the payment page changes, the selectors to adjust are all in e2e/subscription.spec.ts step 4.