Files
2025-11-30 08:48:52 +08:00

73 lines
1.9 KiB
JavaScript

#!/usr/bin/env node
/**
* Fill form fields
* Usage: node fill.js --selector "#input" --value "text" [--url https://example.com]
* Supports both CSS and XPath selectors:
* - CSS: node fill.js --selector "#email" --value "user@example.com"
* - XPath: node fill.js --selector "//input[@type='email']" --value "user@example.com"
*/
import { getBrowser, getPage, closeBrowser, parseArgs, outputJSON, outputError } from './lib/browser.js';
import { parseSelector, waitForElement, typeIntoElement, enhanceError } from './lib/selector.js';
async function fill() {
const args = parseArgs(process.argv.slice(2));
if (!args.selector) {
outputError(new Error('--selector is required'));
return;
}
if (!args.value) {
outputError(new Error('--value is required'));
return;
}
try {
const browser = await getBrowser({
headless: args.headless !== 'false'
});
const page = await getPage(browser);
// Navigate if URL provided
if (args.url) {
await page.goto(args.url, {
waitUntil: args['wait-until'] || 'networkidle2'
});
}
// Parse and validate selector
const parsed = parseSelector(args.selector);
// Wait for element based on selector type
await waitForElement(page, parsed, {
visible: true,
timeout: parseInt(args.timeout || '5000')
});
// Type into element
await typeIntoElement(page, parsed, args.value, {
clear: args.clear === 'true',
delay: parseInt(args.delay || '0')
});
outputJSON({
success: true,
selector: args.selector,
value: args.value,
url: page.url()
});
if (args.close !== 'false') {
await closeBrowser();
}
} catch (error) {
// Enhance error message with troubleshooting tips
const enhanced = enhanceError(error, args.selector);
outputError(enhanced);
process.exit(1);
}
}
fill();