Guidepup Playwright
This package provides Guidepup integration with Playwright for writing screen reader tests that automate VoiceOver on MacOS and NVDA on Windows.
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 environment for screen reader automation with @guidepup/setup
:
npx @guidepup/setup
If you are using GitHub Actions, check out the dedicated guidepup/setup-action
:
- name: Setup Environment
uses: guidepup/setup-action
Install @guidepup/playwright
to your project:
npm install --save-dev @guidepup/playwright @guidepup/guidepup @playwright/test
Note: you require @guidepup/guidepup
and @playwright/test
as they are peer dependencies to this project.
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 awesome examples to learn how you could use Guidepup with Playwright in your projects.
Alternatively check out this project which runs several thousand tests to assert screen reader compatibility against W3C ARIA-AT test suite.
Playwright Config
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,
};
export default config;
Check out the configuration this adds in the config.ts
file.
Web Content Navigation
In addition to the Guidepup APIs the 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 with NVDA:
await page.goto("https://github.com/guidepup/guidepup", {
waitUntil: "load",
});
await page.locator('header[role="banner"]').waitFor();
await nvda.navigateToWebContent();
Note: This command clears all logs meaning .spokenPhraseLog()
and .itemTextLog()
are emptied. If logs from prior to the command are required, first store the logs in a variable for later use:
const spokenPhrases = await nvda.spokenPhraseLog();
await nvda.navigateToWebContent();
const allSpokenPhrases = [...spokenPhrases, ...(await nvda.spokenPhraseLog())];
Providing Screen Reader Start Options
The options provided to nvda.start([options])
or voiceOver.start([options])
can be configured using test.use(config)
as follows:
import { voiceOverTest as test } from "@guidepup/playwright";
test.use({ voiceOverStartOptions: { capture: "initial" } });
import { nvdaTest as test } from "@guidepup/playwright";
test.use({ nvdaStartOptions: { capture: "initial" } });
VoiceOver Example
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",
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,
}) => {
await page.goto("https://github.com/guidepup/guidepup", {
waitUntil: "load",
});
const header = page.locator('header[role="banner"]');
await header.waitFor();
await voiceOver.navigateToWebContent();
while ((await voiceOver.itemText()) !== "Guidepup heading level 1") {
await voiceOver.perform(voiceOver.keyboardCommands.findNextHeading);
}
expect(JSON.stringify(await voiceOver.spokenPhraseLog())).toMatchSnapshot();
});
});
NVDA Example
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",
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,
}) => {
await page.goto("https://github.com/guidepup/guidepup", {
waitUntil: "load",
});
const header = page.locator('header[role="banner"]');
await header.waitFor();
await nvda.navigateToWebContent();
while (
!(await nvda.lastSpokenPhrase()).includes("Guidepup, heading, level 1")
) {
await nvda.perform(nvda.keyboardCommands.moveToNextHeading);
}
expect(JSON.stringify(await nvda.spokenPhraseLog())).toMatchSnapshot();
});
});
Powerful Tooling
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.
Resources