fix: add 10-second timeout to accessibility snapshots
Prevents infinite hangs when _snapshotForAI() blocks on complex pages, SVG files, or file:// URLs. Returns a helpful message suggesting browser_take_screenshot as an alternative.
This commit is contained in:
parent
8e0953abc4
commit
a65f00667a
31
src/tab.ts
31
src/tab.ts
@ -30,6 +30,33 @@ type PageEx = playwright.Page & {
|
|||||||
_snapshotForAI: () => Promise<string>;
|
_snapshotForAI: () => Promise<string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SNAPSHOT_TIMEOUT_MS = 10000; // 10 seconds
|
||||||
|
|
||||||
|
async function snapshotWithTimeout(page: playwright.Page): Promise<string> {
|
||||||
|
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
|
||||||
|
const timeoutPromise = new Promise<string>((resolve) => {
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
resolve(
|
||||||
|
`[Snapshot timed out after ${SNAPSHOT_TIMEOUT_MS / 1000} seconds]\n` +
|
||||||
|
`This can happen with complex pages, SVG files, or file:// URLs.\n` +
|
||||||
|
`Use browser_take_screenshot to view the page, or disable auto-snapshots with browser_configure_snapshots.`
|
||||||
|
);
|
||||||
|
}, SNAPSHOT_TIMEOUT_MS);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await Promise.race([
|
||||||
|
(page as PageEx)._snapshotForAI(),
|
||||||
|
timeoutPromise,
|
||||||
|
]);
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
if (timeoutId)
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const TabEvents = {
|
export const TabEvents = {
|
||||||
modalState: 'modalState'
|
modalState: 'modalState'
|
||||||
};
|
};
|
||||||
@ -914,7 +941,7 @@ export class Tab extends EventEmitter<TabEventsInterface> {
|
|||||||
result.push(...this._listDownloadsMarkdown());
|
result.push(...this._listDownloadsMarkdown());
|
||||||
|
|
||||||
await this._raceAgainstModalStates(async () => {
|
await this._raceAgainstModalStates(async () => {
|
||||||
const snapshot = await (this.page as PageEx)._snapshotForAI();
|
const snapshot = await snapshotWithTimeout(this.page);
|
||||||
result.push(
|
result.push(
|
||||||
`### Page state`,
|
`### Page state`,
|
||||||
`- Page URL: ${this.page.url()}`,
|
`- Page URL: ${this.page.url()}`,
|
||||||
@ -958,7 +985,7 @@ export class Tab extends EventEmitter<TabEventsInterface> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async refLocators(params: { element: string, ref: string }[]): Promise<playwright.Locator[]> {
|
async refLocators(params: { element: string, ref: string }[]): Promise<playwright.Locator[]> {
|
||||||
const snapshot = await (this.page as PageEx)._snapshotForAI();
|
const snapshot = await snapshotWithTimeout(this.page);
|
||||||
return params.map(param => {
|
return params.map(param => {
|
||||||
if (!snapshot.includes(`[ref=${param.ref}]`))
|
if (!snapshot.includes(`[ref=${param.ref}]`))
|
||||||
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
|
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user