@guidepup/playwright 0.14.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -7
- package/lib/applicationNameMap.js +1 -1
- package/lib/nvdaTest.d.ts +2 -2
- package/lib/nvdaTest.js +22 -9
- package/lib/screenReaderConfig.d.ts +2 -0
- package/lib/screenReaderConfig.js +2 -0
- package/lib/voiceOverTest.d.ts +3 -3
- package/lib/voiceOverTest.js +17 -7
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -6,12 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
## [Documentation](https://guidepup.dev) | [API Reference](https://www.guidepup.dev/docs/api/class-guidepup)
|
|
8
8
|
|
|
9
|
-
[](https://apps.apple.com/us/app/macos-monterey/id1576738294)
|
|
10
|
-
[](https://apps.apple.com/us/app/macos-ventura/id1638787999)
|
|
11
9
|
[](https://apps.apple.com/us/app/macos-sonoma/id6450717509)
|
|
12
|
-
[](https://apps.apple.com/us/app/macos-sequoia/id6596773750)
|
|
11
|
+
[](https://www.apple.com/uk/os/macos/)
|
|
14
12
|
[](https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2022)
|
|
13
|
+
[](https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2025)
|
|
15
14
|
|
|
16
15
|
This package provides [Guidepup](https://github.com/guidepup/guidepup) integration with [Playwright](https://playwright.dev/) for writing screen reader tests that automate <a href="https://www.guidepup.dev/docs/api/class-voiceover"><b>VoiceOver on MacOS</b></a> and <a href="https://www.guidepup.dev/docs/api/class-nvda"><b>NVDA on Windows</b></a>.
|
|
17
16
|
|
|
@@ -95,7 +94,7 @@ await nvda.navigateToWebContent();
|
|
|
95
94
|
// ... some commands
|
|
96
95
|
```
|
|
97
96
|
|
|
98
|
-
**Note:** This command clears all logs meaning `.spokenPhraseLog()` and `.itemTextLog()` are emptied. If logs from prior to the command are required,
|
|
97
|
+
**Note:** This command clears all logs by default meaning `.spokenPhraseLog()` and `.itemTextLog()` are emptied. If logs from prior to the command are required, either store the logs in a variable for later use:
|
|
99
98
|
|
|
100
99
|
```ts
|
|
101
100
|
// ... some commands
|
|
@@ -114,6 +113,17 @@ const allSpokenPhrases = [...spokenPhrases, ...(await nvda.spokenPhraseLog())];
|
|
|
114
113
|
// ... do something with spoken phrases
|
|
115
114
|
```
|
|
116
115
|
|
|
116
|
+
or pass a flag to prevent log clearing:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
// ... some commands
|
|
120
|
+
|
|
121
|
+
// Navigate to the web content
|
|
122
|
+
await nvda.navigateToWebContent(false);
|
|
123
|
+
|
|
124
|
+
// ... some commands
|
|
125
|
+
```
|
|
126
|
+
|
|
117
127
|
### Providing Screen Reader Start Options
|
|
118
128
|
|
|
119
129
|
The options provided to `nvda.start([options])` or `voiceOver.start([options])` can be configured using `test.use(config)` as follows:
|
|
@@ -122,16 +132,20 @@ The options provided to `nvda.start([options])` or `voiceOver.start([options])`
|
|
|
122
132
|
// VoiceOver Example
|
|
123
133
|
import { voiceOverTest as test } from "@guidepup/playwright";
|
|
124
134
|
|
|
125
|
-
|
|
135
|
+
// Capture all spoken phrases, including usage hints
|
|
136
|
+
test.use({ voiceOverStartOptions: { capture: true } });
|
|
126
137
|
```
|
|
127
138
|
|
|
128
139
|
```ts
|
|
129
140
|
// NVDA Example
|
|
130
141
|
import { nvdaTest as test } from "@guidepup/playwright";
|
|
131
142
|
|
|
132
|
-
|
|
143
|
+
// Capture all spoken phrases, including usage hints
|
|
144
|
+
test.use({ nvdaStartOptions: { capture: true } });
|
|
133
145
|
```
|
|
134
146
|
|
|
147
|
+
The default for VoiceOver and NVDA is set to `"initial"`. `true` captures all spoken phrases, including usage hints. `false` disables spoken phrase capture.
|
|
148
|
+
|
|
135
149
|
### VoiceOver Example
|
|
136
150
|
|
|
137
151
|
`playwright.config.ts`:
|
|
@@ -148,6 +162,8 @@ const config: PlaywrightTestConfig = {
|
|
|
148
162
|
projects: [
|
|
149
163
|
{
|
|
150
164
|
name: "webkit",
|
|
165
|
+
// Take care to ensure all usage is headed - screen readers cannot
|
|
166
|
+
// operate against headless browsers.
|
|
151
167
|
use: { ...devices["Desktop Safari"], headless: false },
|
|
152
168
|
},
|
|
153
169
|
],
|
|
@@ -206,6 +222,8 @@ const config: PlaywrightTestConfig = {
|
|
|
206
222
|
projects: [
|
|
207
223
|
{
|
|
208
224
|
name: "firefox",
|
|
225
|
+
// Take care to ensure all usage is headed - screen readers cannot
|
|
226
|
+
// operate against headless browsers.
|
|
209
227
|
use: { ...devices["Desktop Firefox"], headless: false },
|
|
210
228
|
},
|
|
211
229
|
],
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.applicationNameMap = void 0;
|
|
4
4
|
exports.applicationNameMap = {
|
|
5
|
-
chromium: "
|
|
5
|
+
chromium: "Google Chrome For Testing",
|
|
6
6
|
chrome: "Google Chrome",
|
|
7
7
|
"chrome-beta": "Google Chrome Beta",
|
|
8
8
|
msedge: "Microsoft Edge",
|
package/lib/nvdaTest.d.ts
CHANGED
|
@@ -32,9 +32,9 @@ export interface NVDAPlaywright extends NVDA {
|
|
|
32
32
|
*
|
|
33
33
|
* This command should be used after page navigation.
|
|
34
34
|
*
|
|
35
|
-
* Note: this command clears all logs.
|
|
35
|
+
* Note: this command clears all logs by default.
|
|
36
36
|
*/
|
|
37
|
-
navigateToWebContent(): Promise<void>;
|
|
37
|
+
navigateToWebContent(clearLogs?: boolean): Promise<void>;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* These tests extend the default Playwright environment that launches the
|
package/lib/nvdaTest.js
CHANGED
|
@@ -14,10 +14,14 @@ const MOVE_TO_TOP = {
|
|
|
14
14
|
keyCode: [guidepup_1.WindowsKeyCodes.Home],
|
|
15
15
|
modifiers: [guidepup_1.WindowsModifiers.Control],
|
|
16
16
|
};
|
|
17
|
-
const
|
|
17
|
+
const hasFocus = ({ applicationName, pageTitle, windowTitle, }) => {
|
|
18
|
+
return ((pageTitle.length && windowTitle.startsWith(pageTitle)) ||
|
|
19
|
+
windowTitle.includes(applicationName));
|
|
20
|
+
};
|
|
21
|
+
const focusBrowser = async ({ applicationName, pageTitle, }) => {
|
|
18
22
|
await nvdaPlaywright.perform(nvdaPlaywright.keyboardCommands.reportTitle);
|
|
19
23
|
let windowTitle = await nvdaPlaywright.lastSpokenPhrase();
|
|
20
|
-
if (
|
|
24
|
+
if (hasFocus({ applicationName, pageTitle, windowTitle })) {
|
|
21
25
|
return;
|
|
22
26
|
}
|
|
23
27
|
let applicationSwitchRetryCount = 0;
|
|
@@ -26,7 +30,7 @@ const focusBrowser = async ({ applicationName, }) => {
|
|
|
26
30
|
await nvdaPlaywright.perform(SWITCH_APPLICATION);
|
|
27
31
|
await nvdaPlaywright.perform(nvdaPlaywright.keyboardCommands.reportTitle);
|
|
28
32
|
windowTitle = await nvdaPlaywright.lastSpokenPhrase();
|
|
29
|
-
if (
|
|
33
|
+
if (hasFocus({ applicationName, pageTitle, windowTitle })) {
|
|
30
34
|
break;
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -38,7 +42,7 @@ const focusBrowser = async ({ applicationName, }) => {
|
|
|
38
42
|
* A fresh started NVDA instance `nvda` is provided to each test.
|
|
39
43
|
*/
|
|
40
44
|
exports.nvdaTest = test_1.test.extend({
|
|
41
|
-
nvdaStartOptions: {},
|
|
45
|
+
nvdaStartOptions: { capture: "initial" },
|
|
42
46
|
nvda: async ({ browserName, page, nvdaStartOptions }, use) => {
|
|
43
47
|
try {
|
|
44
48
|
const applicationName = applicationNameMap_1.applicationNameMap[browserName];
|
|
@@ -47,11 +51,18 @@ exports.nvdaTest = test_1.test.extend({
|
|
|
47
51
|
}
|
|
48
52
|
await page.goto("about:blank", { waitUntil: "load" });
|
|
49
53
|
await page.bringToFront();
|
|
50
|
-
nvdaPlaywright.navigateToWebContent = async () => {
|
|
54
|
+
nvdaPlaywright.navigateToWebContent = async (clearLogs = true) => {
|
|
51
55
|
// Make sure NVDA is not in focus mode.
|
|
52
56
|
await nvdaPlaywright.perform(nvdaPlaywright.keyboardCommands.exitFocusMode);
|
|
57
|
+
const pageTitle = await page.title();
|
|
53
58
|
// Ensure application is brought to front and focused.
|
|
54
|
-
await focusBrowser({ applicationName });
|
|
59
|
+
await focusBrowser({ applicationName, pageTitle });
|
|
60
|
+
// Ensure the document is ready and focused.
|
|
61
|
+
await page.bringToFront();
|
|
62
|
+
await page.locator("body").waitFor();
|
|
63
|
+
await page.locator("body").focus();
|
|
64
|
+
await page.locator("body").click();
|
|
65
|
+
await page.locator("body").blur();
|
|
55
66
|
// NVDA appears to not work well with Firefox when switching between
|
|
56
67
|
// applications resulting in the entire browser window having NVDA focus
|
|
57
68
|
// with focus mode.
|
|
@@ -67,9 +78,11 @@ exports.nvdaTest = test_1.test.extend({
|
|
|
67
78
|
await nvdaPlaywright.perform(nvdaPlaywright.keyboardCommands.toggleBetweenBrowseAndFocusMode);
|
|
68
79
|
await nvdaPlaywright.perform(nvdaPlaywright.keyboardCommands.exitFocusMode);
|
|
69
80
|
await nvdaPlaywright.perform(MOVE_TO_TOP);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
81
|
+
if (clearLogs) {
|
|
82
|
+
// Clear out logs.
|
|
83
|
+
await nvdaPlaywright.clearItemTextLog();
|
|
84
|
+
await nvdaPlaywright.clearSpokenPhraseLog();
|
|
85
|
+
}
|
|
73
86
|
};
|
|
74
87
|
await nvdaPlaywright.start(nvdaStartOptions);
|
|
75
88
|
await use(nvdaPlaywright);
|
|
@@ -2,5 +2,7 @@ import { PlaywrightTestConfig } from "@playwright/test";
|
|
|
2
2
|
export type ScreenReaderPlaywrightTestConfig = PlaywrightTestConfig;
|
|
3
3
|
/**
|
|
4
4
|
* Minimal required configuration for Screen Reader tests in Playwright.
|
|
5
|
+
*
|
|
6
|
+
* Depending on your configuration this may not be sufficient.
|
|
5
7
|
*/
|
|
6
8
|
export declare const screenReaderConfig: ScreenReaderPlaywrightTestConfig;
|
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.screenReaderConfig = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Minimal required configuration for Screen Reader tests in Playwright.
|
|
6
|
+
*
|
|
7
|
+
* Depending on your configuration this may not be sufficient.
|
|
6
8
|
*/
|
|
7
9
|
exports.screenReaderConfig = {
|
|
8
10
|
/**
|
package/lib/voiceOverTest.d.ts
CHANGED
|
@@ -28,11 +28,11 @@ export interface VoiceOverPlaywright extends VoiceOver {
|
|
|
28
28
|
* Guidepup Playwright specific command that navigates VoiceOver to the beginning
|
|
29
29
|
* of the browser's web content.
|
|
30
30
|
*
|
|
31
|
-
* This command should be used after page navigation.
|
|
31
|
+
* This command should be used after a page navigation has completed.
|
|
32
32
|
*
|
|
33
|
-
* Note: this command clears all logs.
|
|
33
|
+
* Note: this command clears all logs by default.
|
|
34
34
|
*/
|
|
35
|
-
navigateToWebContent(): Promise<void>;
|
|
35
|
+
navigateToWebContent(clearLogs?: boolean): Promise<void>;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* These tests extend the default Playwright environment that launches the
|
package/lib/voiceOverTest.js
CHANGED
|
@@ -12,26 +12,36 @@ const voiceOverPlaywright = guidepup_1.voiceOver;
|
|
|
12
12
|
* A fresh started VoiceOver instance `voiceOver` is provided to each test.
|
|
13
13
|
*/
|
|
14
14
|
exports.voiceOverTest = test_1.test.extend({
|
|
15
|
-
voiceOverStartOptions: {},
|
|
15
|
+
voiceOverStartOptions: { capture: "initial" },
|
|
16
16
|
voiceOver: async ({ browserName, page, voiceOverStartOptions }, use) => {
|
|
17
17
|
try {
|
|
18
18
|
const applicationName = applicationNameMap_1.applicationNameMap[browserName];
|
|
19
19
|
if (!applicationName) {
|
|
20
20
|
throw new Error(`Browser ${browserName} is not installed.`);
|
|
21
21
|
}
|
|
22
|
-
voiceOverPlaywright.navigateToWebContent = async () => {
|
|
22
|
+
voiceOverPlaywright.navigateToWebContent = async (clearLogs = true) => {
|
|
23
23
|
// Ensure application is brought to front and focused.
|
|
24
24
|
await (0, guidepup_1.macOSActivate)(applicationName);
|
|
25
25
|
// Ensure the document is ready and focused.
|
|
26
26
|
await page.bringToFront();
|
|
27
27
|
await page.locator("body").waitFor();
|
|
28
28
|
await page.locator("body").focus();
|
|
29
|
-
|
|
29
|
+
await page.locator("body").click();
|
|
30
|
+
await page.locator("body").blur();
|
|
31
|
+
// Try to navigate into web content.
|
|
30
32
|
await voiceOverPlaywright.interact();
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
await voiceOverPlaywright.
|
|
34
|
-
await voiceOverPlaywright.
|
|
33
|
+
// Series of find previous commands to escape accidental interaction
|
|
34
|
+
// with sub-content of web content area.
|
|
35
|
+
await voiceOverPlaywright.perform(voiceOverPlaywright.keyboardCommands.findPreviousHeading);
|
|
36
|
+
await voiceOverPlaywright.perform(voiceOverPlaywright.keyboardCommands.findPreviousGraphic);
|
|
37
|
+
await voiceOverPlaywright.perform(voiceOverPlaywright.keyboardCommands.findPreviousPlainText);
|
|
38
|
+
// Navigate to the beginning of the web content.
|
|
39
|
+
await voiceOverPlaywright.perform(voiceOverPlaywright.keyboardCommands.moveToBeginningOfText);
|
|
40
|
+
if (clearLogs) {
|
|
41
|
+
// Clear out logs.
|
|
42
|
+
await voiceOverPlaywright.clearItemTextLog();
|
|
43
|
+
await voiceOverPlaywright.clearSpokenPhraseLog();
|
|
44
|
+
}
|
|
35
45
|
};
|
|
36
46
|
await voiceOverPlaywright.start(voiceOverStartOptions);
|
|
37
47
|
await (0, guidepup_1.macOSActivate)(applicationName);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guidepup/playwright",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Screen reader driver for Playwright tests.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "https://github.com/guidepup/guidepup-playwright"
|
|
11
|
+
"url": "git+https://github.com/guidepup/guidepup-playwright.git"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/guidepup/guidepup-playwright/issues"
|
|
@@ -42,22 +42,22 @@
|
|
|
42
42
|
"test:voiceover:webkit": "playwright test --config ./examples/playwright-voiceover/webkit.config.ts ./examples/playwright-voiceover/tests/webkit/"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@guidepup/guidepup": "^0.
|
|
45
|
+
"@guidepup/guidepup": "^0.25.0",
|
|
46
46
|
"@guidepup/record": "^0.1.0",
|
|
47
|
-
"@playwright/test": "^1.
|
|
48
|
-
"@types/node": "^
|
|
49
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
50
|
-
"@typescript-eslint/parser": "^8.
|
|
47
|
+
"@playwright/test": "^1.60.0",
|
|
48
|
+
"@types/node": "^24.10.1",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^8.48.1",
|
|
50
|
+
"@typescript-eslint/parser": "^8.48.1",
|
|
51
51
|
"eslint": "^8.56.0",
|
|
52
52
|
"eslint-config-prettier": "^9.1.0",
|
|
53
|
-
"rimraf": "^6.
|
|
53
|
+
"rimraf": "^6.1.2",
|
|
54
54
|
"ts-node": "^10.9.2",
|
|
55
|
-
"typedoc": "^0.
|
|
56
|
-
"typescript": "^5.
|
|
55
|
+
"typedoc": "^0.28.15",
|
|
56
|
+
"typescript": "^5.9.3"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@guidepup/guidepup": ">=0.
|
|
60
|
-
"@playwright/test": "^1.
|
|
59
|
+
"@guidepup/guidepup": ">=0.25.0",
|
|
60
|
+
"@playwright/test": "^1.57.0"
|
|
61
61
|
},
|
|
62
62
|
"resolutions": {
|
|
63
63
|
"strip-ansi": "6.0.1",
|