Skip to main content

How to Test SaaS Onboarding Flows

Short answer

Onboarding is a multi-step activation funnel—invite, profile, billing, integrations, empty states. Reliable tests use fixture-backed users seeded at each step, markScreenState checkpoints for ExploreChimp, and probes on activation flags—not single giant UI scripts or click-every-button tours.

Part of Testing Guides by industry.

Who this is for

B2B and B2C SaaS startups optimizing activation, trials, and time-to-value—with frequent onboarding experiments, A/B step order, and integration gates. PLG signup, sales-assist invite, and team invite flows all fit.

Why testing onboarding matters

Activation bugs kill growth silently:

  • Revenue loss — trial users stuck before billing; paid features locked despite onboarding_complete UI badge.
  • Churn — integration skip breaks downstream automation; empty dashboard on first visit.
  • Experiment risk — A/B reorder breaks tests assuming fixed step sequence; winner variant untested in CI.
  • Analytics drift — product shows drop-off at step 3; E2E never covers skip path or empty state.

The dashboard can render while onboarding_complete and integration flags disagree on the server. Probe user state—not only visible step indicators.

Complexity map

ScenarioEdge caseWhy tests breakApproach
Trial signupEmail verification gateCannot click inboxSeed verified user (email guide)
Invite acceptToken expired404 pageSeed fresh invite token per run
Profile stepRequired fields vary by planValidation flakeProbe partial profile
Skip integrationOptional vs requiredWrong activationProbe flags after skip
A/B step orderVariant B firstHard-coded step indexSeed at step + screen state
Team inviteSeat limitInvite fails silentlyProbe seat count
Billing attachTrial without cardFeature gate wrongProbe subscription status
Empty dashboardNo data first visitBroken CTAExploreChimp + empty-state spec
OAuth connectPopup in CIHangSplit post-connect probe (OAuth guide)
Feature flag variantOnboarding v2Wrong funnelPosture fixture
Resume mid-flowSession timeoutDuplicate orgProbe single tenant
Downgrade pathSkip paid stepWrong entitlementsProbe plan flags
Mobile vs desktopDifferent step UIUntested slicetrueCoverage device slice
SSO domainHosted domain onlyWrong auth pathSeed SSO test user
Activation metricactivated_at nullFalse green UIProbe timestamp

Screen states and ExploreChimp

Screen states anchor exploration and analytics to funnel steps—not bare URLs that change with A/B tests:

import { markScreenState } from '@testchimp/playwright'; // or your harness helper

await page.goto('/onboarding/profile');
await page.getByLabel('Company name').fill('Acme Test');
await page.getByRole('button', { name: 'Continue' }).click();

await markScreenState(page, 'onboarding:integrations');

await page.getByRole('button', { name: 'Skip for now' }).click();
await markScreenState(page, 'onboarding:dashboard');

const user = await request.get(`/api/test/probe-user?runId=${runId}`).then(r => r.json());
expect(user.onboardingComplete).toBe(true);
expect(user.integrationOptional).toBe(true);

ExploreChimp runs UX checks on SmartTests annotated with screen states—surfacing drop-offs, broken empty states, and confusing copy after funnel changes without re-recording opaque sessions (explorations).

Manual QA on staging → convert sanitized path to SmartTest with shared Arrange seed at onboarding:integrations (record-replay vs TestChimp).

Activation funnel: seed at step

Do not walk invite → profile → billing → integration in every spec:

StepArrange seedAssert probe
Post-signuponboarding_step=profileprofile_complete
Pre-integrationonboarding_step=integrationsintegration_pending
Post-skipintegration_skipped=trueonboarding_complete
Trial activetrial_end futureplan=trial
// POST /api/test/seed-onboarding-user
// Body: { runId, step: 'integrations', plan: 'trial', integrationOptional: true }

const { userId } = await request.post('/api/test/seed-onboarding-user', {
data: { runId, step: 'integrations', plan: 'trial', integrationOptional: true },
}).then(r => r.json());

await page.goto('/onboarding/integrations');

One end-to-end smoke with synthetic data optional; focused specs per branch.

Branch scenarios

