Add scrollToLoad and an absent variant of waitFor
scrollToLoad walks a progressively-loading list to the bottom before the steps that act on its items run. Stopping is two-part: no new matches appeared AND the container was already pinned to the bottom — counting alone stops early on a slow fetch. Hitting the scroll cap is reported rather than passed off as done, so a later step never works quietly on a partial list. The scrolling element is usually not the window. Lists like this live in a div with its own overflow, and scrolling the document does nothing at all, so the step walks up from a matched item to the ancestor that actually scrolls — overflow allows it and there is more content than fits — with containerSelector to name one outright when the guess is wrong. Verified against a page whose document also scrolls, which is the case that tells the two apart: it found the inner div and pulled 12 items up to 60 in 7 scrolls. waitFor gains `absent`, for waiting on something to go rather than arrive — a modal closing after a reset. It only accepts a genuine "selector matched nothing"; an unreachable extension looks the same from a distance and would otherwise satisfy the gate for the wrong reason, sending the next iteration into a page that still has the modal open. The locate queue carries a free-form options blob now, so a new kind of request stops meaning a new column each time. Also fixes a missing comma in the reset flow that broke the build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3ac9fe060f
commit
3cc7ddcc5c
@@ -14,6 +14,7 @@ export async function POST() {
|
||||
urlPattern: row.url_pattern,
|
||||
openUrl: row.open_url,
|
||||
navigateUrl: row.navigate_url,
|
||||
options: (() => { try { return JSON.parse(row.options); } catch { return {}; } })(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { corsJson, corsPreflight } from '../cors';
|
||||
/** Python enqueues "find this selector and tell me where it is on screen". */
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json() as { selector?: unknown; index?: unknown; urlPattern?: unknown; openUrl?: unknown; navigateUrl?: unknown };
|
||||
const body = await req.json() as { selector?: unknown; index?: unknown; urlPattern?: unknown; openUrl?: unknown; navigateUrl?: unknown; options?: unknown };
|
||||
if (typeof body.selector !== 'string' || !body.selector.trim()) {
|
||||
return corsJson({ error: '`selector` is required' }, { status: 400 });
|
||||
}
|
||||
@@ -13,8 +13,9 @@ export async function POST(req: NextRequest) {
|
||||
const urlPattern = typeof body.urlPattern === 'string' ? body.urlPattern : '';
|
||||
const openUrl = typeof body.openUrl === 'string' ? body.openUrl : '';
|
||||
const navigateUrl = typeof body.navigateUrl === 'string' ? body.navigateUrl : '';
|
||||
const options = body.options && typeof body.options === 'object' ? JSON.stringify(body.options) : '{}';
|
||||
|
||||
const row = createLocateRequest(body.selector.trim(), index, urlPattern, openUrl, navigateUrl);
|
||||
const row = createLocateRequest(body.selector.trim(), index, urlPattern, openUrl, navigateUrl, options);
|
||||
return corsJson({ id: row.id, status: row.status });
|
||||
} catch (err: any) {
|
||||
return corsJson({ error: err?.message ?? 'Failed to queue request' }, { status: 500 });
|
||||
|
||||
Reference in New Issue
Block a user