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_failed → past_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).
Requirements on the target environment
Section titled “Requirements on the target environment”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-modeSTRIPE_PRICE_ALLIN_MONTHLY/_YEARLY- A test-mode webhook endpoint pointed at
https://<target-api>/api/subscriptions/webhooks/stripe, itswhsec_…inSTRIPE_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.
Running it
Section titled “Running it”# Against a preview deploymentE2E_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 1E2E_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_URLthe suite skips (CI-safe). E2E_STRIPE_SECRET_KEYis optional; it enables the paid-invoice assertion via the Stripe API. A non-sk_test_key is refused, as isE2E_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.tsstep 4.
