Testing announcements
Screen reader testing is not only about moving through the page. It is also about observing what the screen reader says.
Guidepup exposes phrase capture APIs for that:
Those APIs are available on the shared screen reader interface and on the concrete reader instances such as voiceOver and nvda.
Capture the latest spoken phrase
After a navigation or interaction step, read the latest phrase from the reader:
import { voiceOver } from "@guidepup/guidepup";
await voiceOver.start();
try {
await voiceOver.next();
const phrase = await voiceOver.lastSpokenPhrase();
expect(phrase).toContain("Products");
} finally {
await voiceOver.stop();
}
The same shape works with NVDA:
await nvda.next();
const phrase = await nvda.lastSpokenPhrase();
expect(phrase).toContain("Products");
Use lastSpokenPhrase() when a test only needs the most recent announcement.
Inspect a sequence of announcements
Use spokenPhraseLog() when you need to inspect a sequence of announcements instead of just the most recent one:
await voiceOver.start();
try {
await voiceOver.next();
await voiceOver.next();
const log = await voiceOver.spokenPhraseLog();
expect(log).toEqual(expect.arrayContaining([expect.any(String)]));
} finally {
await voiceOver.stop();
}
This is useful for commands that produce a stream of output rather than one isolated phrase.
Clear transcript state
Clear the spoken phrase history when you want to start a fresh observation window:
await voiceOver.clearSpokenPhraseLog();
await nvda.clearSpokenPhraseLog();
You can use the same idea with clearItemTextLog() when you want to reset collected item text state.
Assertion advice
Announcements are often the least predictable part of a screen reader test. They vary across screen reader implementations, browsers, and page content.
A practical assertion is usually one of these:
- a full equality check when the phrase is intentionally stable
- a substring check when the phrase may vary
A typical announcement test reads like this:
await voiceOver.act();
const phrase = await voiceOver.lastSpokenPhrase();
expect(phrase).toContain("Added to basket");
This lets you verify dynamic announcements without hard-coding an overstrict phrase string.