> ## Documentation Index
> Fetch the complete documentation index at: https://docs.craveup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing

> Test storefront capability, concurrency, checkout, and secret-handling behavior.

Use sandbox API and Stripe publishable values for local and CI runs:

```env theme={null}
NEXT_PUBLIC_CRAVEUP_API_URL=https://dev-api-43233223.craveup.com
NEXT_PUBLIC_CRAVEUP_LOCATION_ID=loc_test
NEXT_PUBLIC_CRAVEUP_MERCHANT_SLUG=test-cafe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxx
```

## Unit tests

Test the caller-owned session adapter independently:

* versioned `sessionStorage` keys include the canonical API environment, merchant, and location;
* the cart capability and customer JWT never enter URLs, analytics, or `localStorage`;
* ETag revisions are retained;
* claim, delete, expiry, and terminal checkout handling clear persisted capability state;
* malformed or old-version records fail closed.

Mock `fetch` when testing the SDK:

```ts theme={null}
const fetchMock = vi.fn(
  async () =>
    new Response(JSON.stringify(cart), {
      status: 200,
      headers: { "Content-Type": "application/json", ETag: '"cart-4"' },
    }),
);

const storefront = createStorefrontClient({
  baseUrl: "https://api.example.test",
  fetch: fetchMock,
  sessionStore,
});
```

Assert cart calls send the capability, current `If-Match`, and an idempotency key. For `CART_CONFLICT`, assert the mutation is not replayed automatically and the current cart revision is refreshed.

## Checkout tests

Cover every authoritative result:

* `payment_pending` continues bounded polling;
* `order_pending` continues bounded polling;
* `completed` renders the returned order and clears persisted cart state after terminal handling;
* `failed` renders failure, never falls back to success, and clears persisted cart state after terminal handling;
* authorization, timeout, and stale-revision errors remain visible.

## Receipt tests

Start with a URL containing `#receiptToken=...`. Assert the app calls `history.replaceState` immediately, stores the token only for that API environment, merchant, and receipt ID in `sessionStorage`, and sends it in the receipt header—not in the request URL.

## End-to-end sandbox flow

1. Fetch published merchant, location, menu, product, distance, order-time, and gratuity data anonymously and verify no customer JWT is attached.
2. Create a cart and verify the capability is returned only once for a new cart.
3. Mutate the cart and verify revision changes.
4. Create a PaymentIntent and confirm with a sandbox payment method.
5. Observe nonterminal polling followed by exactly one terminal result.
6. Verify rating and receipt access.
7. Confirm no secret or capability appears in browser URLs, logs, analytics, or static assets.

Run the same build artifact you intend to promote.
