Testing Subscription System - Complete Guide

Date: 2025-01-04 Environment: Stripe Test Mode (Sandbox)

Prerequisites

Before testing, ensure:

  • ✅ Dev server running: pnpm dev
  • ✅ ngrok tunnel active
  • ✅ Webhook configured in Stripe sandbox
  • ✅ All environment variables set in .env.local
  • ✅ You're signed in to the application

Test Suite

Test 1: Checkout Flow - Personal Tier Monthly

Objective: Verify complete checkout and subscription creation

Steps:

  1. Go to http://localhost:3017/pricing
  2. Ensure "Monthly" is selected
  3. Click "Start Free Trial" on Personal tier ($4/month)
  4. Should redirect to Stripe Checkout
  5. Fill in test card details:
    • Card: 4242 4242 4242 4242
    • Expiry: 12/25
    • CVC: 123
    • ZIP: 12345
    • Email: Your test email
  6. Click "Subscribe"
  7. Should redirect to /checkout/success

Expected Results:

  • ✅ Success page displays
  • ✅ Shows "10-day free trial has started"
  • ✅ Console logs: ✅ Received webhook: customer.subscription.created
  • ✅ Console logs: Subscription created: sub_... for user user_...

Verification:

# Check Stripe Dashboard
# Go to: Customers → Find your customer → See subscription with trial

# Check Convex Database
# Go to: Convex Dashboard → Data → subscriptions table
# Verify record exists with:
# - userId: your user ID
# - tier: "personal"
# - status: "trialing"
# - trialEndsAt: ~10 days from now

Test 2: Subscription Status Display

Objective: Verify settings page shows correct subscription info

Steps:

  1. Go to http://localhost:3017/settings
  2. View Subscription Status Card

Expected Results:

  • ✅ Card displays "Personal" tier
  • ✅ Status badge shows "Trial Active" (blue)
  • ✅ Shows "X days remaining" in trial
  • ✅ Shows plan limits:
    • Pages: 3
    • Tabs per Page: 5
    • Cloud Sync: Enabled
    • Premium Widgets: Disabled
  • ✅ "Manage Subscription" button visible

Test 3: Customer Portal Access

Objective: Verify portal opens and shows correct information

Steps:

  1. From /settings, click "Manage Subscription"
  2. Should redirect to Stripe Customer Portal
  3. Verify portal shows:
    • Current plan: Personal
    • Status: Trialing
    • Trial end date
    • Payment method on file
  4. Click "Return to [your app]"
  5. Should redirect back to /settings?portal=true

Expected Results:

  • ✅ Portal opens successfully
  • ✅ Shows correct subscription info
  • ✅ Return link works
  • ✅ Returns to settings page

Test 4: Backend Limit Enforcement - Pages

Objective: Verify page creation limits are enforced

Steps:

  1. Go to your app dashboard
  2. Create 1st page → Should succeed
  3. Create 2nd page → Should succeed
  4. Create 3rd page → Should succeed
  5. Try to create 4th page → Should FAIL

Expected Results:

  • ✅ First 3 pages created successfully
  • ✅ 4th page creation blocked
  • ✅ Error message shown:
    You've reached the 3 page limit for the personal tier.
    Upgrade to pro for unlimited pages.

Console Verification:

Error: {"code":"LIMIT_REACHED","message":"You've reached the 3 page limit...","upgradeRequired":true,"currentTier":"personal","suggestedTier":"pro","currentUsage":3,"limit":3}

Test 5: Backend Limit Enforcement - Tabs

Objective: Verify tabs per page limits are enforced

Steps:

  1. Open any page in your dashboard
  2. Create 1st tab → Should succeed
  3. Create 2nd tab → Should succeed
  4. Create 3rd tab → Should succeed
  5. Create 4th tab → Should succeed
  6. Create 5th tab → Should succeed
  7. Try to create 6th tab → Should FAIL

Expected Results:

  • ✅ First 5 tabs created successfully
  • ✅ 6th tab creation blocked
  • ✅ Error message shown:
    You've reached the 5 tabs per page limit for the personal tier.
    Upgrade to pro for unlimited tabs.

