mcp-accessibility-scanner 2.0.4 → 2.0.6
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 +41 -1
- package/lib/browserServerBackend.js.map +1 -1
- package/lib/mcp/proxyBackend.js +2 -3
- package/lib/mcp/proxyBackend.js.map +1 -1
- package/lib/mcp/tool.js +2 -2
- package/lib/mcp/tool.js.map +1 -1
- package/lib/tools/auditKeyboard.js +296 -0
- package/lib/tools/auditKeyboard.js.map +1 -0
- package/lib/tools/auditSite.js +398 -0
- package/lib/tools/auditSite.js.map +1 -0
- package/lib/tools/axe.js +58 -0
- package/lib/tools/axe.js.map +1 -0
- package/lib/tools/scanPageMatrix.js +207 -0
- package/lib/tools/scanPageMatrix.js.map +1 -0
- package/lib/tools/snapshot.js +5 -23
- package/lib/tools/snapshot.js.map +1 -1
- package/lib/tools.js +6 -0
- package/lib/tools.js.map +1 -1
- package/lib/vscode/host.js +1 -2
- package/lib/vscode/host.js.map +1 -1
- package/package.json +24 -24
package/README.md
CHANGED
|
@@ -131,6 +131,47 @@ Performs a comprehensive accessibility scan on the current page using Axe-core.
|
|
|
131
131
|
- Section 508: `section508`
|
|
132
132
|
- Categories: `cat.aria`, `cat.color`, `cat.forms`, `cat.keyboard`, `cat.language`, `cat.name-role-value`, `cat.parsing`, `cat.semantics`, `cat.sensory-and-visual-cues`, `cat.structure`, `cat.tables`, `cat.text-alternatives`, `cat.time-and-media`
|
|
133
133
|
|
|
134
|
+
### Audit Tools
|
|
135
|
+
|
|
136
|
+
#### `audit_site`
|
|
137
|
+
Crawls and scans multiple internal pages, then aggregates violations across the site.
|
|
138
|
+
- Default strategy: link-based BFS from the current URL
|
|
139
|
+
- Supports `links`, `nav`, `sitemap`, and `provided` URL strategies
|
|
140
|
+
- Always writes a JSON report (default filename: `audit-site-{timestamp}.json`)
|
|
141
|
+
|
|
142
|
+
**Example flow:**
|
|
143
|
+
```text
|
|
144
|
+
1. Navigate to your site homepage with browser_navigate
|
|
145
|
+
2. Run audit_site with maxPages: 25 and maxDepth: 2
|
|
146
|
+
3. Review the report path returned by the tool (written to the MCP output directory)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### `scan_page_matrix`
|
|
150
|
+
Runs Axe scans on the same page across viewport/media/zoom variants and compares deltas against baseline.
|
|
151
|
+
- Default variants: baseline, mobile, desktop, forced-colors, reduced-motion, zoom-200
|
|
152
|
+
- Supports custom variants and optional reload between variants
|
|
153
|
+
- Always writes a JSON report (default filename: `scan-matrix-{timestamp}.json`)
|
|
154
|
+
|
|
155
|
+
**Example flow:**
|
|
156
|
+
```text
|
|
157
|
+
1. Navigate to a page state you want to validate
|
|
158
|
+
2. Run scan_page_matrix with defaults (or provide custom variants)
|
|
159
|
+
3. Review per-variant deltas and open the generated JSON report path
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### `audit_keyboard`
|
|
163
|
+
Audits real keyboard focus behavior by pressing Tab (and optional Shift+Tab) with practical heuristics.
|
|
164
|
+
- Checks skip links, focus visibility, focus jumps, and possible focus traps
|
|
165
|
+
- Optional issue screenshots (`screenshotOnIssue`)
|
|
166
|
+
- Always writes a JSON report (default filename: `audit-keyboard-{timestamp}.json`)
|
|
167
|
+
|
|
168
|
+
**Example flow:**
|
|
169
|
+
```text
|
|
170
|
+
1. Navigate to the target page and let it fully load
|
|
171
|
+
2. Run audit_keyboard with maxTabs: 50
|
|
172
|
+
3. Review focus findings and open the generated JSON report path
|
|
173
|
+
```
|
|
174
|
+
|
|
134
175
|
### Navigation Tools
|
|
135
176
|
|
|
136
177
|
#### `browser_navigate`
|
|
@@ -312,4 +353,3 @@ npm install
|
|
|
312
353
|
## License
|
|
313
354
|
|
|
314
355
|
MIT
|
|
315
|
-
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserServerBackend.js","sourceRoot":"","sources":["../src/browserServerBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAO1C,MAAM,OAAO,oBAAoB;IACvB,MAAM,CAAS;IACf,QAAQ,CAAsB;IAC9B,WAAW,CAAyB;IACpC,OAAO,CAAa;IACpB,sBAAsB,CAAwB;IAEtD,YAAY,MAAkB,EAAE,OAA8B;QAC5D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,sBAAsB,GAAG,OAAO,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAwB,EAAE,aAAsC,EAAE,KAAuB;QACxG,IAAI,QAA4B,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;YACnC,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC7D,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1G,IAAI,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC;YAC1B,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,MAAM,EAAE,IAAI,CAAC,OAAO;YACpB,qBAAqB,EAAE,IAAI,CAAC,sBAAsB;YAClD,UAAU,EAAE,IAAI,CAAC,WAAW;YAC5B,UAAU,EAAE,EAAE,GAAG,aAAa,EAAE,QAAQ,EAAE;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,YAA8D;QACzF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAE,CAAC;QAClE,IAAI,CAAC,IAAI;YACP,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,aAAa,CAAC,CAAC;QAC9C,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"browserServerBackend.js","sourceRoot":"","sources":["../src/browserServerBackend.ts"],"names":[],"mappings":"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"}
|
package/lib/mcp/proxyBackend.js
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import debug from 'debug';
|
|
17
17
|
import { z } from 'zod';
|
|
18
|
-
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
19
18
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
20
19
|
import { ListRootsRequestSchema, PingRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
21
20
|
const errorsDebug = debug('pw:mcp:errors');
|
|
@@ -76,9 +75,9 @@ export class ProxyBackend {
|
|
|
76
75
|
'Connect to a browser using one of the available methods:',
|
|
77
76
|
...this._mcpProviders.map(factory => `- "${factory.name}": ${factory.description}`),
|
|
78
77
|
].join('\n'),
|
|
79
|
-
inputSchema:
|
|
78
|
+
inputSchema: z.toJSONSchema(z.object({
|
|
80
79
|
name: z.enum(this._mcpProviders.map(factory => factory.name)).default(this._mcpProviders[0].name).describe('The method to use to connect to the browser'),
|
|
81
|
-
})
|
|
80
|
+
})),
|
|
82
81
|
annotations: {
|
|
83
82
|
title: 'Connect to a browser context',
|
|
84
83
|
readOnlyHint: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxyBackend.js","sourceRoot":"","sources":["../../src/mcp/proxyBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"proxyBackend.js","sourceRoot":"","sources":["../../src/mcp/proxyBackend.ts"],"names":[],"mappings":"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"}
|
package/lib/mcp/tool.js
CHANGED
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
16
|
+
import { z } from 'zod';
|
|
17
17
|
export function toMcpTool(tool) {
|
|
18
18
|
return {
|
|
19
19
|
name: tool.name,
|
|
20
20
|
description: tool.description,
|
|
21
|
-
inputSchema:
|
|
21
|
+
inputSchema: z.toJSONSchema(tool.inputSchema),
|
|
22
22
|
annotations: {
|
|
23
23
|
title: tool.title,
|
|
24
24
|
readOnlyHint: tool.type === 'readOnly',
|
package/lib/mcp/tool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/mcp/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/mcp/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,MAAM,UAAU,SAAS,CAAC,IAAqB;IAC7C,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAkC;QAC9E,WAAW,EAAE;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,YAAY,EAAE,IAAI,CAAC,IAAI,KAAK,UAAU;YACtC,eAAe,EAAE,IAAI,CAAC,IAAI,KAAK,aAAa;YAC5C,aAAa,EAAE,IAAI;SACpB;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAyB,IAAuB;IAC9E,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { defineTabTool } from './tool.js';
|
|
4
|
+
import { sanitizeForFilePath } from '../utils/fileUtils.js';
|
|
5
|
+
function buildFingerprint(point) {
|
|
6
|
+
return [
|
|
7
|
+
point.role ?? '',
|
|
8
|
+
point.name ?? '',
|
|
9
|
+
point.href ?? '',
|
|
10
|
+
point.tagName ?? '',
|
|
11
|
+
point.id ?? '',
|
|
12
|
+
].join('|');
|
|
13
|
+
}
|
|
14
|
+
function isLikelySkipLink(point) {
|
|
15
|
+
if (point.role !== 'link')
|
|
16
|
+
return false;
|
|
17
|
+
const value = `${point.name ?? ''} ${point.text ?? ''}`.toLowerCase();
|
|
18
|
+
return /\bskip\b/.test(value);
|
|
19
|
+
}
|
|
20
|
+
function didUrlHashChange(urlBefore, urlAfter) {
|
|
21
|
+
if (!urlBefore || !urlAfter)
|
|
22
|
+
return false;
|
|
23
|
+
try {
|
|
24
|
+
return new URL(urlBefore).hash !== new URL(urlAfter).hash;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function safeIsoTimestampForFileName() {
|
|
31
|
+
return sanitizeForFilePath(new Date().toISOString());
|
|
32
|
+
}
|
|
33
|
+
async function maybeCaptureIssueScreenshot(options, callbacks, screenshots, issueName) {
|
|
34
|
+
if (!options.screenshotOnIssue || !callbacks.captureScreenshot)
|
|
35
|
+
return;
|
|
36
|
+
if (screenshots.length >= options.maxIssueScreenshots)
|
|
37
|
+
return;
|
|
38
|
+
const path = await callbacks.captureScreenshot(issueName);
|
|
39
|
+
screenshots.push(path);
|
|
40
|
+
}
|
|
41
|
+
export async function runKeyboardFocusAudit(options, callbacks) {
|
|
42
|
+
const stops = [];
|
|
43
|
+
const uniqueFingerprints = new Set();
|
|
44
|
+
const screenshots = [];
|
|
45
|
+
let skipLinkStep = null;
|
|
46
|
+
let skipLinkActivation = null;
|
|
47
|
+
let skipLinkActivated = false;
|
|
48
|
+
let focusTrapDetectedAt = null;
|
|
49
|
+
let focusTrapFingerprint = null;
|
|
50
|
+
let focusTrapRecentFingerprints = [];
|
|
51
|
+
for (let step = 1; step <= options.maxTabs; step++) {
|
|
52
|
+
const key = options.includeShiftTab && step % 2 === 0 ? 'Shift+Tab' : 'Tab';
|
|
53
|
+
const before = await callbacks.getActiveElementInfo();
|
|
54
|
+
await callbacks.pressKey(key);
|
|
55
|
+
const after = await callbacks.getActiveElementInfo();
|
|
56
|
+
const stop = {
|
|
57
|
+
...after,
|
|
58
|
+
step,
|
|
59
|
+
key,
|
|
60
|
+
fingerprint: buildFingerprint(after),
|
|
61
|
+
scrollDeltaX: after.scrollX - before.scrollX,
|
|
62
|
+
scrollDeltaY: after.scrollY - before.scrollY,
|
|
63
|
+
issues: [],
|
|
64
|
+
};
|
|
65
|
+
uniqueFingerprints.add(stop.fingerprint);
|
|
66
|
+
if (options.checkFocusVisibility && !stop.hasVisibleIndicator) {
|
|
67
|
+
stop.issues.push('no-visible-focus-indicator');
|
|
68
|
+
await maybeCaptureIssueScreenshot(options, callbacks, screenshots, `focus-visibility-${step}`);
|
|
69
|
+
}
|
|
70
|
+
if (options.checkFocusJumps) {
|
|
71
|
+
const hasLargeJump = Math.abs(stop.scrollDeltaY) > options.jumpScrollThresholdPx;
|
|
72
|
+
const isNotVisible = stop.boundingBox === null || !stop.inViewport;
|
|
73
|
+
if (hasLargeJump || isNotVisible) {
|
|
74
|
+
stop.issues.push('focus-jump-or-not-visible');
|
|
75
|
+
await maybeCaptureIssueScreenshot(options, callbacks, screenshots, `focus-jump-${step}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (options.checkSkipLink && step <= options.skipLinkMaxTabs && isLikelySkipLink(stop) && skipLinkStep === null) {
|
|
79
|
+
skipLinkStep = step;
|
|
80
|
+
if (options.activateSkipLink && !skipLinkActivated) {
|
|
81
|
+
const beforeActivation = stop;
|
|
82
|
+
const urlBefore = callbacks.getCurrentUrl ? await callbacks.getCurrentUrl() : null;
|
|
83
|
+
await callbacks.pressKey('Enter');
|
|
84
|
+
const afterActivation = await callbacks.getActiveElementInfo();
|
|
85
|
+
const urlAfter = callbacks.getCurrentUrl ? await callbacks.getCurrentUrl() : null;
|
|
86
|
+
const hashChanged = didUrlHashChange(urlBefore, urlAfter);
|
|
87
|
+
const fullUrlChanged = urlBefore !== null && urlAfter !== null && urlBefore !== urlAfter;
|
|
88
|
+
const navigationOccurred = fullUrlChanged && !hashChanged;
|
|
89
|
+
skipLinkActivation = {
|
|
90
|
+
attempted: true,
|
|
91
|
+
hashChanged,
|
|
92
|
+
focusChanged: buildFingerprint(beforeActivation) !== buildFingerprint(afterActivation),
|
|
93
|
+
scrollChanged: beforeActivation.scrollY !== afterActivation.scrollY || beforeActivation.scrollX !== afterActivation.scrollX,
|
|
94
|
+
navigationOccurred,
|
|
95
|
+
urlBefore,
|
|
96
|
+
urlAfter,
|
|
97
|
+
};
|
|
98
|
+
if (navigationOccurred && callbacks.goBack)
|
|
99
|
+
await callbacks.goBack();
|
|
100
|
+
skipLinkActivated = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (options.checkFocusTrap) {
|
|
104
|
+
let shouldStopOnCycle = false;
|
|
105
|
+
const recentStops = stops.slice(Math.max(0, stops.length - options.cycleWindow + 1));
|
|
106
|
+
const foundRepeat = recentStops.some(previous => previous.fingerprint === stop.fingerprint);
|
|
107
|
+
const touchedDocumentRoot = recentStops.some(previous => previous.tagName === 'HTML' || previous.tagName === 'BODY') || stop.tagName === 'HTML' || stop.tagName === 'BODY';
|
|
108
|
+
if (foundRepeat && !touchedDocumentRoot) {
|
|
109
|
+
focusTrapDetectedAt = step;
|
|
110
|
+
focusTrapFingerprint = stop.fingerprint;
|
|
111
|
+
focusTrapRecentFingerprints = [...recentStops.map(previous => previous.fingerprint), stop.fingerprint];
|
|
112
|
+
stop.issues.push('possible-focus-trap');
|
|
113
|
+
await maybeCaptureIssueScreenshot(options, callbacks, screenshots, `focus-trap-${step}`);
|
|
114
|
+
if (options.stopOnCycle)
|
|
115
|
+
shouldStopOnCycle = true;
|
|
116
|
+
}
|
|
117
|
+
stops.push(stop);
|
|
118
|
+
if (shouldStopOnCycle)
|
|
119
|
+
break;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
stops.push(stop);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
stops,
|
|
126
|
+
uniqueFingerprints: uniqueFingerprints.size,
|
|
127
|
+
skipLink: {
|
|
128
|
+
found: skipLinkStep !== null,
|
|
129
|
+
step: skipLinkStep,
|
|
130
|
+
activated: skipLinkActivated,
|
|
131
|
+
activation: skipLinkActivation,
|
|
132
|
+
},
|
|
133
|
+
focusVisibilityIssues: stops.filter(stop => stop.issues.includes('no-visible-focus-indicator')),
|
|
134
|
+
focusJumpIssues: stops.filter(stop => stop.issues.includes('focus-jump-or-not-visible')),
|
|
135
|
+
focusTrap: {
|
|
136
|
+
detected: focusTrapDetectedAt !== null,
|
|
137
|
+
step: focusTrapDetectedAt,
|
|
138
|
+
cycleFingerprint: focusTrapFingerprint,
|
|
139
|
+
recentFingerprints: focusTrapRecentFingerprints,
|
|
140
|
+
},
|
|
141
|
+
screenshots,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const auditKeyboardSchema = z.object({
|
|
145
|
+
maxTabs: z.number().int().min(1).max(200).default(50).describe('Maximum number of Tab keypresses.'),
|
|
146
|
+
includeShiftTab: z.boolean().default(false).describe('Alternate with Shift+Tab during the sequence.'),
|
|
147
|
+
stopOnCycle: z.boolean().default(true).describe('Stop once a focus cycle/trap is detected.'),
|
|
148
|
+
cycleWindow: z.number().int().min(2).max(50).default(10).describe('Recent-window size used for cycle detection.'),
|
|
149
|
+
checkSkipLink: z.boolean().default(true).describe('Check early focus stops for a skip link.'),
|
|
150
|
+
skipLinkMaxTabs: z.number().int().min(1).max(20).default(3).describe('Maximum early steps to look for a skip link.'),
|
|
151
|
+
activateSkipLink: z.boolean().default(false).describe('Press Enter when skip link is found.'),
|
|
152
|
+
checkFocusTrap: z.boolean().default(true).describe('Detect likely focus trap/cycle.'),
|
|
153
|
+
checkFocusVisibility: z.boolean().default(true).describe('Check focus ring visibility heuristic.'),
|
|
154
|
+
checkFocusJumps: z.boolean().default(true).describe('Detect large scroll jumps and invisible focus.'),
|
|
155
|
+
jumpScrollThresholdPx: z.number().int().min(1).default(800).describe('Scroll delta threshold for jump detection.'),
|
|
156
|
+
screenshotOnIssue: z.boolean().default(false).describe('Capture screenshots for detected issues.'),
|
|
157
|
+
maxIssueScreenshots: z.number().int().min(1).max(20).default(3).describe('Maximum screenshots saved when screenshotOnIssue=true.'),
|
|
158
|
+
reportFile: z.string().optional().describe('Output JSON report file name.'),
|
|
159
|
+
});
|
|
160
|
+
const auditKeyboard = defineTabTool({
|
|
161
|
+
capability: 'core',
|
|
162
|
+
schema: {
|
|
163
|
+
name: 'audit_keyboard',
|
|
164
|
+
title: 'Audit keyboard focus flow',
|
|
165
|
+
description: 'Audit keyboard tab order, focus visibility, jumps, skip links, and focus traps.',
|
|
166
|
+
inputSchema: auditKeyboardSchema,
|
|
167
|
+
type: 'destructive',
|
|
168
|
+
},
|
|
169
|
+
handle: async (tab, params, response) => {
|
|
170
|
+
const getActiveElementInfo = async () => {
|
|
171
|
+
return await tab.page.evaluate(() => {
|
|
172
|
+
const current = document.activeElement;
|
|
173
|
+
const scrollX = window.scrollX;
|
|
174
|
+
const scrollY = window.scrollY;
|
|
175
|
+
if (!current) {
|
|
176
|
+
return {
|
|
177
|
+
role: null,
|
|
178
|
+
name: null,
|
|
179
|
+
tagName: null,
|
|
180
|
+
id: null,
|
|
181
|
+
href: null,
|
|
182
|
+
text: null,
|
|
183
|
+
boundingBox: null,
|
|
184
|
+
inViewport: false,
|
|
185
|
+
hasVisibleIndicator: false,
|
|
186
|
+
scrollX,
|
|
187
|
+
scrollY,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const role = current.getAttribute('role') || current.tagName.toLowerCase();
|
|
191
|
+
const name = current.getAttribute('aria-label')
|
|
192
|
+
|| current.getAttribute('aria-labelledby') && document.getElementById(current.getAttribute('aria-labelledby'))?.textContent?.trim()
|
|
193
|
+
|| current.getAttribute('title')
|
|
194
|
+
|| (current instanceof HTMLInputElement || current instanceof HTMLTextAreaElement ? current.labels?.[0]?.textContent?.trim() : null)
|
|
195
|
+
|| current.textContent?.trim().slice(0, 200)
|
|
196
|
+
|| null;
|
|
197
|
+
const rect = current.getBoundingClientRect();
|
|
198
|
+
const style = window.getComputedStyle(current);
|
|
199
|
+
const outlineWidth = Number.parseFloat(style.outlineWidth || '0');
|
|
200
|
+
const hasOutline = outlineWidth > 0 && style.outlineStyle !== 'none';
|
|
201
|
+
const hasBoxShadow = style.boxShadow !== 'none';
|
|
202
|
+
const inViewport = rect.width > 0
|
|
203
|
+
&& rect.height > 0
|
|
204
|
+
&& rect.bottom >= 0
|
|
205
|
+
&& rect.right >= 0
|
|
206
|
+
&& rect.top <= window.innerHeight
|
|
207
|
+
&& rect.left <= window.innerWidth;
|
|
208
|
+
return {
|
|
209
|
+
role,
|
|
210
|
+
name: name ? name.slice(0, 200) : null,
|
|
211
|
+
tagName: current.tagName,
|
|
212
|
+
id: current.id || null,
|
|
213
|
+
href: current instanceof HTMLAnchorElement ? current.href : null,
|
|
214
|
+
text: current.textContent?.trim().slice(0, 200) || null,
|
|
215
|
+
boundingBox: rect.width > 0 || rect.height > 0 ? {
|
|
216
|
+
x: rect.x,
|
|
217
|
+
y: rect.y,
|
|
218
|
+
width: rect.width,
|
|
219
|
+
height: rect.height,
|
|
220
|
+
} : null,
|
|
221
|
+
inViewport,
|
|
222
|
+
hasVisibleIndicator: hasOutline || hasBoxShadow,
|
|
223
|
+
scrollX,
|
|
224
|
+
scrollY,
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
const captureScreenshot = async (label) => {
|
|
229
|
+
const fileName = await tab.context.outputFile(`${sanitizeForFilePath(label)}-${safeIsoTimestampForFileName()}.png`);
|
|
230
|
+
await tab.page.screenshot({ path: fileName, fullPage: true });
|
|
231
|
+
return fileName;
|
|
232
|
+
};
|
|
233
|
+
const result = await runKeyboardFocusAudit({
|
|
234
|
+
maxTabs: params.maxTabs,
|
|
235
|
+
includeShiftTab: params.includeShiftTab,
|
|
236
|
+
stopOnCycle: params.stopOnCycle,
|
|
237
|
+
cycleWindow: params.cycleWindow,
|
|
238
|
+
checkSkipLink: params.checkSkipLink,
|
|
239
|
+
skipLinkMaxTabs: params.skipLinkMaxTabs,
|
|
240
|
+
activateSkipLink: params.activateSkipLink,
|
|
241
|
+
checkFocusTrap: params.checkFocusTrap,
|
|
242
|
+
checkFocusVisibility: params.checkFocusVisibility,
|
|
243
|
+
checkFocusJumps: params.checkFocusJumps,
|
|
244
|
+
jumpScrollThresholdPx: params.jumpScrollThresholdPx,
|
|
245
|
+
screenshotOnIssue: params.screenshotOnIssue,
|
|
246
|
+
maxIssueScreenshots: params.maxIssueScreenshots,
|
|
247
|
+
}, {
|
|
248
|
+
pressKey: async (key) => {
|
|
249
|
+
await tab.waitForCompletion(async () => {
|
|
250
|
+
await tab.page.keyboard.press(key);
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
getActiveElementInfo,
|
|
254
|
+
getCurrentUrl: async () => tab.page.url(),
|
|
255
|
+
goBack: async () => {
|
|
256
|
+
await tab.page.goBack({ waitUntil: 'domcontentloaded' });
|
|
257
|
+
},
|
|
258
|
+
captureScreenshot,
|
|
259
|
+
});
|
|
260
|
+
const report = {
|
|
261
|
+
version: 'v1',
|
|
262
|
+
metadata: {
|
|
263
|
+
url: tab.page.url(),
|
|
264
|
+
options: params,
|
|
265
|
+
generatedAt: new Date().toISOString(),
|
|
266
|
+
},
|
|
267
|
+
...result,
|
|
268
|
+
};
|
|
269
|
+
const reportFileName = sanitizeForFilePath(params.reportFile ?? `audit-keyboard-${safeIsoTimestampForFileName()}.json`);
|
|
270
|
+
const reportPath = await tab.context.outputFile(reportFileName);
|
|
271
|
+
await fs.promises.writeFile(reportPath, JSON.stringify(report, null, 2), 'utf-8');
|
|
272
|
+
const focusVisibilityPreview = result.focusVisibilityIssues.slice(0, 10).map(stop => (`- Step ${stop.step} (${stop.key}): ${stop.role ?? 'unknown-role'} ${stop.name ?? ''}`.trim()));
|
|
273
|
+
const focusJumpPreview = result.focusJumpIssues.slice(0, 10).map(stop => (`- Step ${stop.step}: deltaY=${stop.scrollDeltaY}, inViewport=${stop.inViewport}`));
|
|
274
|
+
const skipLinkResult = result.skipLink.found
|
|
275
|
+
? `found at step ${result.skipLink.step}${result.skipLink.activated ? ', activated' : ''}`
|
|
276
|
+
: 'not found';
|
|
277
|
+
response.addCode('// Pressed Tab/Shift+Tab and audited focus behavior heuristics.');
|
|
278
|
+
response.addResult([
|
|
279
|
+
`Unique focus stops: ${result.uniqueFingerprints}`,
|
|
280
|
+
`Skip link: ${skipLinkResult}`,
|
|
281
|
+
`No visible focus indicator: ${result.focusVisibilityIssues.length}`,
|
|
282
|
+
...(focusVisibilityPreview.length ? focusVisibilityPreview : ['- None']),
|
|
283
|
+
'',
|
|
284
|
+
`Focus trap detected: ${result.focusTrap.detected ? `yes (step ${result.focusTrap.step})` : 'no'}`,
|
|
285
|
+
`Focus jumps: ${result.focusJumpIssues.length}`,
|
|
286
|
+
...(focusJumpPreview.length ? focusJumpPreview : ['- None']),
|
|
287
|
+
...(result.screenshots.length ? ['', 'Issue screenshots:', ...result.screenshots.map(path => `- ${path}`)] : []),
|
|
288
|
+
'',
|
|
289
|
+
`JSON report: ${reportPath}`,
|
|
290
|
+
].join('\n'));
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
export default [
|
|
294
|
+
auditKeyboard,
|
|
295
|
+
];
|
|
296
|
+
//# sourceMappingURL=auditKeyboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditKeyboard.js","sourceRoot":"","sources":["../../src/tools/auditKeyboard.ts"],"names":[],"mappings":"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"}
|