Test the services behind your app.

Point your test environment at a documented clone, run the payment, message, sign-in, or upload task, and inspect the record your app creates. Control supported failures and timing, then restore the starting state for the next run.

Start with the documented API coverage for the services your app calls.

See what happens after a payment.

Follow one checkout through its payment record, webhook delivery, and resulting account access. This interactive example is local to this page; it is not connected to your app or a live vendor.

clones / run_checkout / stripe
healthy
PAYMENT INTENTpi_3f29a1
SucceededAmount captured · $24.00 USD
customer
cus_8q2maya
payment_method
pm_card_4242
created_at
14:30:03 UTC
tenant
run_checkout
DELIVERY TRACE
  1. 01charge.succeededobserved
  2. 02payment_intent.succeededsigned
  3. 03order.confirmedreceived
virtual clock · 2026-08-14 14:30 UTCSnapshot ready to save before a risky path.

Interactive example · sample Stripe state only · buttons change the local illustration. In this sample, advancing 24h delivers a queued callback retry.

Choose exactly what goes wrong.

A successful API response only tests one path. Make the service slow, return an error, or retry a webhook—and check how your app responds.

Two requests work.
The third fails.

Choose a method, path, error body, and when the failure starts. Test whether your app retries, explains the problem, and avoids creating a duplicate record.

You can also inject latency and request-rate limits. Check the resulting app state, not just the response code.

Request 1200 OKRequest 2200 OKRequest 3503 Error
Stripe clone · failure rule
// On an already-started Stripe clone:
await clone.injectError({
  method: 'GET', path: '/v1/customers',
  after: 2, rate: 1, status: 503,
  body: { error: { type: 'api_error',
    message: 'Service unavailable' } }
});
// The first two matching requests succeed.
// Later matching requests return this 503.

Five minutes later.
Without a five-minute wait.

Advance the service clock to run scheduled behavior. Test supported billing events and delayed delivery while your test is still running.

This moves the clone’s clock. Your app’s clock and real security credentials keep their own time.

Advance time. Inspect the change.

Records and scheduled events use simulated time.

TypeScript SDK · virtual clock
// Move the clone clock forward by five minutes.
await clone.advanceClock('5m');

The payment worked.
Your webhook handler didn’t.

Keep signature verification enabled. Let your test handler return an error, advance the clone clock, and inspect the next delivery attempt. Then check that repeated delivery updates the order only once.

Try the callback example
Example · a handler recovers on the third attempt
  1. Payment succeededEvent created
  2. Delivery 1 · handler returns 500Immediate retry
  3. Delivery 2 · handler returns 500Wait 5s on clone clock
  4. Delivery 3 · handler returns 200Delivered

Supported Stripe, Twilio, Email, and S3 callbacks have clone-controlled signatures. Configure the callback target and signing secret for your test environment.

Put Clones inside your test suite.

Start a service, point your test app at it, and reset its state between scenarios. Keep your existing browser tests and assertions.

Start, change, and restore Stripe

TypeScript SDK · checkout-state.ts
import assert from 'node:assert/strict';
import { stripe } from '@molar/clones';

const clone = await stripe.start({ seed: 'checkout' });
try {
  const initial = await clone.listCustomers();
  const before = await clone.snapshot();
  await clone.seedData({
    customers: [{ email: 'buyer@example.test' }]
  });
  assert.ok((await clone.listCustomers()).some(
    customer => customer.email === 'buyer@example.test'
  ));
  await clone.restore(before);
  assert.deepEqual(await clone.listCustomers(), initial);
} finally {
  await clone.stop();
}

The clones SDK isn’t on npm yet. Email pratik@molar.it and we’ll send the package and the local clone binaries. The SDK starts a local process and configures its test credentials. Local clones keep their records on your machine and send nothing to Molar. This example checks that restoring removes the customer created after the snapshot.

Connect the app you’re testing

Test runnerYour appClones
  1. Set the service endpoint

    Configure your app’s HTTP client or vendor SDK to call the clone. clone.apiPath('/v1/customers') gives the full, run-specific customer URL, including /t/{runId}.

  2. Use the test credentials and certificate

    Keep vendor test credentials separate from the run token used for clone controls. For a local SDK-started process, trust the certificate in clone.tlsCAPEM when connecting through your own HTTP client.

  3. Keep each test’s state separate

    Give concurrent scenarios separate runs. Restore the service snapshot before repeating a scenario, reset your app’s own database separately, and stop local clones in finally.

