npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@guidepup/playwright

v0.21.0

Published

Screen reader automation library for Playwright testing.

Readme

Documentation | API Reference

macOS Sonoma Support macOS Sequoia Support macOS Tahoe Support macOS Golden Gate Support Windows Server 2022 Support Windows Server 2025 Support Ubuntu Resolute Support Debian Trixie Support

Guidepup is a screen reader automation library for testing.

This package provides Guidepup integration with Playwright to enable testing with NVDA on Windows, Orca on Linux, and VoiceOver on macOS.

Capabilities

  • Full Control - If a screen reader has a keyboard command, then Guidepup supports it.
  • Mirrors Real User Experience - Assert on what users really do and hear when using screen readers.

Getting started

Set up your machine for screen reader automation:

npx @guidepup/setup setup

Install @guidepup/playwright to your project:

npm install --save-dev @guidepup/playwright @guidepup/guidepup @playwright/test

[!NOTE] @guidepup/guidepup and @playwright/test are required as peer dependencies of this project.

Install the Guidepup screen reader assets:

npx @guidepup/setup install

And get cracking with your first screen reader tests in Playwright!

Examples

Head over to the Guidepup Website for guides, real world examples, environment setup, and complete API documentation with examples.

You can also check out these examples to learn how you could use Guidepup with Playwright in your projects.

Playwright config

In your playwright.config.ts add the following for the best results with Guidepup for Screen Reader automation:

import { withGuidepup } from "@guidepup/playwright";

export default withGuidepup({
  // ... your custom config
});

withGuidepup configures Playwright to run tests serially and forces headed browsers, including when browser options are specified in individual projects. The existing screenReaderConfig export remains available if you prefer to spread the configuration manually.

Web content navigation

In addition to the Guidepup APIs the screenReader, nvda, orca, and voiceOver instances provided by the Guidepup Playwright setup have an additional utility method .navigateToWebContent().

This method will navigate the screen reader to the first element of the document body in the browser.

Use this method after you navigate to a page and have made any necessary checks that the page has loaded as expected. For example, this is how you might use the method:

// Navigate to the desired page
await page.goto("https://github.com/guidepup/guidepup", {
  waitUntil: "load",
});

// Wait for page to be ready
await page.locator('header[role="banner"]').waitFor();

// Navigate to the web content
await screenReader.navigateToWebContent();

// ... some commands

Providing screen reader start options

The options provided to screenReader.start([options]), nvda.start([options]), orca.start([options]), or voiceOver.start([options]) can be configured using test.use(config) as follows:

// Screen Reader Example
import { screenReaderTest as test } from "@guidepup/playwright";

// Capture all spoken phrases, including usage hints
test.use({ screenReaderStartOptions: { capture: true } });
// NVDA Example
import { nvdaTest as test } from "@guidepup/playwright";

// Capture all spoken phrases, including usage hints
test.use({ nvdaStartOptions: { capture: true } });
// Orca Example
import { orcaTest as test } from "@guidepup/playwright";

// Capture all spoken phrases, including usage hints
test.use({ orcaStartOptions: { capture: true } });
// VoiceOver Example
import { voiceOverTest as test } from "@guidepup/playwright";

// Capture all spoken phrases, including usage hints
test.use({ voiceOverStartOptions: { capture: true } });

The default for NVDA, Orca, and VoiceOver is set to "initial". true captures all spoken phrases, including usage hints. false disables spoken phrase capture.

NVDA example

playwright.config.ts:

import { devices } from "@playwright/test";
import { withGuidepup } from "@guidepup/playwright";

const config = withGuidepup({
  reportSlowTests: null,
  timeout: 5 * 60 * 1000,
  retries: 2,
  projects: [
    {
      name: "chrome",
      use: { ...devices["Desktop Chrome"] },
    },
  ],
});

export default config;

nvda.spec.ts:

import { nvdaTest as test } from "@guidepup/playwright";
import { expect } from "@playwright/test";

