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

# Testing Your Integration

> Test Fanfare integrations against public journey states and handoff behavior.

Test your Fanfare integration from the public contract. Your tests should prove that the right UI appears for each public state, that valid actions are wired correctly, and that granted handoff stays inside your trusted flow.

For the deeper SDK reference, see [SDK Testing](/sdk/reference/testing).

## What To Cover

| Scenario      | What to verify                                                           |
| ------------- | ------------------------------------------------------------------------ |
| Ready         | Start CTA appears and calls the current view's start action.             |
| Routing       | Loading UI appears without invalid buttons.                              |
| Gated         | Auth, access-code, or verification UI uses generic customer-safe copy.   |
| Scheduled     | Scheduled or waitlist messaging renders.                                 |
| Enterable     | The enter, bid, or booking action is available when exposed by the view. |
| Participating | Status, progress, and valid participation actions render.                |
| Granted       | Checkout handoff receives the grant.                                     |
| Ended         | Recovery or support copy is clear and does not infer private reasons.    |
| Error         | Retry or fallback UI is visible.                                         |

## Component Tests

For custom React UI, split SDK wiring from rendering. The wrapper calls `useExperienceJourney`; the view component accepts controlled props.

```tsx theme={null}
import { useExperienceJourney } from "@fanfare-io/fanfare-sdk-react";

export function LaunchExperience({ experienceId }: { experienceId: string }) {
  const journey = useExperienceJourney(experienceId);

  return <LaunchExperienceView {...journey} />;
}
```

In unit tests, render `LaunchExperienceView` with representative public views. Avoid depending on private SDK internals, undocumented mock helpers, or assumed state-transition timing.

## Widget Tests

When using `ExperienceWidget`, keep tests focused on app-owned behavior:

* The widget is rendered with the expected `experienceId`.
* `checkoutUrl` or `onGranted` is configured for granted users.
* Slot overrides render your custom UI.
* Sensitive values are not sent to logs or analytics.

Example granted-state handoff boundary:

```tsx theme={null}
<ExperienceWidget
  experienceId="exp_123"
  onGranted={(admissionGrant) => {
    void sendAdmissionToServer({ admissionGrant });
  }}
/>
```

Test `sendAdmissionToServer` as your application code. Use SDK-level integration tests sparingly for full journey behavior.

## End-To-End Tests

Use a test experience and test publishable key for browser tests. Keep assertions based on visible public states and your app's handoff behavior.

```ts theme={null}
import { expect, test } from "@playwright/test";

test("customer can reach the launch experience", async ({ page }) => {
  await page.goto("/launch");

  await expect(page.getByRole("main")).toBeVisible();
  await expect(page.getByText(/launch|access|checkout/i)).toBeVisible();
});
```

For admitted-state tests, prefer a controlled test experience or a test fixture in your application boundary. Do not put real admission grants in URLs, screenshots, or test logs.

## Manual QA Checklist

* Start from a clean browser profile.
* Repeat with an existing browser session.
* Open the same experience in two tabs.
* Verify ready, routing, gated, routed, admitted, denied, unavailable, and error copy where your experience can reach those states.
* Confirm checkout receives only the values it needs.
* Confirm analytics record high-level outcomes, not raw grants or snapshots.
* Confirm production builds do not enable debug logging.

## Local Development

Use your application's normal local server with Fanfare test credentials. If you need deterministic states, place a small boundary around your UI and supply controlled public `JourneyView` values in tests.

Avoid inventing SDK mock helper names unless they are documented in the SDK reference or provided by your installed SDK version.

## CI

Add the checks that already protect your application:

```yaml theme={null}
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - run: npm ci
      - run: npm test
```

Store only test publishable credentials in frontend test environments. Keep secret keys in server-side CI contexts.

## Next Steps

* [Deployment](/getting-started/deployment) - Prepare production rollout.
* [SDK Testing](/sdk/reference/testing) - Review the SDK testing contract.
* [Journey State](/sdk/core/journey-state) - Cover the public states your UI renders.