Test 6: Plan Upgrade via Portal

Objective: Verify plan upgrade works and syncs to Convex

Steps:

  1. From /settings, click "Manage Subscription"
  2. In Stripe Portal, click "Update plan"
  3. Select Pro plan
  4. Confirm upgrade
  5. Return to app

Expected Results:

  • ✅ Upgrade completes in portal
  • ✅ Webhook received: customer.subscription.updated
  • ✅ Convex database updated with tier: "pro"
  • ✅ Settings page shows "Pro" tier
  • ✅ Plan limits updated:
    • Pages: Unlimited
    • Tabs per Page: Unlimited
    • Premium Widgets: Enabled
  • ✅ Can now create more than 3 pages
  • ✅ Can now create more than 5 tabs per page

Console Verification:

✅ Received webhook: customer.subscription.updated
Subscription updated: sub_...

Test 7: Payment Method Update

Objective: Verify payment method can be updated

Steps:

  1. From /settings, click "Manage Subscription"
  2. In portal, click "Update payment method"
  3. Add new test card: 5555 5555 5555 4444 (Mastercard)
  4. Set as default
  5. Return to app

Expected Results:

  • ✅ New card added successfully
  • ✅ Set as default payment method
  • ✅ Old card still visible (can delete if desired)

Test 8: Subscription Cancellation

Objective: Verify cancellation works and syncs correctly

Steps:

  1. From /settings, click "Manage Subscription"
  2. In portal, click "Cancel subscription"
  3. Select "Cancel at end of billing period"
  4. Confirm cancellation
  5. Return to app

Expected Results:

  • ✅ Cancellation confirmed in portal
  • ✅ Webhook received: customer.subscription.updated
  • ✅ Subscription status shows "Active" (still in period)
  • ✅ Portal shows "Cancels on [date]"
  • ✅ Can still use features until period ends

Console Verification:

✅ Received webhook: customer.subscription.updated
Subscription updated: sub_...

Database Verification:

Check Convex subscriptions table:
- cancelAtPeriodEnd: true
- status: "active" (still active until period ends)

Test 9: Subscription Reactivation

Objective: Verify canceled subscription can be reactivated

Steps:

  1. From /settings, click "Manage Subscription"
  2. In portal, should see "Renew subscription" button
  3. Click "Renew subscription"
  4. Confirm renewal
  5. Return to app

Expected Results:

  • ✅ Renewal confirmed in portal
  • ✅ Webhook received: customer.subscription.updated
  • ✅ Status shows "Active" without cancellation notice
  • ✅ Portal no longer shows cancel date

Console Verification:

✅ Received webhook: customer.subscription.updated
Subscription updated: sub_...

Database Verification:

Check Convex subscriptions table:
- cancelAtPeriodEnd: false
- status: "active"

Test 10: Yearly Subscription

Objective: Verify yearly billing works correctly

Steps:

  1. Go to /pricing
  2. Toggle to "Yearly"
  3. Click "Start Free Trial" on Pro tier ($90/year)
  4. Complete checkout with test card
  5. Verify subscription created

Expected Results:

  • ✅ Checkout shows $90/year pricing
  • ✅ Subscription created with yearly interval
  • ✅ Shows "$7.50/month billed annually" in portal
  • ✅ Next billing date is 1 year from now (after trial)

Test 11: Free Tier User Experience

Objective: Verify free tier users see upgrade prompts

Steps:

  1. Create a new test user (or cancel subscription to downgrade)
  2. Go to /settings as free tier user
  3. View subscription status

Expected Results:

  • ✅ Shows "Free" tier
  • ✅ Plan limits:
    • Pages: 1
    • Tabs per Page: 3
    • Cloud Sync: Disabled
    • Premium Widgets: Disabled
  • ✅ Shows "View Plans" button instead of "Manage Subscription"
  • ✅ Button links to /pricing

Test 12: Failed Payment Simulation

Objective: Verify payment failure handling

Steps:

  1. In Stripe Dashboard, find your subscription
  2. Click "Actions" → "Simulate payment failure"
  3. Or create new subscription with decline card: 4000 0000 0000 0002
  4. Check webhook and status

