Skip to main content
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.

What To Cover

ScenarioWhat to verify
ReadyStart CTA appears and calls the current view’s start action.
RoutingLoading UI appears without invalid buttons.
GatedAuth, access-code, or verification UI uses generic customer-safe copy.
ScheduledScheduled or waitlist messaging renders.
EnterableThe enter, bid, or booking action is available when exposed by the view.
ParticipatingStatus, progress, and valid participation actions render.
GrantedCheckout handoff receives the grant.
EndedRecovery or support copy is clear and does not infer private reasons.
ErrorRetry 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.
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:
<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.
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:
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