UNPKG

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
/** * 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