Guidepup is a screen reader automation library for testing.
This package provides Guidepup integration with Playwright to enable testing with VoiceOver on MacOS and NVDA on Windows.
- 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.
Set up your machine for screen reader automation:
npx @guidepup/setup setupInstall @guidepup/playwright to your project:
npm install --save-dev @guidepup/playwright @guidepup/guidepup @playwright/testNote
@guidepup/guidepup and @playwright/test are required as peer dependencies of this project.
Install the Guidepup screen reader assets:
npx @guidepup/setup installAnd get cracking with your first screen reader tests in Playwright!
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.
In your playwright.config.ts add the following for the best results with Guidepup for Screen Reader automation:
import { devices, PlaywrightTestConfig } from "@playwright/test";
import { screenReaderConfig } from "@guidepup/playwright";
const config: PlaywrightTestConfig = {
...screenReaderConfig,
// ... your custom config
};
export default config;Check out the configuration this adds in the config.ts file.
In addition to the Guidepup APIs the screenReader, voiceOver, and nvda 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 commandsThe options provided to screenReader.start([options]), nvda.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 } });// VoiceOver Example
import { voiceOverTest as test } from "@guidepup/playwright";
// Capture all spoken phrases, including usage hints
test.use({ voiceOverStartOptions: { capture: true } });// NVDA Example
import { nvdaTest as test } from "@guidepup/playwright";
// Capture all spoken phrases, including usage hints
test.use({ nvdaStartOptions: { capture: true } });The default for VoiceOver and NVDA is set to "initial". true captures all spoken phrases, including usage hints. false disables spoken phrase capture.
playwright.config.ts:
import { devices, PlaywrightTestConfig } from "@playwright/test";
import { screenReaderConfig } from "@guidepup/playwright";
const config: PlaywrightTestConfig = {
...screenReaderConfig,
reportSlowTests: null,
timeout: 5 * 60 * 1000,
retries: 2,
projects: [
{
name: "webkit",
// Take care to ensure all usage is headed - screen readers cannot
// operate against headless browsers.
use: { ...devices["Desktop Safari"], headless: false },
},
],
};
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.itemText()) !== "Guidepup heading level 1") {
await voiceOver.perform(voiceOver.keyboardCommands.findNextHeading);
}
// Assert that the spoken phrases are as expected
expect(JSON.stringify(await voiceOver.spokenPhraseLog())).toMatchSnapshot();
});
});playwright.config.ts:
import { devices, PlaywrightTestConfig } from "@playwright/test";
import { screenReaderConfig } from "@guidepup/playwright";
const config: PlaywrightTestConfig = {
...screenReaderConfig,
reportSlowTests: null,
timeout: 5 * 60 * 1000,
retries: 2,
projects: [
{
name: "firefox",
// Take care to ensure all usage is headed - screen readers cannot
// operate against headless browsers.
use: { ...devices["Desktop Firefox"], headless: false },
},
],
};
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()).includes("Guidepup, heading, level 1")
) {
await nvda.perform(nvda.keyboardCommands.moveToNextHeading);
}
// Assert that the spoken phrases are as expected
expect(JSON.stringify(await nvda.spokenPhraseLog())).toMatchSnapshot();
});
});Check out some of the other Guidepup modules:
@guidepup/guidepup- Reliable automation for your screen reader a11y workflows through JavaScript supporting VoiceOver and NVDA.@guidepup/setup- Set up your local or CI environment for screen reader test automation.@guidepup/virtual-screen-reader- Reliable unit testing for your screen reader a11y workflows.@guidepup/jest- Jest matchers for reliable unit testing of your screen reader a11y workflows.
