Files
english/.opencode/skills/chrome-devtools/scripts/select-ref.js
2026-04-12 01:06:31 +07:00

133 lines
3.8 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Select and interact with elements by ref from ARIA snapshot
* Usage: node select-ref.js --ref e5 --action click
* node select-ref.js --ref e10 --action fill --value "text"
* node select-ref.js --ref e3 --action screenshot --output element.png
*
* Actions:
* click - Click the element
* fill - Fill input with --value
* screenshot - Take screenshot of element
* text - Get text content
* focus - Focus the element
* hover - Hover over element
*
* Refs are obtained from aria-snapshot.js output (e.g., [ref=e5])
*
* Session behavior:
* By default, browser stays running for session persistence
* Use --close true to fully close browser
*/
import { getBrowser, getPage, closeBrowser, disconnectBrowser, parseArgs, outputJSON, outputError } from './lib/browser.js';
import fs from 'fs/promises';
import path from 'path';
async function selectRef() {
const args = parseArgs(process.argv.slice(2));
if (!args.ref) {
outputError(new Error('--ref is required (e.g., --ref e5)'));
return;
}
if (!args.action) {
outputError(new Error('--action is required (click, fill, screenshot, text, focus, hover)'));
return;
}
try {
const browser = await getBrowser({
headless: args.headless
});
const page = await getPage(browser);
// Get element by ref from window.__chromeDevToolsRefs
const element = await page.evaluateHandle((ref) => {
const refs = window.__chromeDevToolsRefs;
if (!refs) {
throw new Error('No refs available. Run aria-snapshot.js first to generate refs.');
}
const el = refs.get(ref);
if (!el) {
throw new Error(`Ref "${ref}" not found. Available refs: ${Array.from(refs.keys()).join(', ')}`);
}
return el;
}, args.ref);
const elementHandle = element.asElement();
if (!elementHandle) {
throw new Error(`Could not get element handle for ref "${args.ref}"`);
}
let result = {
success: true,
ref: args.ref,
action: args.action
};
// Perform action
switch (args.action) {
case 'click':
await elementHandle.click();
result.message = 'Element clicked';
break;
case 'fill':
if (!args.value && args.value !== '') {
throw new Error('--value is required for fill action');
}
await elementHandle.click({ clickCount: 3 }); // Select all
await elementHandle.type(args.value);
result.message = 'Element filled';
result.value = args.value;
break;
case 'screenshot':
if (!args.output) {
throw new Error('--output is required for screenshot action');
}
const outputDir = path.dirname(args.output);
await fs.mkdir(outputDir, { recursive: true });
await elementHandle.screenshot({ path: args.output });
result.output = path.resolve(args.output);
result.message = 'Screenshot saved';
break;
case 'text':
const text = await page.evaluate(el => el.textContent?.trim(), elementHandle);
result.text = text;
break;
case 'focus':
await elementHandle.focus();
result.message = 'Element focused';
break;
case 'hover':
await elementHandle.hover();
result.message = 'Hovering over element';
break;
default:
throw new Error(`Unknown action: ${args.action}. Valid actions: click, fill, screenshot, text, focus, hover`);
}
outputJSON(result);
// Default: disconnect to keep browser running for session persistence
// Use --close true to fully close browser
if (args.close === 'true') {
await closeBrowser();
} else {
await disconnectBrowser();
}
process.exit(0);
} catch (error) {
outputError(error);
}
}
selectRef();