test.describe("Playwright NVDA", () => {
  test("I can navigate the Guidepup Github page with NVDA", async ({
    page,
    nvda,
  }) => {
    // Navigate to Guidepup GitHub page
    await page.goto("https://github.com/guidepup/guidepup", {
      waitUntil: "load",
    });

    // Wait for page to be ready and setup
    const header = page.locator('header[role="banner"]');
    await header.waitFor();

    // Interact with the page
    await nvda.navigateToWebContent();

    // Move across the page menu to the Guidepup heading using NVDA
    while ((await nvda.lastSpokenPhrase()) !== "Guidepup, heading, level 1") {
      await nvda.nextHeading();
    }

    // Assert that the spoken phrases are as expected
    expect(JSON.stringify(await nvda.spokenPhraseLog())).toMatchSnapshot();
  });
});

Orca example

playwright.config.ts:

import { devices } from "@playwright/test";
import { withGuidepup } from "@guidepup/playwright";

const config = withGuidepup({
  reportSlowTests: null,
  timeout: 5 * 60 * 1000,
  retries: 2,
  projects: [
    {
      name: "firefox",
      use: { ...devices["Desktop Firefox"] },
    },
  ],
});

export default config;

orca.spec.ts:

import { orcaTest as test } from "@guidepup/playwright";
import { expect } from "@playwright/test";

test.describe("Playwright Orca", () => {
  test("I can navigate the Guidepup Github page with Orca", async ({
    page,
    orca,
  }) => {
    // Navigate to Guidepup GitHub page
    await page.goto("https://github.com/guidepup/guidepup", {
      waitUntil: "load",
    });

    // Wait for page to be ready and setup
    const header = page.locator('header[role="banner"]');
    await header.waitFor();

    // Interact with the page
    await orca.navigateToWebContent();

    // Move across the page menu to the Guidepup heading using Orca
    while ((await orca.lastSpokenPhrase()) !== "Guidepup. heading 1") {
      await orca.nextHeading();
    }

    // Assert that the spoken phrases are as expected
    expect(JSON.stringify(await orca.spokenPhraseLog())).toMatchSnapshot();
  });
});

VoiceOver example

playwright.config.ts:

import { devices } from "@playwright/test";
import { withGuidepup } from "@guidepup/playwright";

const config = withGuidepup({
  reportSlowTests: null,
  timeout: 5 * 60 * 1000,
  retries: 2,
  projects: [
    {
      name: "webkit",
      use: { ...devices["Desktop Safari"] },
    },
  ],
});

export default config;

voiceOver.spec.ts:

import { voiceOverTest as test } from "@guidepup/playwright";
import { expect } from "@playwright/test";

test.describe("Playwright VoiceOver", () => {
  test("I can navigate the Guidepup Github page with VoiceOver", async ({
    page,
    voiceOver,
  }) => {
    // Navigate to Guidepup GitHub page
    await page.goto("https://github.com/guidepup/guidepup", {
      waitUntil: "load",
    });

    // Wait for page to be ready
    const header = page.locator('header[role="banner"]');
    await header.waitFor();

    // Interact with the page
    await voiceOver.navigateToWebContent();

    // Move across the page menu to the Guidepup heading using VoiceOver
    while (
      (await voiceOver.lastSpokenPhrase()) !== "heading level 1 Guidepup"
    ) {
      await voiceOver.nextHeading();
    }

    // Assert that the spoken phrases are as expected
    expect(JSON.stringify(await voiceOver.spokenPhraseLog())).toMatchSnapshot();
  });
});

Capture Playwright Interactions

Use the capture() API to wrap Playwright interactions and capture the resulting screen reader output without needing to perform the interaction through Guidepup.

const capture = await screenReader.capture(() =>
  page.getByRole("button", { name: "Add to cart" }).click(),
);

expect(capture.spokenPhrase).toContain("Added to cart");

Powerful tooling

Check out some of the other Guidepup tooling:

Resources