ai-debug-local-mcp
Version:
🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
203 lines • 8.74 kB
JavaScript
/**
* Flutter Form Filler
* Intelligent form filling for Flutter web applications
*/
export class FlutterFormFiller {
/**
* Automatically detect form fields on the current page
*/
static async detectFormFields(elements) {
const fields = [];
// Common form field patterns
const fieldPatterns = [
{ pattern: /name|full name/i, type: 'text' },
{ pattern: /email|e-mail/i, type: 'email' },
{ pattern: /phone|mobile|cell/i, type: 'tel' },
{ pattern: /date|dob|birth/i, type: 'date' },
{ pattern: /number|amount|quantity/i, type: 'number' },
{ pattern: /state|country|select/i, type: 'select' },
{ pattern: /agree|terms|consent/i, type: 'checkbox' }
];
// Analyze elements to find form fields
elements.forEach(element => {
// Skip non-clickable elements (those without proper bounds)
if (element.bounds.width === 0 || element.bounds.height === 0)
return;
// Check if this looks like a form field
const label = element.label.toLowerCase();
// Match against patterns
for (const { pattern, type } of fieldPatterns) {
if (pattern.test(label)) {
fields.push({
label: element.label,
type: type,
required: label.includes('*') || label.includes('required')
});
break;
}
}
// Generic text field for unmatched labels
if (!fields.find(f => f.label === element.label) &&
(label.includes('field') || label.includes('input') || label.endsWith(':'))) {
fields.push({
label: element.label,
type: 'text',
required: label.includes('*') || label.includes('required')
});
}
});
return fields;
}
/**
* Fill a form with provided data
*/
static async fillForm(quantumDebugger, sessionId, formData) {
const session = quantumDebugger.getSession(sessionId);
if (!session) {
return { success: false, filledFields: [], errors: ['Session not found'] };
}
const filledFields = [];
const errors = [];
// Process each form field
for (const [fieldName, value] of Object.entries(formData)) {
try {
// console.log(`📝 Filling field: ${fieldName} with value: ${value}`);
// Determine the action based on value type
if (typeof value === 'boolean') {
// Checkbox or toggle
const result = await quantumDebugger.interact(sessionId, `toggle ${fieldName}`);
if (result.success) {
filledFields.push(fieldName);
}
else {
errors.push(`Failed to toggle ${fieldName}: ${result.error}`);
}
}
else if (typeof value === 'string' && value.includes('select:')) {
// Dropdown selection
const optionValue = value.replace('select:', '');
const result = await quantumDebugger.interact(sessionId, `select ${optionValue} from ${fieldName}`);
if (result.success) {
filledFields.push(fieldName);
}
else {
errors.push(`Failed to select ${optionValue} in ${fieldName}: ${result.error}`);
}
}
else {
// Text input
// First click on the field
const clickResult = await quantumDebugger.interact(sessionId, `click ${fieldName}`);
if (!clickResult.success) {
errors.push(`Failed to click on ${fieldName}: ${clickResult.error}`);
continue;
}
// Then type the value
const typeResult = await quantumDebugger.interact(sessionId, `type ${value} in ${fieldName}`);
if (typeResult.success) {
filledFields.push(fieldName);
}
else {
errors.push(`Failed to type in ${fieldName}: ${typeResult.error}`);
}
}
// Small delay between fields
await session.page.waitForTimeout(500);
}
catch (error) {
errors.push(`Error filling ${fieldName}: ${error}`);
}
}
return {
success: errors.length === 0,
filledFields,
errors
};
}
/**
* Generate sample data for detected form fields
*/
static generateSampleData(fields) {
const sampleData = {};
fields.forEach(field => {
const fieldName = field.label.replace(/[*:]/g, '').trim();
switch (field.type) {
case 'text':
if (field.label.toLowerCase().includes('name')) {
sampleData[fieldName] = field.label.toLowerCase().includes('first') ? 'John' :
field.label.toLowerCase().includes('last') ? 'Doe' : 'John Doe';
}
else if (field.label.toLowerCase().includes('address')) {
sampleData[fieldName] = '123 Main Street';
}
else if (field.label.toLowerCase().includes('city')) {
sampleData[fieldName] = 'Seattle';
}
else if (field.label.toLowerCase().includes('zip')) {
sampleData[fieldName] = '98101';
}
else {
sampleData[fieldName] = 'Sample Text';
}
break;
case 'email':
sampleData[fieldName] = 'test@example.com';
break;
case 'tel':
sampleData[fieldName] = '(206) 555-0123';
break;
case 'number':
sampleData[fieldName] = '42';
break;
case 'date':
sampleData[fieldName] = '2024-01-15';
break;
case 'select':
// For selects, we'll need to analyze available options
if (field.label.toLowerCase().includes('state')) {
sampleData[fieldName] = 'select:Washington';
}
else if (field.label.toLowerCase().includes('country')) {
sampleData[fieldName] = 'select:United States';
}
else {
sampleData[fieldName] = 'select:Option 1';
}
break;
case 'checkbox':
sampleData[fieldName] = true;
break;
}
});
return sampleData;
}
/**
* Submit the form
*/
static async submitForm(quantumDebugger, sessionId, submitButtonText = 'Submit') {
try {
// console.log(`🚀 Submitting form by clicking "${submitButtonText}" button...`);
const result = await quantumDebugger.interact(sessionId, `click ${submitButtonText} button`);
if (result.success) {
// Wait for form submission
const session = quantumDebugger.getSession(sessionId);
if (session) {
await session.page.waitForTimeout(2000);
// Check for success indicators
const pageContent = await session.page.content();
const hasSuccess = pageContent.toLowerCase().includes('success') ||
pageContent.toLowerCase().includes('thank you') ||
pageContent.toLowerCase().includes('submitted');
if (hasSuccess) {
// console.log('✅ Form submitted successfully!');
}
}
}
return { success: result.success, error: result.error };
}
catch (error) {
return { success: false, error: `Submit failed: ${error}` };
}
}
}
//# sourceMappingURL=flutter-form-filler.js.map