Rebasely Beta: data may be purged

examples/storefront Public

Markdown · 2.0 KiB · at 80dbc76

id: testing
type: guide
owner: justin
describes:
  - test/helpers/**
reviewed: 2026-10-15

Running and writing tests

npm test          # node --test over test/**/*.test.ts
npm run typecheck

The tests need only Node 24. They do not start workerd or wrangler.

How it works

test/helpers/app.ts builds the real fetch handler from createApp with a fresh environment per test:

  • DB is TestD1 (test/helpers/d1.ts), a small D1 stand-in over node:sqlite with every file in migrations/ applied in order and foreign keys on. It covers prepare, bind, first, all, run and batch, and a batch is a transaction, as in D1.
  • IMAGES is TestR2 (test/helpers/r2.ts), an in-memory bucket whose objects map tests can inspect, and IMAGES_URL is https://images.shop.test.
  • ORDER_EVENTS is TestQueue (test/helpers/queue.ts), which keeps every message in sent.
  • PAYMENTS is FakePayments (test/helpers/payments.ts), standing in for the payments Worker, which records every charge, fails the next one when failNext is set, and refuses to cancel the intents in uncancellable. test/stripe-payments.test.ts checks the payments Worker's Stripe adapter against a fake fetch, and test/payments-webhook.test.ts runs its webhook against the test database, so no test calls Stripe.
  • The clock is fixed and ids count up (id-1, id-2), so assertions can name them.

Tests talk HTTP to the handler through call(method, path, body, headers), which returns the status, headers and parsed JSON. addProduct creates a product with the admin token, payments is the fake the app was given and events is its queue.

Writing one

Test behavior through the API rather than the modules, the way a client sees it. When code calls a D1 method the stand-in does not have yet, add it to TestD1 in the same change. A new migration needs nothing: the stand-in applies whatever is in migrations/. See [[0001-d1-for-shop-data]] for why the SQL is shared.