DEV Community

Trailguide
Trailguide

Posted on

Running Product Tours as Playwright Tests with @trailguide/playwright

The Problem: Tours and Tests Living in Different Worlds

You've built a great product tour. Your users love it. But here's the thing: nobody's testing it.

Your Playwright test suite doesn't know about the tour. The tour doesn't know if it still works after you refactored that button. By the time you notice the tour is broken, users have already suffered through a confusing experience.

Meanwhile, you're maintaining tour logic in one place and end-to-end tests in another. The steps diverge. The tour guides users through a flow that your tests stopped validating months ago.

It doesn't have to be this way.

Enter @trailguide/playwright

@trailguide/playwright lets you run your product tours as actual end-to-end tests. Same Playwright you know. Same assertions. Same CI integration. But now your tour is also your test.

The concept is simple: you define a trail (that's what Trailguide calls a tour flow) in JSON. You pass it to runTrail along with a Playwright page object. It clicks, types, hovers, and waits through every step exactly as a user would. If anything breaks, your test fails.

This means your tours stay accurate. Your tests stay in sync with reality. Everyone wins.

How It Actually Works

Here's the basic pattern:

import { runTrail } from '@trailguide/playwright';

test('user can complete onboarding flow', async ({ page }) => {
  await page.goto('https://app.example.com');

  const trail = {
    steps: [
      { action: 'click', selector: '.start-button' },
      { action: 'fill', selector: 'input[name="email"]', value: 'user@example.com' },
      { action: 'click', selector: 'button[type="submit"]' },
      { action: 'visible', selector: '.welcome-screen' }
    ]
  };

  await runTrail(page, trail);
});
Enter fullscreen mode Exit fullscreen mode

That's it. runTrail executes each step in order. If any assertion fails or a selector isn't found, the test fails.

What Actions and Assertions Do You Get?

The library supports the actions your users actually perform:

  • click - tap a button, link, or interactive element
  • fill - type into an input field
  • hover - move over something
  • select - pick from a dropdown
  • check - toggle a checkbox
  • drag - drag and drop (yes, really)

And the assertions you need to verify things worked:

  • visible - element is on screen
  • text - element contains specific text
  • value - input has a certain value
  • url - page is at the right route

You can also handle waits for network idle or specific selectors to appear. Because real users don't move instantly. They wait for that API call. They wait for the modal to fade in.

Test-Only Trails: No UI Required

Here's a powerful feature: trails can be test-only. You don't have to show UI to your users. Define a trail that validates your critical path without ever displaying a tour overlay.

Perfect for:

  • Testing flows that are too internal for a tour
  • Running smoke tests in CI without side effects
  • Validating complex multi-step interactions that users rarely need guidance on

Why This Matters

Product tours are fragile. They break silently. A developer renames a class. A designer moves a button. The tour still displays, but it's pointing at nothing.

With your tours as tests, you catch this immediately. In CI. Before users see it. Your tour is now part of your deployment process, not an afterthought.

You maintain one source of truth. The trail defines both the user experience and the test. They can't diverge. They won't fall out of sync.

Get Started

Trailguide offers the free MIT-licensed runtime to run your trails, plus Pro features like onboarding analytics, team collaboration, and hosted tour management for $49/month. Try it free at gettrailguide.com.

Top comments (0)