Expected Results:

  • ✅ Webhook received: invoice.payment_failed
  • ✅ Status changes to "past_due"
  • ✅ Settings page shows "Payment Due" badge (yellow)
  • ✅ Warning message displayed:
    Your last payment failed. Please update your payment
    method to maintain access.

Console Verification:

✅ Received webhook: invoice.payment_failed
Payment failed for subscription: sub_...

Webhook Monitoring

Real-time Console Logs

Watch your Next.js console for these webhook events:

# Subscription created
 Received webhook: customer.subscription.created
Subscription created: sub_1234567890 for user user_abc123

# Subscription updated (upgrades, downgrades, renewals)
 Received webhook: customer.subscription.updated
Subscription updated: sub_1234567890

# Payment succeeded
 Received webhook: invoice.payment_succeeded
Payment succeeded for subscription: sub_1234567890

# Payment failed
 Received webhook: invoice.payment_failed
Payment failed for subscription: sub_1234567890

# Subscription deleted/canceled
 Received webhook: customer.subscription.deleted
Subscription deleted: sub_1234567890

ngrok Dashboard

Monitor requests at: http://127.0.0.1:4040

Should see:

  • ✅ POST requests to /api/stripe/webhook
  • ✅ Status: 200 OK
  • ✅ Response: {"received":true}

Stripe Dashboard

Check webhook delivery:

  1. Go to: DevelopersWebhooks → Your endpoint
  2. Click "Recent deliveries" tab
  3. Verify all events show ✅ Success

Quick Verification Checklist

After running tests, verify:

Stripe Dashboard

  • Customer created with correct email
  • Subscription shows correct tier
  • Trial end date is ~10 days from now
  • Payment method on file
  • Webhooks all show success (200 OK)

Convex Database

  • subscriptions table has record
  • userId matches your user
  • tier is correct ("personal", "pro", or "team")
  • status is correct ("trialing" or "active")
  • stripeSubscriptionId starts with "sub_"
  • stripeCustomerId starts with "cus_"
  • trialEndsAt is ~10 days from now

Application UI

  • Settings page loads without errors
  • Subscription status card shows correct info
  • Trial countdown displays correctly
  • Manage subscription button works
  • Customer portal opens and returns correctly
  • Pricing page checkouts work

Backend Enforcement

  • Page creation limits enforced
  • Tab creation limits enforced
  • Error messages include upgrade suggestions
  • Limits update after plan upgrade

Test Cards Reference

Success Cards

  • 4242 4242 4242 4242 - Visa
  • 5555 5555 5555 4444 - Mastercard
  • 3782 822463 10005 - Amex

Failure Cards

  • 4000 0000 0000 0002 - Card declined
  • 4000 0000 0000 9995 - Insufficient funds
  • 4000 0000 0000 0069 - Expired card

For all cards: Any future expiry, any CVC, any ZIP


Troubleshooting

Issue: Webhook not received

Check:

  1. ngrok tunnel still active? Run ngrok http 3017
  2. Webhook URL correct in Stripe? Should match ngrok URL
  3. Dev server running? Run pnpm dev
  4. Check ngrok dashboard: http://127.0.0.1:4040

Issue: "No subscription found" in portal

Cause: Subscription not created or webhook failed

Fix:

  1. Check console logs for webhook errors
  2. Verify subscription exists in Stripe Dashboard
  3. Manually trigger webhook test from Stripe
  4. Check Convex database for subscription record

Issue: Limits not enforced

Cause: User tier not detected correctly

Fix:

  1. Check subscription record in Convex
  2. Verify tier field is set correctly
  3. Check mutations are importing tier limits helper
  4. Test with TypeScript compilation: npx tsc --noEmit

Issue: Settings page doesn't load

Cause: Missing Badge component import

Fix: Badge component should be available in @workspace/ui/primitives/badge


Success Criteria

All tests passWebhooks deliver successfullyDatabase records correctUI displays accurate infoLimits enforced properlyPortal works end-to-endNo console errors


When all tests pass, the subscription system is fully functional and ready for production! 🎉

Next step: Switch to live Stripe keys when ready to accept real payments.

On this page