Document in markdown:

  1. Happy path — complete all steps; probe activated_at set
  2. Skip optional integration — probe onboarding_complete without integration_connected
  3. Invite accept — probe org membership + role
  4. Billing required — cannot reach dashboard without payment method when policy requires
  5. Empty dashboard first visit — probe zero projects + CTA visible; ExploreChimp for UX

Link SmartTests with // @Scenario: ONBOARD-SKIP-INT-01 (requirement traceability).

Requirement slices to cover

  • onboarding_step — signup, profile, billing, integrations, dashboard
  • onboarding_outcome — completed, skipped_integration, abandoned, invited
  • plan_type — trial, free, paid, enterprise
  • auth_method — password, google, sso

Compare onboarding_step_completed sequences prod vs test—when prod shows 35% skip integration but tests always connect Slack, evolve skip specs.

CI checklist

  1. Unique email per worker in signup specs
  2. Seed users at step boundaries for focused tests
  3. markScreenState at each funnel checkpoint
  4. Probe activation flags—not only URL or step indicator
  5. ExploreChimp run after major onboarding PR (preview URL)
  6. Feature-flag posture matches preview branch
  7. SSO/OAuth split: post-connect probe spec per OAuth guide

Anti-patterns

Anti-patternWhy it failsBetter approach
Click every button onceMisses branch gatesScenarios per funnel branch
No activation assertSignups without setupProbe user state + TrueCoverage
Shared signup emailData collisions in CISeed unique emails per run
Ignore empty statesUX breaks first visitExploreChimp on onboarding paths
Monolithic 15-min scriptBreaks on copy reorderStep seeds + screen states
URL-only navigationA/B changes routesmarkScreenState anchors
Skip billing gate negativesPaid leakageProbe entitlements

Example scenario

Situation: Trial user skips integration step but must still reach dashboard.

Expected outcome: User lands on dashboard with `onboarding_complete=true` and integration optional.

Why UI-only automation breaks: Test assumes fixed step order; A/B reorder breaks suite though product is fine.

  1. Arrange: Seed trial user at pre-integration state via fixture.
  2. Act: Click skip integration and finish onboarding in UI.
  3. Assert: Probe reads activation flags; `markScreenState` at dashboard for downstream ExploreChimp.

TestChimp workflow: Compare `onboarding_step_completed` sequences in prod vs test runs.

Same Arrange/Act/Assert pattern as expired-coupon checkout.

Connect scenarios to your QA workflow

Capture business rules in markdown test plans and enforce them with seed routes and probe Assert. Link SmartTests with // @Scenario: for requirement traceability. Use /testchimp test on PRs; /testchimp explore on SmartTest paths for non-functional gaps (ExploreChimp).

External references

Frequently asked questions

How do screen states help SaaS onboarding tests?

markScreenState anchors ExploreChimp and Atlas to funnel steps—not bare URLs—so activation regressions map to scenario coverage when /testchimp test updates SmartTests.

Should every spec walk the full onboarding funnel?

No—seed users at profile, integrations, or billing steps for focused specs. One synthetic end-to-end smoke optional; branch scenarios for skip and invite paths.

How do I test A/B onboarding order changes?

Avoid hard-coded step indices; seed user at logical step via probe field, use screen states for navigation asserts, probe activation flags for outcome.

When should I run ExploreChimp on onboarding?

After funnel UI PRs on preview URLs—especially empty dashboard and skip paths. Annotated SmartTests link UX findings back to markdown scenarios.

How do activation probes differ from UI step indicators?

Probes read onboarding_complete, integration_connected, plan, activated_at on user/org record—UI checkmarks can desync from server flags.

Invite and SSO flows in CI?

Seed fresh invite tokens per run; for OAuth use post-connect tier with probe on org membership—full popup in nightly job per OAuth guide.

How does TrueCoverage guide onboarding tests?

Compare onboarding_step and outcome sequences prod vs test. Evolve when skip integration or invite accept paths dominate prod but tests only cover happy connect.

Apply these patterns in your repo

Run `/testchimp init` to connect TestChimp to your repo, then `/testchimp test` on PRs to turn these patterns into maintained SmartTests. Use `/testchimp evolve` when you want to expand coverage as your app grows.

Start free on TestChimp · Book a demo