Your client must support a custom endpoint. The exact configuration differs by SDK; setting an environment variable alone does not redirect its requests.

Restore the payment.
And the receipt.

A checkout changes more than one service. Save the selected clones together, exercise your scenario, and restore their saved records before trying the next branch.

Example · one saved starting point, two service states
before-checkoutSaved service state
StripeCustomer records
Payment state
EmailReceipt messages
Delivery state
Restore both, then run the next scenario
TypeScript SDK · multiple services
import { world } from '@molar/clones';

// payment and inbox are started Stripe and Email clones.
// Use the same runId when starting both services.
const services = world.localRegistry([payment, inbox]);
await world.snapshot(services, payment.runId, 'before-checkout');

// Run your checkout test against both services here.

await world.restore(services, payment.runId, 'before-checkout');

Start both clones with the same runId and register the services you want to include. Local snapshots stay in the SDK process.

Snapshots restore clone state. They do not rewind your application database, browser, or real vendor account.

Find the services
your app depends on.

All 28 service clones, with the supported operations and setup for each.

5 stateful services

Create and inspect records. Use supported clock, callback, snapshot, and reset controls to repeat your test.

23 API clones

Test against predefined responses for named operations. These packs do not reproduce the provider’s full behavior or state transitions.

28 services

Each service covers specific API paths. Review its documentation before adding it to your test.

Need a different service?

Choose the right service for the test.

Use Clones for repeatable application tests against supported service behavior. Keep provider sandboxes for checking your integration against the provider itself.

HTTP mocks

Good for precise responses and scenarios you define. WireMock also supports stateful scenarios; the distinction is who builds and maintains the service behavior.

WireMock stateful scenarios

Vendor sandboxes

Good for provider-specific API and integration checks. Stripe also offers test clocks for Billing subscriptions and lifecycle webhooks.

Stripe test clocks

Molar Clones

Use implemented vendor operations with records, failure controls, and snapshots in your test environment. Check the catalog’s coverage before depending on an API path.

Browse supported operations

Run it where your tests run.

Start local processes from the SDK, or connect to an existing clone service from CI. Docker and Helm packages are available for self-hosted setups.

Ask about your test environment

Keep real accounts out of the run.

The Clones SDK checks known live vendor hosts and credential patterns before sending a request. Keep test credentials in your app too: calls made outside the SDK need their own configuration and network controls.

Use Clones with CLI and MCP

Frequently asked questions

Have a specific workflow in mind?
Talk to us

What does a Clones run isolate?

Each run gets its own copy of the service state, including the records your test creates. Deterministic IDs make repeated local and CI runs easier to compare.

Can I test a webhook without weakening signature checks?

Yes, supported webhook paths emit vendor-shaped callbacks with clone-controlled signing secrets. Your application can verify the signature and your test can inspect delivery attempts.

How do I test expiry or renewal without waiting?

Use the virtual clock controls exposed by the clone setup. Advance simulated time to reach supported expiry, delayed delivery, or renewal behavior, then inspect the resulting records.

What is the difference between reset and restore?

Restore loads a saved snapshot of a run’s records. Reset removes the run state so the clone can return to its initial state. Choose the one your scenario needs.

Does the catalog implement every vendor API?

No. Five stateful services implement documented operations and state transitions. Another 23 API clones provide predefined responses for named API operations. Neither tier implements every vendor API; check the coverage for the paths your app calls.

Can I run this in CI or offline?

Yes, local clones can run in a CI job. An offline job needs its binaries, SDK, and other dependencies available in advance, and any webhook targets reachable within that environment. Docker and Helm packaging are available for self-hosted setup; email pratik@molar.it for the cluster requirements.

Does a snapshot also reset my app?

No. Snapshots restore the selected clone services. Reset your application database, browser storage, and other test fixtures separately before repeating the scenario.

Do I need to rewrite my Playwright tests?

You can keep the browser actions and assertions in your suite. Add a fixture that starts the clones, configure your app’s vendor clients to use their endpoints, and restore or stop the clones during cleanup.

Give your next test the right services.

Check the supported API paths, connect a test endpoint, and run the flow from known state.

Free during the beta. No card.