Use test mode to check the whole payment handoff.

Stripe’s test environment lets you exercise payment flows without moving real money. Start with a test secret key and Stripe’s documented test payment methods; never paste a live secret key into a test job. A test card proves only the payment method path you selected. Your application still has to create the right customer or checkout session, handle the payment status, process the webhook, and grant access once.

Before writing the browser step, write down the state that should exist before and after it. For example: a new account has no Pro entitlement; checkout creates one payment; the callback marks the order paid; the account can open the Pro feature. That list makes it possible to tell a payment failure from an account-update failure.

Stripe’s testing guide covers test values and the test environment. Molar’s Stripe Clone reference covers the supported local paths when you need a resettable service instead.

BROWSER

Payment confirmed

The customer sees the checkout result.

screen state
CALLBACK

Payment succeeded

The app receives and verifies the provider event.

delivery can lag
APPLICATION

Access granted

Account permissions change only after the callback is applied.

assert here
A payment callback changes accessThe browser can show success before the application has processed the provider callback.

Choose Stripe test mode or a supported clone.

Use Stripe test mode when you need compatibility with the provider’s own request and webhook contract. Use a supported Molar Clone when repeated local or CI runs need records you can inspect, controlled starting state, or supported failure cases without depending on a shared provider sandbox. Check the documented endpoints before choosing: a clone that covers PaymentIntents does not automatically cover every Billing, Connect, tax, dispute, or refund workflow.

In either setup, keep the application’s provider base URL and credentials explicit. Fail the test setup if the expected test variable is missing; silently falling back to a live account is a configuration bug, not a useful test result.

Code example
const paymentIntent = await stripe.paymentIntents.create({
  amount: 4900,
  currency: 'usd',
  payment_method_types: ['card'],
  payment_method: 'pm_card_visa',
  confirm: true,
});

expect(paymentIntent.status).toBe('succeeded');

This Node example uses Stripe’s test payment method value. Adapt the client setup and assertion to the SDK version your project uses, and keep the secret in the test environment.

Run one clean checkout from payment to access.

  1. Seed a disposable account. Create a customer with no paid entitlement and record its identifier for the test.
  2. Open checkout. Use the browser to select the plan and submit the test payment. Assert the amount, currency, and confirmation visible to the user.
  3. Capture the payment ID. Keep the PaymentIntent, Checkout Session, or order identifier your application uses to connect the browser action to the callback.
  4. Process the callback. Deliver the supported event through your test setup and verify signature validation. Do not bypass the webhook handler just to make the browser test green.
  5. Check the account. Assert that the intended feature is available once and that a second callback does not create a second entitlement.
  6. Reset and repeat. Restore the clone snapshot or recreate the provider test data, then run again from the same starting state.

The browser confirmation and the payment record answer different questions. Keep both assertions so a page that says “paid” cannot hide a missing callback or an order that was never persisted.

Exercise the failures that change customer treatment.

Use documented Stripe test values or clone controls for a declined payment, a payment that needs additional action, and a delayed or repeated callback where your setup supports them. The expected product behavior should be explicit: a decline leaves the account unpaid and offers a retry; additional action leaves checkout pending until the customer completes it; a repeated event is ignored after the first successful update.

Subscriptions add time to the problem. Stripe Billing testing describes test clocks for advancing subscription state and observing resulting events. A clock-backed test still needs to check your webhook consumer, invoice handling, and account entitlement. It does not prove that every production billing path is covered.

Code example
const event = stripe.webhooks.constructEvent(
  rawBody,
  signatureHeader,
  process.env.STRIPE_WEBHOOK_SECRET,
);

await handleStripeEvent(event);

Use the raw request body for signature verification in the framework configuration that receives your webhook. A parsed-and-re-serialized body can invalidate the signature before your handler runs.

Keep the failed run useful.

When checkout fails, retain the browser step, payment identifier, callback status, and final account assertion together. A missing screenshot means capture is incomplete, not that checkout failed. A successful PaymentIntent with no entitlement calls for checking callback delivery and application state. A declined test payment calls for checking the expected failure handling. This separation saves a team from rerunning the same flow without changing the diagnosis.

Start Molar with one defined checkout and the integrations its current workflow supports. Explore Clones for resettable service state, review Guard for configured release checks, or talk to us. Exporting runs as Playwright tests and blocking merges on them are in beta, so review the generated tests before you rely on them.