#!/usr/bin/env python3 """ Visual Testing Script for WHOOSH Frontend Development Uses Selenium WebDriver to test and capture screenshots of the frontend """ import os import sys import time import json from datetime import datetime from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import TimeoutException, WebDriverException class WHOOSHVisualTester: def __init__(self, base_url="http://localhost:3000", headless=True): self.base_url = base_url self.headless = headless self.driver = None self.screenshots_dir = "/tmp/whoosh_screenshots" self.setup_driver() os.makedirs(self.screenshots_dir, exist_ok=True) def setup_driver(self): """Setup Chrome WebDriver with appropriate options""" chrome_options = Options() if self.headless: chrome_options.add_argument("--headless") chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-dev-shm-usage") chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("--window-size=1920,1080") chrome_options.add_argument("--disable-extensions") try: self.driver = webdriver.Chrome(options=chrome_options) self.driver.implicitly_wait(10) print("โœ… Chrome WebDriver initialized successfully") except Exception as e: print(f"โŒ Failed to initialize Chrome WebDriver: {e}") sys.exit(1) def take_screenshot(self, name, description=""): """Take a screenshot and save with timestamp""" timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"{timestamp}_{name}.png" filepath = os.path.join(self.screenshots_dir, filename) try: self.driver.save_screenshot(filepath) print(f"๐Ÿ“ธ Screenshot saved: {filename}") if description: print(f" Description: {description}") return filepath except Exception as e: print(f"โŒ Failed to take screenshot: {e}") return None def wait_for_element(self, by, value, timeout=10): """Wait for element to be present and visible""" try: element = WebDriverWait(self.driver, timeout).until( EC.presence_of_element_located((by, value)) ) return element except TimeoutException: print(f"โฐ Timeout waiting for element: {by}={value}") return None def test_homepage_load(self): """Test if homepage loads correctly""" print("\n๐Ÿ” Testing Homepage Load...") try: self.driver.get(self.base_url) self.take_screenshot("01_homepage_initial", "Initial homepage load") # Wait for React to load time.sleep(3) # Check if we get redirected to login or see the main app current_url = self.driver.current_url print(f"Current URL: {current_url}") # Look for common elements page_title = self.driver.title print(f"Page title: {page_title}") # Check for main content or login form body_text = self.driver.find_element(By.TAG_NAME, "body").text if "login" in body_text.lower() or "sign in" in body_text.lower(): print("๐Ÿ” Detected login page") self.take_screenshot("02_login_page", "Login page detected") return "login" elif "dashboard" in body_text.lower() or "agents" in body_text.lower(): print("๐Ÿ  Detected main dashboard") self.take_screenshot("02_dashboard_page", "Dashboard page detected") return "dashboard" else: print("โ“ Unknown page state") self.take_screenshot("02_unknown_state", "Unknown page state") return "unknown" except Exception as e: print(f"โŒ Error testing homepage: {e}") self.take_screenshot("error_homepage", "Error on homepage") return "error" def test_api_connectivity(self): """Test API connectivity by checking network requests""" print("\n๐Ÿ” Testing API Connectivity...") try: # Enable network logging self.driver.execute_cdp_cmd('Network.enable', {}) # Navigate to a page that should make API calls self.driver.get(f"{self.base_url}/agents") time.sleep(5) # Wait for API calls self.take_screenshot("03_agents_page", "Agents page with API data") # Check for API error messages in the page body_text = self.driver.find_element(By.TAG_NAME, "body").text if "error" in body_text.lower() or "failed" in body_text.lower(): print("โš ๏ธ Possible API errors detected in page content") return False print("โœ… No obvious API errors detected") return True except Exception as e: print(f"โŒ Error testing API connectivity: {e}") self.take_screenshot("error_api_test", "Error testing API") return False def test_navigation(self): """Test navigation between pages""" print("\n๐Ÿ” Testing Navigation...") nav_items = [ ("/", "homepage"), ("/agents", "agents_page"), ("/tasks", "tasks_page"), ("/workflows", "workflows_page"), ("/analytics", "analytics_page"), ("/executions", "executions_page") ] for path, name in nav_items: try: print(f"Navigating to: {path}") self.driver.get(f"{self.base_url}{path}") time.sleep(3) # Wait for page load self.take_screenshot(f"04_nav_{name}", f"Navigation to {path}") # Check for loading states or errors body_text = self.driver.find_element(By.TAG_NAME, "body").text if "loading" in body_text.lower(): print("โณ Page still loading...") time.sleep(3) self.take_screenshot(f"04_nav_{name}_loaded", f"After loading: {path}") except Exception as e: print(f"โŒ Error navigating to {path}: {e}") self.take_screenshot(f"error_nav_{name}", f"Navigation error: {path}") def test_live_data_display(self): """Test if live data is being displayed correctly""" print("\n๐Ÿ” Testing Live Data Display...") # Test Analytics page for data try: self.driver.get(f"{self.base_url}/analytics") time.sleep(5) page_source = self.driver.page_source # Look for mock data indicators mock_indicators = ["mock", "demo", "placeholder", "sample"] found_mock = any(indicator in page_source.lower() for indicator in mock_indicators) if found_mock: print("โš ๏ธ Mock data indicators found - may need to replace with live data") else: print("โœ… No obvious mock data indicators found") self.take_screenshot("05_analytics_data", "Analytics page data display") # Check for charts/graphs charts = self.driver.find_elements(By.CSS_SELECTOR, "svg, canvas, .recharts-wrapper") print(f"Found {len(charts)} chart elements") return not found_mock except Exception as e: print(f"โŒ Error testing live data: {e}") return False def test_responsive_design(self): """Test responsive design at different screen sizes""" print("\n๐Ÿ” Testing Responsive Design...") screen_sizes = [ (1920, 1080, "desktop"), (1024, 768, "tablet"), (375, 667, "mobile") ] for width, height, device in screen_sizes: try: self.driver.set_window_size(width, height) time.sleep(2) self.driver.get(f"{self.base_url}/agents") time.sleep(3) self.take_screenshot(f"06_responsive_{device}", f"Responsive test: {device} ({width}x{height})") except Exception as e: print(f"โŒ Error testing {device} responsive: {e}") def run_full_test_suite(self): """Run complete visual test suite""" print("๐Ÿš€ Starting WHOOSH Frontend Visual Test Suite") print("=" * 50) results = {} # Test 1: Homepage load results['homepage'] = self.test_homepage_load() # Test 2: API connectivity results['api'] = self.test_api_connectivity() # Test 3: Navigation self.test_navigation() results['navigation'] = True # Test 4: Live data results['live_data'] = self.test_live_data_display() # Test 5: Responsive design self.test_responsive_design() results['responsive'] = True # Summary print("\n" + "=" * 50) print("๐Ÿ“Š Test Results Summary:") for test, result in results.items(): status = "โœ… PASS" if result in [True, "dashboard", "login"] else "โŒ FAIL" print(f" {test}: {status} ({result})") print(f"\n๐Ÿ“ Screenshots saved to: {self.screenshots_dir}") return results def cleanup(self): """Clean up WebDriver""" if self.driver: self.driver.quit() print("๐Ÿงน WebDriver closed") def main(): # Check if Chrome is available try: tester = WHOOSHVisualTester(headless=True) results = tester.run_full_test_suite() tester.cleanup() # Return exit code based on results failed_tests = [k for k, v in results.items() if v in [False, "error", "unknown"]] if failed_tests: print(f"\nโŒ Some tests failed: {failed_tests}") sys.exit(1) else: print("\nโœ… All tests passed!") sys.exit(0) except Exception as e: print(f"โŒ Test suite failed: {e}") sys.exit(1) if __name__ == "__main__": main()