UNPKG

playwright-advanced-ml-healer

Version:

Advanced AI-powered self-healing selectors for Playwright with 19+ healing types, neural networks, machine learning models, and Global DOM Learning ML Model

626 lines 24.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GlobalDOMLearningML = void 0; /** * Global DOM Learning ML Model * * This model crawls global websites, analyzes DOM patterns, and learns * from real-world element structures to continuously improve healing capabilities. */ class GlobalDOMLearningML { constructor(page) { this.page = page; this.browser = null; this.context = null; this.knowledgeBase = new Map(); this.learningHistory = []; // Configuration this.config = { maxWebsites: 1000, maxPagesPerWebsite: 10, maxElementsPerPage: 500, learningRate: 0.1, confidenceThreshold: 0.7, crawlDelay: 1000, // 1 second between requests timeout: 30000, // 30 seconds per page userAgents: [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36' ] }; } /** * Initialize the global learning system */ async initialize() { try { console.log('🌍 Initializing Global DOM Learning ML Model...'); // Initialize browser context for crawling this.context = await this.page.context().browser()?.newContext({ userAgent: this.getRandomUserAgent(), viewport: { width: 1920, height: 1080 }, deviceScaleFactor: 1, isMobile: false, hasTouch: false, javaScriptEnabled: true, acceptDownloads: false, ignoreHTTPSErrors: true }); console.log('✅ Global DOM Learning ML Model initialized successfully'); } catch (error) { console.error('❌ Failed to initialize Global DOM Learning ML Model:', error); } } /** * Start global learning from diverse websites */ async startGlobalLearning() { console.log('🚀 Starting Global DOM Learning...'); const websites = this.getDiverseWebsiteList(); let learnedCount = 0; for (const website of websites) { if (learnedCount >= this.config.maxWebsites) break; try { console.log(`🌐 Learning from: ${website}`); await this.learnFromWebsite(website); learnedCount++; // Delay between websites to be respectful await this.delay(this.config.crawlDelay); } catch (error) { console.error(`❌ Failed to learn from ${website}:`, error); } } console.log(`🎓 Global learning completed! Learned from ${learnedCount} websites`); await this.saveKnowledgeBase(); } /** * Learn from a specific website */ async learnFromWebsite(website) { if (!this.context) return; const page = await this.context.newPage(); try { // Navigate to website await page.goto(website, { waitUntil: 'domcontentloaded', timeout: this.config.timeout }); // Learn from homepage await this.learnFromPage(page, website, 'homepage'); // Find and learn from additional pages const additionalPages = await this.discoverAdditionalPages(page); for (let i = 0; i < Math.min(additionalPages.length, this.config.maxPagesPerWebsite - 1); i++) { try { await page.goto(additionalPages[i], { waitUntil: 'domcontentloaded', timeout: this.config.timeout }); await this.learnFromPage(page, website, `page-${i + 1}`); } catch (error) { console.error(`Failed to learn from additional page: ${additionalPages[i]}`); } } } catch (error) { console.error(`Failed to learn from website: ${website}`); } finally { await page.close(); } } /** * Learn from a specific page */ async learnFromPage(page, website, pageType) { try { // Extract DOM patterns const domPatterns = await this.extractDOMPatterns(page); // Analyze element structures const elementStructures = await this.analyzeElementStructures(page); // Learn form patterns const formPatterns = await this.learnFormPatterns(page); // Learn navigation patterns const navigationPatterns = await this.learnNavigationPatterns(page); // Learn button patterns const buttonPatterns = await this.learnButtonPatterns(page); // Learn input patterns const inputPatterns = await this.learnInputPatterns(page); // Store learned patterns const learningData = { website, pageType, timestamp: Date.now(), domPatterns, elementStructures, formPatterns, navigationPatterns, buttonPatterns, inputPatterns, metadata: { url: page.url(), title: await page.title(), domain: new URL(page.url()).hostname } }; this.learningHistory.push({ website, patterns: [learningData], timestamp: Date.now(), success: true }); // Update knowledge base this.updateKnowledgeBase(learningData); console.log(`✅ Learned from ${website} - ${pageType}`); } catch (error) { console.error(`Failed to learn from page: ${page.url()}`); } } /** * Extract DOM patterns from a page */ async extractDOMPatterns(page) { return await page.evaluate(() => { const patterns = []; // Analyze document structure const body = document.body; if (body) { // Count element types const elementCounts = {}; const allElements = body.querySelectorAll('*'); allElements.forEach(element => { const tagName = element.tagName.toLowerCase(); elementCounts[tagName] = (elementCounts[tagName] || 0) + 1; }); // Find common patterns const commonPatterns = Object.entries(elementCounts) .filter(([_, count]) => count > 5) .sort(([_, a], [__, b]) => b - a) .slice(0, 10); patterns.push({ type: 'element_distribution', data: commonPatterns, totalElements: allElements.length }); } // Analyze form patterns const forms = document.querySelectorAll('form'); if (forms.length > 0) { const formPatterns = Array.from(forms).map(form => ({ action: form.action, method: form.method, inputCount: form.querySelectorAll('input').length, buttonCount: form.querySelectorAll('button').length, hasLabels: form.querySelectorAll('label').length > 0 })); patterns.push({ type: 'form_patterns', data: formPatterns }); } // Analyze navigation patterns const navs = document.querySelectorAll('nav, [role="navigation"]'); if (navs.length > 0) { const navPatterns = Array.from(navs).map(nav => ({ hasList: nav.querySelector('ul, ol') !== null, hasLinks: nav.querySelectorAll('a').length, hasButtons: nav.querySelectorAll('button').length, depth: window.calculateDepth(nav) })); patterns.push({ type: 'navigation_patterns', data: navPatterns }); } return patterns; }); } /** * Analyze element structures */ async analyzeElementStructures(page) { return await page.evaluate(() => { const structures = []; // Analyze button structures const buttons = document.querySelectorAll('button, [role="button"], input[type="button"], input[type="submit"]'); if (buttons.length > 0) { const buttonStructures = Array.from(buttons).map(button => ({ tagName: button.tagName.toLowerCase(), type: button.getAttribute('type'), text: button.textContent?.trim(), className: button.className, id: button.id, hasIcon: button.querySelector('i, svg, img') !== null, size: window.getElementSize(button), position: window.getElementPosition(button) })); structures.push({ type: 'button_structures', data: buttonStructures }); } // Analyze input structures const inputs = document.querySelectorAll('input, textarea, select'); if (inputs.length > 0) { const inputStructures = Array.from(inputs).map(input => ({ tagName: input.tagName.toLowerCase(), type: input.getAttribute('type'), placeholder: input.getAttribute('placeholder'), name: input.getAttribute('name'), id: input.id, className: input.className, hasLabel: window.hasAssociatedLabel(input), hasValidation: window.hasValidationAttributes(input) })); structures.push({ type: 'input_structures', data: inputStructures }); } return structures; }); } /** * Learn form patterns */ async learnFormPatterns(page) { return await page.evaluate(() => { const patterns = []; const forms = document.querySelectorAll('form'); forms.forEach(form => { const inputs = form.querySelectorAll('input, textarea, select'); const buttons = form.querySelectorAll('button, input[type="submit"]'); // Analyze input patterns const inputTypes = Array.from(inputs).map(input => ({ type: input.getAttribute('type') || 'text', name: input.getAttribute('name'), placeholder: input.getAttribute('placeholder'), required: input.hasAttribute('required'), pattern: input.getAttribute('pattern') })); // Analyze button patterns const buttonTypes = Array.from(buttons).map(button => ({ type: button.getAttribute('type') || 'button', text: button.textContent?.trim(), position: window.getElementPosition(button) })); patterns.push({ inputCount: inputs.length, buttonCount: buttons.length, inputTypes, buttonTypes, hasValidation: form.querySelector('[required], [pattern], [min], [max]') !== null }); }); return patterns; }); } /** * Learn navigation patterns */ async learnNavigationPatterns(page) { return await page.evaluate(() => { const patterns = []; const navs = document.querySelectorAll('nav, [role="navigation"], header, .nav, .navigation'); navs.forEach(nav => { const links = nav.querySelectorAll('a'); const buttons = nav.querySelectorAll('button'); const lists = nav.querySelectorAll('ul, ol'); patterns.push({ linkCount: links.length, buttonCount: buttons.length, listCount: lists.length, hasDropdown: nav.querySelector('.dropdown, [aria-expanded]') !== null, hasSearch: nav.querySelector('input[type="search"], .search') !== null, hasLogo: nav.querySelector('img[alt*="logo"], .logo') !== null }); }); return patterns; }); } /** * Learn button patterns */ async learnButtonPatterns(page) { return await page.evaluate(() => { const patterns = []; const buttons = document.querySelectorAll('button, [role="button"], input[type="button"], input[type="submit"]'); buttons.forEach(button => { const text = button.textContent?.trim(); const type = button.getAttribute('type'); const className = button.className; patterns.push({ text, type, className, hasIcon: button.querySelector('i, svg, img') !== null, isPrimary: className.includes('primary') || className.includes('btn-primary'), isSecondary: className.includes('secondary') || className.includes('btn-secondary'), isDanger: className.includes('danger') || className.includes('btn-danger'), size: window.getButtonSize(button) }); }); return patterns; }); } /** * Learn input patterns */ async learnInputPatterns(page) { return await page.evaluate(() => { const patterns = []; const inputs = document.querySelectorAll('input, textarea, select'); inputs.forEach(input => { const type = input.getAttribute('type'); const placeholder = input.getAttribute('placeholder'); const name = input.getAttribute('name'); const id = input.id; patterns.push({ type, placeholder, name, id, hasLabel: window.hasAssociatedLabel(input), isRequired: input.hasAttribute('required'), hasValidation: window.hasValidationAttributes(input), commonPatterns: window.findCommonInputPatterns(input) }); }); return patterns; }); } /** * Discover additional pages on a website */ async discoverAdditionalPages(page) { try { const links = await page.evaluate(() => { const anchors = document.querySelectorAll('a[href]'); const urls = []; anchors.forEach(anchor => { const href = anchor.getAttribute('href'); if (href && href.startsWith('/') && !href.includes('#')) { urls.push(href); } }); return [...new Set(urls)].slice(0, 20); // Limit to 20 unique internal pages }); const baseUrl = new URL(page.url()).origin; return links.map(link => baseUrl + link); } catch (error) { return []; } } /** * Update knowledge base with new learning data */ updateKnowledgeBase(learningData) { const domain = learningData.metadata.domain; if (!this.knowledgeBase.has(domain)) { this.knowledgeBase.set(domain, { patterns: [], elementStructures: [], formPatterns: [], navigationPatterns: [], buttonPatterns: [], inputPatterns: [], lastUpdated: Date.now(), visitCount: 0 }); } const domainData = this.knowledgeBase.get(domain); domainData.patterns.push(learningData.domPatterns); domainData.elementStructures.push(learningData.elementStructures); domainData.formPatterns.push(learningData.formPatterns); domainData.navigationPatterns.push(learningData.navigationPatterns); domainData.buttonPatterns.push(learningData.buttonPatterns); domainData.inputPatterns.push(learningData.inputPatterns); domainData.lastUpdated = Date.now(); domainData.visitCount++; // Keep only recent data (last 10 visits) if (domainData.patterns.length > 10) { domainData.patterns = domainData.patterns.slice(-10); domainData.elementStructures = domainData.elementStructures.slice(-10); domainData.formPatterns = domainData.formPatterns.slice(-10); domainData.navigationPatterns = domainData.navigationPatterns.slice(-10); domainData.buttonPatterns = domainData.buttonPatterns.slice(-10); domainData.inputPatterns = domainData.inputPatterns.slice(-10); } } /** * Get diverse website list for learning */ getDiverseWebsiteList() { return [ // E-commerce 'https://www.amazon.com', 'https://www.ebay.com', 'https://www.walmart.com', 'https://www.target.com', 'https://www.bestbuy.com', // Social Media 'https://www.facebook.com', 'https://www.twitter.com', 'https://www.instagram.com', 'https://www.linkedin.com', 'https://www.youtube.com', // News & Media 'https://www.bbc.com', 'https://www.cnn.com', 'https://www.nytimes.com', 'https://www.reuters.com', 'https://www.theguardian.com', // Technology 'https://www.github.com', 'https://www.stackoverflow.com', 'https://www.microsoft.com', 'https://www.apple.com', 'https://www.google.com', // Banking & Finance 'https://www.chase.com', 'https://www.bankofamerica.com', 'https://www.wellsfargo.com', 'https://www.paypal.com', 'https://www.stripe.com', // Travel 'https://www.booking.com', 'https://www.expedia.com', 'https://www.airbnb.com', 'https://www.kayak.com', 'https://www.tripadvisor.com', // Education 'https://www.coursera.org', 'https://www.edx.org', 'https://www.udemy.com', 'https://www.khanacademy.org', 'https://www.mit.edu', // Healthcare 'https://www.mayoclinic.org', 'https://www.webmd.com', 'https://www.healthline.com', 'https://www.medlineplus.gov', 'https://www.cdc.gov', // Government 'https://www.usa.gov', 'https://www.whitehouse.gov', 'https://www.congress.gov', 'https://www.supremecourt.gov', 'https://www.irs.gov', // Entertainment 'https://www.netflix.com', 'https://www.spotify.com', 'https://www.hulu.com', 'https://www.disneyplus.com', 'https://www.hbomax.com' ]; } /** * Get random user agent for crawling */ getRandomUserAgent() { return this.config.userAgents[Math.floor(Math.random() * this.config.userAgents.length)]; } /** * Save knowledge base to persistent storage */ async saveKnowledgeBase() { try { // Convert Map to object for storage const knowledgeData = Object.fromEntries(this.knowledgeBase); // Save to file or database // This would integrate with your existing storage system console.log('💾 Knowledge base saved successfully'); } catch (error) { console.error('❌ Failed to save knowledge base:', error); } } /** * Get learned patterns for a specific domain */ getLearnedPatterns(domain) { return this.knowledgeBase.get(domain) || null; } /** * Get global patterns across all domains */ getGlobalPatterns() { const globalPatterns = { buttonPatterns: [], inputPatterns: [], formPatterns: [], navigationPatterns: [] }; this.knowledgeBase.forEach((domainData, domain) => { globalPatterns.buttonPatterns.push(...domainData.buttonPatterns); globalPatterns.inputPatterns.push(...domainData.inputPatterns); globalPatterns.formPatterns.push(...domainData.formPatterns); globalPatterns.navigationPatterns.push(...domainData.navigationPatterns); }); return globalPatterns; } /** * Get learning statistics */ getLearningStats() { return { totalWebsites: this.knowledgeBase.size, totalLearningSessions: this.learningHistory.length, successfulSessions: this.learningHistory.filter(h => h.success).length, lastLearningSession: this.learningHistory[this.learningHistory.length - 1]?.timestamp, knowledgeBaseSize: Array.from(this.knowledgeBase.values()).reduce((acc, val) => acc + val.patterns.length, 0) }; } /** * Delay utility */ delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } exports.GlobalDOMLearningML = GlobalDOMLearningML; // Inject helper functions if (typeof window !== 'undefined') { window.calculateDepth = (element) => { let depth = 0; let current = element; while (current.parentElement) { depth++; current = current.parentElement; } return depth; }; window.getElementSize = (element) => { const rect = element.getBoundingClientRect(); return { width: rect.width, height: rect.height }; }; window.getElementPosition = (element) => { const rect = element.getBoundingClientRect(); return { x: rect.left, y: rect.top }; }; window.hasAssociatedLabel = (input) => { const id = input.getAttribute('id'); if (id) { return document.querySelector(`label[for="${id}"]`) !== null; } return input.closest('label') !== null; }; window.hasValidationAttributes = (input) => { return input.hasAttribute('required') || input.hasAttribute('pattern') || input.hasAttribute('min') || input.hasAttribute('max') || input.hasAttribute('minlength') || input.hasAttribute('maxlength'); }; window.findCommonInputPatterns = (input) => { const patterns = []; const type = input.getAttribute('type'); const placeholder = input.getAttribute('placeholder'); if (type === 'email' && placeholder?.toLowerCase().includes('email')) patterns.push('email_input'); if (type === 'password' && placeholder?.toLowerCase().includes('password')) patterns.push('password_input'); if (type === 'text' && placeholder?.toLowerCase().includes('name')) patterns.push('name_input'); if (type === 'tel' && placeholder?.toLowerCase().includes('phone')) patterns.push('phone_input'); return patterns; }; window.getButtonSize = (button) => { const className = button.className.toLowerCase(); if (className.includes('btn-lg') || className.includes('large')) return 'large'; if (className.includes('btn-sm') || className.includes('small')) return 'small'; return 'medium'; }; } //# sourceMappingURL=global-dom-learning-ml.js.map