accessibilitySnapshot({ page, searchString: /textarea|form/i })

This commit is contained in:
Tommy D. Rossi
2025-11-19 16:07:05 +01:00
parent 184da5e07c
commit 123b2d6b88
2 changed files with 68 additions and 5 deletions
+45 -3
View File
@@ -46,7 +46,11 @@ interface VMContext {
error: (...args: any[]) => void
debug: (...args: any[]) => void
}
accessibilitySnapshot: (page: Page) => Promise<string>
accessibilitySnapshot: (options: {
page: Page
searchString?: string | RegExp
contextLines?: number
}) => Promise<string>
resetPlaywright: () => Promise<{ page: Page; context: BrowserContext }>
require: NodeRequire
import: (specifier: string) => Promise<any>
@@ -223,14 +227,52 @@ server.tool(
},
}
const accessibilitySnapshot = async (targetPage: Page) => {
const accessibilitySnapshot = async (options: {
page: Page
searchString?: string | RegExp
contextLines?: number
}) => {
const { page: targetPage, searchString, contextLines = 10 } = options
if ((targetPage as any)._snapshotForAI) {
const snapshot = await (targetPage as any)._snapshotForAI()
const snapshotStr =
typeof snapshot === 'string'
? snapshot
: JSON.stringify(snapshot, null, 2)
return snapshotStr
if (!searchString) {
return snapshotStr
}
const lines = snapshotStr.split('\n')
const matches: { line: string; index: number }[] = []
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
let isMatch = false
if (searchString instanceof RegExp) {
isMatch = searchString.test(line)
} else {
isMatch = line.includes(searchString)
}
if (isMatch) {
matches.push({ line, index: i })
if (matches.length >= 10) break
}
}
if (matches.length === 0) {
return 'No matches found'
}
return matches
.map((m) => {
const start = Math.max(0, m.index - contextLines)
const end = Math.min(lines.length, m.index + contextLines + 1)
return lines.slice(start, end).join('\n')
})
.join('\n\n---\n\n')
}
throw new Error('accessibilitySnapshot is not available on this page')
}
+23 -2
View File
@@ -44,7 +44,7 @@ await state.localhostPage.bringToFront();
after you click a button or submit a form you ALWAYS have to then check what is the current state of the page. you cannot assume what happened after doing an action. instead run the following code to know what happened after the action:
`console.log('url:', page.url()); console.log(await accessibilitySnapshot(page).then(x => x.slice(0, 1000)));`
`console.log('url:', page.url()); console.log(await accessibilitySnapshot({ page }).then(x => x.slice(0, 1000)));`
if nothing happened you may need to wait before the action completes, using something like `page.waitForNavigation({timeout: 3000})` or `await page.waitForLoadState('networkidle', {timeout: 3000})`
@@ -59,7 +59,10 @@ always detach event listener you create at the end of a message using `page.remo
you have access to some functions in addition to playwright methods:
- `async accessibilitySnapshot(page)`: gets a human readable snapshot of clickable elements on the page. useful to see the overall structure of the page and what elements you can interact with
- `async accessibilitySnapshot({ page, searchString, contextLines })`: gets a human readable snapshot of clickable elements on the page. useful to see the overall structure of the page and what elements you can interact with.
- `page`: the page object to snapshot
- `searchString`: (optional) a string or regex to filter the snapshot. If provided, returns the first 10 matches with surrounding context
- `contextLines`: (optional) number of lines of context to show around each match (default: 10)
- `async resetPlaywright()`: recreates the CDP connection and resets the browser/page/context. Use this when the MCP stops responding, you get connection errors, assertion failures, or timeout issues. After calling this, the page and context variables are automatically updated in the execution environment. IMPORTANT: this completely resets the execution context, removing any custom properties you may have added to the global scope AND clearing all keys from the `state` object. Only `page`, `context`, `state` (empty), `console`, and utility functions will remain
To bring a tab to front and focus it, use the standard Playwright method `await page.bringToFront()`
@@ -88,6 +91,24 @@ Then you can use `page.locator(`aria-ref=${ref}`)` to get an element with a spec
IMPORTANT: notice that we do not add any quotes in `aria-ref`! it MUST be called without quotes
## finding specific elements with snapshot
You can use `searchString` to find specific elements in the snapshot without reading the whole page structure. This is useful for finding forms, textareas, or specific text.
Example: find a textarea or form using case-insensitive regex:
```js
const snapshot = await accessibilitySnapshot({ page, searchString: /textarea|form/i })
console.log(snapshot)
```
Example: find elements containing "Login":
```js
const snapshot = await accessibilitySnapshot({ page, searchString: "Login" })
console.log(snapshot)
```
## getting outputs of code execution
You can use `console.log` to print values you want to see in the tool call result. For seeing logs across runs you can store then in `state.logs` and then print them later, filtering and paginating them too.