mirror of
https://github.com/SawyerHood/dev-browser.git
synced 2026-09-20 13:44:44 +08:00
131 lines
6.0 KiB
Plaintext
131 lines
6.0 KiB
Plaintext
LLM USAGE GUIDE:
|
|
Write small, focused scripts. Each script should do ONE thing: navigate, click, fill, or check.
|
|
End each script by logging the state you need for the next decision.
|
|
Use descriptive page names like "login", "checkout", or "results" instead of "page1".
|
|
Named pages from browser.getPage("name") persist between script runs, so you usually do not need to re-navigate.
|
|
Inside page.evaluate(...), write plain JavaScript only - no TypeScript syntax in the browser context.
|
|
On Windows/PowerShell, use here-strings to pipe multiline scripts:
|
|
@"
|
|
const page = await browser.getPage("main");
|
|
console.log(await page.title());
|
|
"@ | dev-browser --connect
|
|
|
|
Quick inspection:
|
|
dev-browser --connect <<'EOF'
|
|
const tabs = await browser.listPages();
|
|
console.log(JSON.stringify(tabs, null, 2));
|
|
EOF
|
|
|
|
dev-browser --connect <<'EOF'
|
|
const page = await browser.getPage("TARGET_ID_HERE");
|
|
console.log(JSON.stringify({
|
|
url: page.url(),
|
|
title: await page.title(),
|
|
}, null, 2));
|
|
EOF
|
|
|
|
AI snapshots for element discovery:
|
|
dev-browser <<'EOF'
|
|
const page = await browser.getPage("main");
|
|
const result = await page.snapshotForAI();
|
|
console.log(result.full);
|
|
// Returns { full: string, incremental?: string }.
|
|
// Optional args: { track?: string, depth?: number, timeout?: number }.
|
|
// Read result.full to identify the right element.
|
|
// Then interact with it using Playwright:
|
|
// await page.getByRole("button", { name: "Continue" }).click();
|
|
// Re-run page.snapshotForAI({ track: "main" }) after the page changes.
|
|
EOF
|
|
|
|
Choosing your approach:
|
|
Unknown pages: use page.snapshotForAI() first to discover the page, then interact based on what you find.
|
|
Known pages/selectors: skip the snapshot and use direct Playwright selectors like page.click(), page.fill(), or page.locator() for faster, more reliable automation.
|
|
|
|
Screenshots for visual state:
|
|
dev-browser <<'EOF'
|
|
const page = await browser.getPage("main");
|
|
const buf = await page.screenshot();
|
|
const path = await saveScreenshot(buf, "debug.png");
|
|
console.log(path);
|
|
EOF
|
|
|
|
Waiting patterns:
|
|
dev-browser <<'EOF'
|
|
const page = await browser.getPage("search-results");
|
|
await page.waitForSelector(".results");
|
|
await page.waitForURL("**/success");
|
|
console.log(JSON.stringify({
|
|
url: page.url(),
|
|
title: await page.title(),
|
|
}, null, 2));
|
|
EOF
|
|
|
|
Dev server navigation:
|
|
For local dev servers (Next.js, Vite, etc.), prefer:
|
|
await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
The default "load" wait can hang on HMR, streaming, or other long-lived dev-server connections.
|
|
Use "load" only when you specifically need every subresource to finish loading.
|
|
|
|
Error recovery:
|
|
If a script fails, the page usually stays where it stopped.
|
|
Reconnect to the same page name, take a screenshot, and log the URL/title:
|
|
dev-browser <<'EOF'
|
|
const page = await browser.getPage("checkout");
|
|
const path = await saveScreenshot(await page.screenshot(), "debug.png");
|
|
console.log(JSON.stringify({
|
|
screenshot: path,
|
|
url: page.url(),
|
|
title: await page.title(),
|
|
}, null, 2));
|
|
EOF
|
|
|
|
Common Playwright Page methods:
|
|
page.goto(url, { waitUntil: "domcontentloaded" })
|
|
Navigate to a URL; prefer this on dev servers
|
|
page.title() Get the current page title
|
|
page.url() Get the current URL
|
|
page.snapshotForAI(options) Get an AI-optimized snapshot; returns { full, incremental? }
|
|
Options: { track?: string, depth?: number, timeout?: number }
|
|
page.getByRole(role, { name }) Target elements discovered from the snapshot
|
|
page.textContent(selector) Get the text content of an element
|
|
page.innerHTML(selector) Get the inner HTML of an element
|
|
page.fill(selector, value) Fill an input field
|
|
page.click(selector) Click an element
|
|
page.type(selector, text) Type text character by character
|
|
page.press(selector, key) Press a key such as Enter or Tab
|
|
page.waitForSelector(selector) Wait for an element to appear
|
|
page.waitForURL(url) Wait for navigation to a URL
|
|
page.screenshot() Capture a screenshot buffer; save it with saveScreenshot(...)
|
|
page.$$eval(selector, fn) Run a function on all matching elements
|
|
page.$eval(selector, fn) Run a function on the first matching element
|
|
page.evaluate(fn) Run JavaScript in the page context (plain JS only)
|
|
page.locator(selector) Create a locator for chained actions
|
|
|
|
Connecting to a running Chrome instance:
|
|
Auto-discover Chrome with debugging enabled:
|
|
dev-browser --connect <<'EOF'
|
|
const page = await browser.getPage("main");
|
|
console.log(await page.title());
|
|
EOF
|
|
|
|
Connect to a specific CDP endpoint:
|
|
dev-browser --connect http://localhost:9222 <<'EOF'
|
|
const page = await browser.getPage("main");
|
|
console.log(await page.title());
|
|
EOF
|
|
|
|
To launch Chrome with debugging enabled:
|
|
chrome.exe --remote-debugging-port=9222
|
|
google-chrome --remote-debugging-port=9222
|
|
|
|
Or visit chrome://inspect/#remote-debugging to configure.
|
|
|
|
Tips:
|
|
- Use console.log(JSON.stringify(...)) for structured output.
|
|
- Prefer page.snapshotForAI() for structure; use screenshots when visual layout or styling matters.
|
|
- Keep page names stable across scripts so you can resume work after failures.
|
|
- Each --browser name maps to a separate daemon-managed browser instance.
|
|
- Use --connect to attach to an existing browser; omit the URL to auto-discover Chrome with debugging enabled.
|
|
- Use short timeouts (--timeout 10) so scripts fail fast instead of hanging on missing elements.
|
|
- Add --headless for unattended automation; omit it when you want to watch the browser window.
|