Spaces:
Sleeping
Sleeping
| """ | |
| 🤖 Fagun Browser Automation Testing Agent - Enhanced AI Testing Engine | |
| ==================================================================== | |
| Enhanced AI testing engine that aggressively finds errors, bugs, and issues | |
| with comprehensive test scenarios and intelligent bug detection. | |
| Author: Mejbaur Bahar Fagun | |
| Role: Software Engineer in Test | |
| LinkedIn: https://www.linkedin.com/in/mejbaur/ | |
| """ | |
| import asyncio | |
| import random | |
| import string | |
| from typing import List, Dict, Any, Optional | |
| from playwright.async_api import Page, Locator | |
| import logging | |
| from dataclasses import dataclass | |
| from enum import Enum | |
| logger = logging.getLogger(__name__) | |
| class BugSeverity(Enum): | |
| """Bug severity levels.""" | |
| CRITICAL = "critical" | |
| HIGH = "high" | |
| MEDIUM = "medium" | |
| LOW = "low" | |
| INFO = "info" | |
| class BugReport: | |
| """Bug report structure.""" | |
| title: str | |
| severity: BugSeverity | |
| description: str | |
| steps_to_reproduce: List[str] | |
| expected_behavior: str | |
| actual_behavior: str | |
| url: str | |
| element_info: Dict[str, Any] | |
| recommendations: List[str] | |
| class EnhancedAITestingEngine: | |
| """Enhanced AI testing engine with aggressive bug finding capabilities.""" | |
| def __init__(self): | |
| self.bugs_found: List[BugReport] = [] | |
| self.test_scenarios = self._load_test_scenarios() | |
| self.bug_patterns = self._load_bug_patterns() | |
| self.performance_thresholds = self._load_performance_thresholds() | |
| def _load_test_scenarios(self) -> Dict[str, List[Dict[str, Any]]]: | |
| """Load comprehensive test scenarios.""" | |
| return { | |
| "navigation": [ | |
| {"action": "rapid_navigation", "description": "Rapidly navigate between pages"}, | |
| {"action": "back_forward", "description": "Test browser back/forward buttons"}, | |
| {"action": "refresh_test", "description": "Test page refresh functionality"}, | |
| {"action": "url_manipulation", "description": "Test URL manipulation and direct access"} | |
| ], | |
| "form_testing": [ | |
| {"action": "empty_submission", "description": "Submit forms with empty fields"}, | |
| {"action": "invalid_data", "description": "Submit forms with invalid data"}, | |
| {"action": "sql_injection", "description": "Test for SQL injection vulnerabilities"}, | |
| {"action": "xss_attempts", "description": "Test for XSS vulnerabilities"}, | |
| {"action": "large_data", "description": "Submit forms with large amounts of data"}, | |
| {"action": "special_characters", "description": "Test with special characters"}, | |
| {"action": "unicode_testing", "description": "Test with Unicode characters"}, | |
| {"action": "script_injection", "description": "Test for script injection"} | |
| ], | |
| "ui_testing": [ | |
| {"action": "responsive_test", "description": "Test responsive design"}, | |
| {"action": "accessibility_test", "description": "Test accessibility features"}, | |
| {"action": "hover_effects", "description": "Test hover effects and interactions"}, | |
| {"action": "click_areas", "description": "Test clickable areas and buttons"}, | |
| {"action": "scroll_behavior", "description": "Test scrolling behavior"}, | |
| {"action": "zoom_testing", "description": "Test zoom functionality"}, | |
| {"action": "keyboard_navigation", "description": "Test keyboard navigation"} | |
| ], | |
| "performance": [ | |
| {"action": "load_time_test", "description": "Test page load times"}, | |
| {"action": "resource_loading", "description": "Test resource loading performance"}, | |
| {"action": "memory_usage", "description": "Monitor memory usage"}, | |
| {"action": "cpu_usage", "description": "Monitor CPU usage"}, | |
| {"action": "network_latency", "description": "Test network latency"} | |
| ], | |
| "security": [ | |
| {"action": "csrf_test", "description": "Test for CSRF vulnerabilities"}, | |
| {"action": "clickjacking", "description": "Test for clickjacking vulnerabilities"}, | |
| {"action": "session_management", "description": "Test session management"}, | |
| {"action": "authentication", "description": "Test authentication mechanisms"}, | |
| {"action": "authorization", "description": "Test authorization controls"} | |
| ] | |
| } | |
| def _load_bug_patterns(self) -> Dict[str, List[str]]: | |
| """Load bug detection patterns.""" | |
| return { | |
| "ui_bugs": [ | |
| "Element not visible", | |
| "Element not clickable", | |
| "Layout broken", | |
| "Text overflow", | |
| "Image not loading", | |
| "Button not responding", | |
| "Form validation missing", | |
| "Error message not displayed", | |
| "Loading state not handled", | |
| "Responsive design issues" | |
| ], | |
| "functional_bugs": [ | |
| "Function not working", | |
| "Data not saved", | |
| "Validation bypassed", | |
| "Error not handled", | |
| "State not maintained", | |
| "Navigation broken", | |
| "Search not working", | |
| "Filter not applied", | |
| "Sort not working", | |
| "Pagination broken" | |
| ], | |
| "performance_bugs": [ | |
| "Page load too slow", | |
| "Memory leak detected", | |
| "CPU usage high", | |
| "Network timeout", | |
| "Resource not optimized", | |
| "Caching issues", | |
| "Database slow query", | |
| "API response slow", | |
| "Image not optimized", | |
| "JavaScript blocking" | |
| ], | |
| "security_bugs": [ | |
| "SQL injection possible", | |
| "XSS vulnerability", | |
| "CSRF token missing", | |
| "Authentication bypass", | |
| "Authorization issue", | |
| "Data exposure", | |
| "Session hijacking", | |
| "Clickjacking possible", | |
| "Input not sanitized", | |
| "Error information leaked" | |
| ] | |
| } | |
| def _load_performance_thresholds(self) -> Dict[str, float]: | |
| """Load performance thresholds.""" | |
| return { | |
| "page_load_time": 3.0, # seconds | |
| "element_interaction_time": 1.0, # seconds | |
| "form_submission_time": 2.0, # seconds | |
| "navigation_time": 1.5, # seconds | |
| "memory_usage_mb": 100.0, # MB | |
| "cpu_usage_percent": 80.0, # percentage | |
| } | |
| async def run_comprehensive_testing(self, page: Page) -> List[BugReport]: | |
| """Run comprehensive testing with all AI agents.""" | |
| logger.info("🤖 Starting comprehensive AI testing...") | |
| # Clear previous bugs | |
| self.bugs_found.clear() | |
| # Run all test scenarios | |
| await self._test_navigation_scenarios(page) | |
| await self._test_form_scenarios(page) | |
| await self._test_ui_scenarios(page) | |
| await self._test_performance_scenarios(page) | |
| await self._test_security_scenarios(page) | |
| logger.info(f"🔍 Found {len(self.bugs_found)} bugs/issues during testing") | |
| return self.bugs_found | |
| async def _test_navigation_scenarios(self, page: Page): | |
| """Test navigation scenarios.""" | |
| logger.info("🧭 Testing navigation scenarios...") | |
| try: | |
| # Test rapid navigation | |
| await self._rapid_navigation_test(page) | |
| # Test back/forward | |
| await self._back_forward_test(page) | |
| # Test refresh | |
| await self._refresh_test(page) | |
| # Test URL manipulation | |
| await self._url_manipulation_test(page) | |
| except Exception as e: | |
| logger.error(f"Navigation testing error: {e}") | |
| async def _test_form_scenarios(self, page: Page): | |
| """Test form scenarios.""" | |
| logger.info("📝 Testing form scenarios...") | |
| try: | |
| # Find all forms | |
| forms = await page.query_selector_all('form') | |
| for form in forms: | |
| # Test empty submission | |
| await self._test_empty_form_submission(form, page) | |
| # Test invalid data | |
| await self._test_invalid_form_data(form, page) | |
| # Test SQL injection | |
| await self._test_sql_injection_forms(form, page) | |
| # Test XSS attempts | |
| await self._test_xss_forms(form, page) | |
| # Test large data | |
| await self._test_large_form_data(form, page) | |
| # Test special characters | |
| await self._test_special_characters(form, page) | |
| except Exception as e: | |
| logger.error(f"Form testing error: {e}") | |
| async def _test_ui_scenarios(self, page: Page): | |
| """Test UI scenarios.""" | |
| logger.info("🎨 Testing UI scenarios...") | |
| try: | |
| # Test responsive design | |
| await self._test_responsive_design(page) | |
| # Test accessibility | |
| await self._test_accessibility(page) | |
| # Test hover effects | |
| await self._test_hover_effects(page) | |
| # Test clickable areas | |
| await self._test_clickable_areas(page) | |
| # Test scrolling | |
| await self._test_scrolling_behavior(page) | |
| except Exception as e: | |
| logger.error(f"UI testing error: {e}") | |
| async def _test_performance_scenarios(self, page: Page): | |
| """Test performance scenarios.""" | |
| logger.info("⚡ Testing performance scenarios...") | |
| try: | |
| # Test page load time | |
| await self._test_page_load_time(page) | |
| # Test resource loading | |
| await self._test_resource_loading(page) | |
| # Test memory usage | |
| await self._test_memory_usage(page) | |
| # Test network performance | |
| await self._test_network_performance(page) | |
| except Exception as e: | |
| logger.error(f"Performance testing error: {e}") | |
| async def _test_security_scenarios(self, page: Page): | |
| """Test security scenarios.""" | |
| logger.info("🔒 Testing security scenarios...") | |
| try: | |
| # Test CSRF | |
| await self._test_csrf_vulnerabilities(page) | |
| # Test clickjacking | |
| await self._test_clickjacking(page) | |
| # Test session management | |
| await self._test_session_management(page) | |
| # Test authentication | |
| await self._test_authentication(page) | |
| except Exception as e: | |
| logger.error(f"Security testing error: {e}") | |
| async def _rapid_navigation_test(self, page: Page): | |
| """Test rapid navigation between pages.""" | |
| try: | |
| # Get all links | |
| links = await page.query_selector_all('a[href]') | |
| if len(links) > 3: | |
| # Click first 3 links rapidly | |
| for i in range(min(3, len(links))): | |
| try: | |
| await links[i].click() | |
| await page.wait_for_timeout(500) # Short wait | |
| # Check for errors | |
| if await self._check_for_errors(page): | |
| self._add_bug_report( | |
| title="Rapid Navigation Error", | |
| severity=BugSeverity.MEDIUM, | |
| description="Error occurred during rapid navigation", | |
| steps_to_reproduce=["Navigate rapidly between pages", "Click multiple links quickly"], | |
| expected_behavior="Navigation should work smoothly", | |
| actual_behavior="Error occurred during navigation", | |
| url=page.url, | |
| element_info={"link_index": i}, | |
| recommendations=["Add loading states", "Implement proper error handling"] | |
| ) | |
| except Exception as e: | |
| self._add_bug_report( | |
| title="Navigation Failure", | |
| severity=BugSeverity.HIGH, | |
| description=f"Failed to navigate: {str(e)}", | |
| steps_to_reproduce=["Click on navigation link", "Observe error"], | |
| expected_behavior="Navigation should work", | |
| actual_behavior=f"Navigation failed: {str(e)}", | |
| url=page.url, | |
| element_info={"link_index": i}, | |
| recommendations=["Fix navigation logic", "Add error handling"] | |
| ) | |
| except Exception as e: | |
| logger.error(f"Rapid navigation test error: {e}") | |
| async def _test_empty_form_submission(self, form: Locator, page: Page): | |
| """Test form submission with empty fields.""" | |
| try: | |
| # Find all input fields | |
| inputs = await form.query_selector_all('input, textarea, select') | |
| if inputs: | |
| # Try to submit empty form | |
| submit_button = await form.query_selector('button[type="submit"], input[type="submit"]') | |
| if submit_button: | |
| await submit_button.click() | |
| await page.wait_for_timeout(1000) | |
| # Check if validation is working | |
| error_elements = await page.query_selector_all('.error, .invalid, [class*="error"], [class*="invalid"]') | |
| if not error_elements: | |
| self._add_bug_report( | |
| title="Missing Form Validation", | |
| severity=BugSeverity.HIGH, | |
| description="Form accepts empty submissions without validation", | |
| steps_to_reproduce=["Leave form fields empty", "Submit form"], | |
| expected_behavior="Form should show validation errors", | |
| actual_behavior="Form submitted without validation", | |
| url=page.url, | |
| element_info={"form_action": await form.get_attribute("action")}, | |
| recommendations=["Add client-side validation", "Add server-side validation"] | |
| ) | |
| except Exception as e: | |
| logger.error(f"Empty form submission test error: {e}") | |
| async def _test_sql_injection_forms(self, form: Locator, page: Page): | |
| """Test forms for SQL injection vulnerabilities.""" | |
| try: | |
| inputs = await form.query_selector_all('input[type="text"], input[type="email"], textarea') | |
| sql_payloads = [ | |
| "' OR '1'='1", | |
| "'; DROP TABLE users; --", | |
| "' UNION SELECT * FROM users --", | |
| "admin'--", | |
| "' OR 1=1#" | |
| ] | |
| for input_field in inputs: | |
| for payload in sql_payloads: | |
| try: | |
| await input_field.fill(payload) | |
| submit_button = await form.query_selector('button[type="submit"], input[type="submit"]') | |
| if submit_button: | |
| await submit_button.click() | |
| await page.wait_for_timeout(1000) | |
| # Check for SQL error messages | |
| content = await page.content() | |
| sql_errors = [ | |
| "mysql_fetch_array", "ORA-01756", "Microsoft OLE DB Provider", | |
| "SQLServer JDBC Driver", "PostgreSQL query failed", "Warning: mysql_", | |
| "valid MySQL result", "MySqlClient.", "SQL syntax" | |
| ] | |
| for error in sql_errors: | |
| if error.lower() in content.lower(): | |
| self._add_bug_report( | |
| title="SQL Injection Vulnerability", | |
| severity=BugSeverity.CRITICAL, | |
| description=f"SQL injection vulnerability detected with payload: {payload}", | |
| steps_to_reproduce=[f"Enter payload: {payload}", "Submit form"], | |
| expected_behavior="Input should be sanitized", | |
| actual_behavior="SQL injection successful", | |
| url=page.url, | |
| element_info={"payload": payload, "error": error}, | |
| recommendations=["Use parameterized queries", "Sanitize input", "Implement proper validation"] | |
| ) | |
| break | |
| # Clear input for next test | |
| await input_field.fill("") | |
| except Exception as e: | |
| logger.warning(f"SQL injection test error: {e}") | |
| continue | |
| except Exception as e: | |
| logger.error(f"SQL injection form test error: {e}") | |
| async def _test_xss_forms(self, form: Locator, page: Page): | |
| """Test forms for XSS vulnerabilities.""" | |
| try: | |
| inputs = await form.query_selector_all('input[type="text"], input[type="email"], textarea') | |
| xss_payloads = [ | |
| "<script>alert('XSS')</script>", | |
| "<img src=x onerror=alert('XSS')>", | |
| "javascript:alert('XSS')", | |
| "<svg onload=alert('XSS')>", | |
| "<iframe src=javascript:alert('XSS')></iframe>" | |
| ] | |
| for input_field in inputs: | |
| for payload in xss_payloads: | |
| try: | |
| await input_field.fill(payload) | |
| submit_button = await form.query_selector('button[type="submit"], input[type="submit"]') | |
| if submit_button: | |
| await submit_button.click() | |
| await page.wait_for_timeout(1000) | |
| # Check if payload is reflected | |
| content = await page.content() | |
| if payload in content: | |
| self._add_bug_report( | |
| title="XSS Vulnerability", | |
| severity=BugSeverity.CRITICAL, | |
| description=f"XSS vulnerability detected with payload: {payload}", | |
| steps_to_reproduce=[f"Enter payload: {payload}", "Submit form"], | |
| expected_behavior="Input should be sanitized", | |
| actual_behavior="XSS payload reflected", | |
| url=page.url, | |
| element_info={"payload": payload}, | |
| recommendations=["Sanitize output", "Use CSP headers", "Validate input"] | |
| ) | |
| # Clear input for next test | |
| await input_field.fill("") | |
| except Exception as e: | |
| logger.warning(f"XSS test error: {e}") | |
| continue | |
| except Exception as e: | |
| logger.error(f"XSS form test error: {e}") | |
| async def _test_responsive_design(self, page: Page): | |
| """Test responsive design.""" | |
| try: | |
| viewports = [ | |
| {"width": 320, "height": 568}, # iPhone SE | |
| {"width": 375, "height": 667}, # iPhone 8 | |
| {"width": 768, "height": 1024}, # iPad | |
| {"width": 1024, "height": 768}, # Desktop | |
| {"width": 1920, "height": 1080} # Large desktop | |
| ] | |
| for viewport in viewports: | |
| await page.set_viewport_size(viewport) | |
| await page.wait_for_timeout(500) | |
| # Check for layout issues | |
| elements = await page.query_selector_all('*') | |
| for element in elements: | |
| try: | |
| box = await element.bounding_box() | |
| if box and (box['width'] > viewport['width'] or box['height'] > viewport['height']): | |
| self._add_bug_report( | |
| title="Responsive Design Issue", | |
| severity=BugSeverity.MEDIUM, | |
| description=f"Element overflows viewport at {viewport['width']}x{viewport['height']}", | |
| steps_to_reproduce=[f"Set viewport to {viewport['width']}x{viewport['height']}", "Check layout"], | |
| expected_behavior="Elements should fit within viewport", | |
| actual_behavior="Element overflows viewport", | |
| url=page.url, | |
| element_info={"viewport": viewport, "element_box": box}, | |
| recommendations=["Fix CSS media queries", "Adjust element sizing", "Test responsive design"] | |
| ) | |
| except Exception as e: | |
| continue | |
| except Exception as e: | |
| logger.error(f"Responsive design test error: {e}") | |
| async def _test_page_load_time(self, page: Page): | |
| """Test page load time.""" | |
| try: | |
| start_time = await page.evaluate("performance.now()") | |
| await page.reload() | |
| await page.wait_for_load_state('networkidle') | |
| end_time = await page.evaluate("performance.now()") | |
| load_time = (end_time - start_time) / 1000 # Convert to seconds | |
| if load_time > self.performance_thresholds['page_load_time']: | |
| self._add_bug_report( | |
| title="Slow Page Load Time", | |
| severity=BugSeverity.MEDIUM, | |
| description=f"Page load time is {load_time:.2f}s, exceeds threshold of {self.performance_thresholds['page_load_time']}s", | |
| steps_to_reproduce=["Reload page", "Measure load time"], | |
| expected_behavior="Page should load quickly", | |
| actual_behavior=f"Page loads in {load_time:.2f}s", | |
| url=page.url, | |
| element_info={"load_time": load_time, "threshold": self.performance_thresholds['page_load_time']}, | |
| recommendations=["Optimize images", "Minify CSS/JS", "Use CDN", "Enable compression"] | |
| ) | |
| except Exception as e: | |
| logger.error(f"Page load time test error: {e}") | |
| async def _check_for_errors(self, page: Page) -> bool: | |
| """Check for JavaScript errors on the page.""" | |
| try: | |
| # Check console for errors | |
| errors = await page.evaluate(""" | |
| () => { | |
| if (window.fagunErrorMonitor) { | |
| return window.fagunErrorMonitor.getErrors(); | |
| } | |
| return []; | |
| } | |
| """) | |
| return len(errors) > 0 | |
| except Exception: | |
| return False | |
| def _add_bug_report(self, title: str, severity: BugSeverity, description: str, | |
| steps_to_reproduce: List[str], expected_behavior: str, | |
| actual_behavior: str, url: str, element_info: Dict[str, Any], | |
| recommendations: List[str]): | |
| """Add a bug report.""" | |
| bug = BugReport( | |
| title=title, | |
| severity=severity, | |
| description=description, | |
| steps_to_reproduce=steps_to_reproduce, | |
| expected_behavior=expected_behavior, | |
| actual_behavior=actual_behavior, | |
| url=url, | |
| element_info=element_info, | |
| recommendations=recommendations | |
| ) | |
| self.bugs_found.append(bug) | |
| logger.info(f"🐛 Bug found: {title} ({severity.value})") | |
| # Placeholder methods for other tests | |
| async def _back_forward_test(self, page: Page): | |
| """Test browser back/forward functionality.""" | |
| pass | |
| async def _refresh_test(self, page: Page): | |
| """Test page refresh functionality.""" | |
| pass | |
| async def _url_manipulation_test(self, page: Page): | |
| """Test URL manipulation.""" | |
| pass | |
| async def _test_invalid_form_data(self, form: Locator, page: Page): | |
| """Test form with invalid data.""" | |
| pass | |
| async def _test_large_form_data(self, form: Locator, page: Page): | |
| """Test form with large data.""" | |
| pass | |
| async def _test_special_characters(self, form: Locator, page: Page): | |
| """Test form with special characters.""" | |
| pass | |
| async def _test_accessibility(self, page: Page): | |
| """Test accessibility features.""" | |
| pass | |
| async def _test_hover_effects(self, page: Page): | |
| """Test hover effects.""" | |
| pass | |
| async def _test_clickable_areas(self, page: Page): | |
| """Test clickable areas.""" | |
| pass | |
| async def _test_scrolling_behavior(self, page: Page): | |
| """Test scrolling behavior.""" | |
| pass | |
| async def _test_resource_loading(self, page: Page): | |
| """Test resource loading performance.""" | |
| pass | |
| async def _test_memory_usage(self, page: Page): | |
| """Test memory usage.""" | |
| pass | |
| async def _test_network_performance(self, page: Page): | |
| """Test network performance.""" | |
| pass | |
| async def _test_csrf_vulnerabilities(self, page: Page): | |
| """Test CSRF vulnerabilities.""" | |
| pass | |
| async def _test_clickjacking(self, page: Page): | |
| """Test clickjacking vulnerabilities.""" | |
| pass | |
| async def _test_session_management(self, page: Page): | |
| """Test session management.""" | |
| pass | |
| async def _test_authentication(self, page: Page): | |
| """Test authentication.""" | |
| pass | |
| # Global enhanced testing engine | |
| enhanced_ai_testing_engine = EnhancedAITestingEngine() | |