Testing
The suite below is the acceptance bar for the features in this design. The marketing site and the documentation site do not implement these cases yet. Add them with the API, and keep them in CI before a production release.
Layers
| Layer | What it proves |
|---|---|
| Unit | Price snapshots, the reward formula, status transitions, and the gallery predicate. No network. |
| Integration | Prisma against PostgreSQL, including unique keys, checks, and the append-only triggers. |
| Stripe contract | Signed Stripe fixtures. Invalid signatures are rejected. |
| End to end | Browser booking through pending approval, and a download that is refused until access is approved. |
Cases that must exist
Map each row to the acceptance criteria.
| Area | Case |
|---|---|
| Pricing | Client-supplied price is ignored. Catalog cents and USD are stored. |
| Accounts | New payer receives one setup token. Repeating the token fails. An existing email reuses the user. |
| Payments | Success redirect leaves the order unpaid. A verified webhook marks it paid and the booking pending approval. |
| Payments | The same event id applied twice does not create a second payment or a second reward. |
| Payments | A rejected paid booking enqueues one refund for the captured USD amount. |
| Galleries | A published gallery with pending access returns no signed URL. |
| Galleries | Approval writes a review row and the following request returns a URL expiring within 5 minutes. |
| Galleries | Another customer receives the same response as a missing gallery. |
| Ratings | Ratings outside 1 through 5 fail. A second rating by the same customer fails. |
| Rewards | 20000 cents at 500 basis points yields 1000 cents. 1010 cents at 500 basis points yields 51 cents. |
| Rewards | Self-referral and a second referrer are rejected. |
| Rewards | A pending reward cannot be redeemed. Two concurrent redemptions cannot spend the same balance. |
| Ledger | UPDATE and DELETE on reward_ledger fail in the database. |
Fixture amounts
Use integer cents. The standard reward fixture is a $200.00 eligible subtotal and a 5 percent policy. Assert 1000, not a floating-point dollar amount.
Webhook tests use recorded Stripe payloads and the test signing secret. They do not call the live Stripe API in CI. A separate sandbox smoke test can create a real test charge before release. Integration tests use the generated Prisma Client and a throwaway DATABASE_URL.
Data
Integration tests run in a transaction that rolls back, or on a database created for the run and dropped after. They do not point at production. Seed prices in tests are fixtures, including the $200.00 example.