#!/usr/bin/env python3 """ Comprehensive Demo of Playwright-style WebSocket Browser Control Shows both backward-compatible and new Playwright-style APIs. """ import asyncio import logging import sys import os from datetime import datetime from client import Browser, Playwright, browser # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) async def demo_basic_navigation(): """Demo basic navigation features""" print("\n=== Basic Navigation Demo ===") # Create browser instance browser_instance = Browser("ws://localhost:8765") await browser_instance.connect() try: # Create a page page = await browser_instance.new_page() # Navigate to a website print("Navigating to example.com...") await page.goto("https://example.com") await asyncio.sleep(2) # Get page info title = await page.title() url = await page.url() print(f"Title: {title}") print(f"URL: {url}") # Navigate to another page print("\nNavigating to Python.org...") await page.goto("https://www.python.org") await asyncio.sleep(2) # Go back print("Going back...") await page.go_back() await asyncio.sleep(2) # Go forward print("Going forward...") await page.go_forward() await asyncio.sleep(2) # Reload print("Reloading page...") await page.reload() await asyncio.sleep(2) finally: await browser_instance.close() async def demo_playwright_style(): """Demo Playwright-style API usage""" print("\n=== Playwright-Style API Demo ===") # Using Playwright launcher playwright = Playwright() browser_instance = await playwright.chromium.launch(ws_endpoint="ws://localhost:8765") try: # Create context and page context = await browser_instance.new_context() page = await context.new_page() # Navigate and wait for load print("Navigating with Playwright-style API...") await page.goto("https://www.wikipedia.org") await page.wait_for_load_state("load") # Use locators print("Using locators to find elements...") search_box = page.locator('input[name="search"]') # Type into search box print("Typing 'Python programming' into search...") await search_box.type("Python programming", delay=50) await asyncio.sleep(1) # Press Enter print("Pressing Enter...") await search_box.press("Enter") await page.wait_for_load_state("load") await asyncio.sleep(2) # Take screenshot print("Taking screenshot...") screenshot_data = await page.screenshot() with open("wikipedia_search.png", "wb") as f: f.write(screenshot_data) print("Screenshot saved as wikipedia_search.png") finally: await browser_instance.close() async def demo_form_interaction(): """Demo form interaction capabilities""" print("\n=== Form Interaction Demo ===") async with browser(ws_endpoint="ws://localhost:8765") as browser_instance: page = await browser_instance.new_page() # Create a test form html_content = """ Test Form

Test Form

""" # Set the content print("Loading test form...") await page.set_content(html_content) # Fill the form using different methods print("\nFilling form fields...") # Method 1: Using fill() await page.fill("#name", "John Doe") # Method 2: Using type() for more realistic typing await page.type("#email", "john.doe@example.com", delay=50) # Method 3: Using locator country_select = page.locator("#country") await country_select.select_option("us") # Check checkbox print("Checking newsletter checkbox...") await page.check("#newsletter") # Select radio button print("Selecting gender radio button...") await page.click('input[name="gender"][value="male"]') # Fill textarea print("Adding comments...") comments_field = page.locator("#comments") await comments_field.fill("This is a test comment\nWith multiple lines\nUsing Playwright-style API") # Submit form print("Submitting form...") await page.click('button[type="submit"]') await asyncio.sleep(1) # Check if result is visible result_div = page.locator("#result") is_visible = await result_div.is_visible() print(f"Result visible: {is_visible}") # Get the result content result_text = await page.inner_text("#resultContent") print("Form submission result:") print(result_text) # Take a screenshot of the filled form await page.screenshot() print("Screenshot taken of submitted form") async def demo_element_queries(): """Demo element querying and manipulation""" print("\n=== Element Query Demo ===") browser_instance = Browser("ws://localhost:8765") await browser_instance.connect() try: page = await browser_instance.new_page() # Create a test page with multiple elements html_content = """ Element Query Test

Element Query Test

Item 1
Item 2
Item 4
""" await page.set_content(html_content) print("Test page loaded") # Query single element print("\nQuerying single element...") first_item = await page.query_selector(".item") if first_item: text = await first_item.inner_text() print(f"First item text: {text}") # Query all elements print("\nQuerying all items...") all_items = await page.query_selector_all(".item") print(f"Found {len(all_items)} items") # Check visibility print("\nChecking visibility of items...") for i, item in enumerate(all_items): is_visible = await item.is_visible() print(f"Item {i+1} visible: {is_visible}") # Get attributes print("\nGetting data attributes...") for item in all_items: data_id = await item.get_attribute("data-id") print(f"Item has data-id: {data_id}") # Click toggle button to show hidden item print("\nClicking toggle button...") await page.click("#toggleBtn") await asyncio.sleep(0.5) # Check visibility again hidden_item = page.locator('[data-id="3"]') is_visible_after = await hidden_item.is_visible() print(f"Hidden item visible after toggle: {is_visible_after}") # Click highlight button print("\nClicking highlight button...") await page.click("#highlightBtn") await asyncio.sleep(0.5) # Use evaluate to check if highlighting worked has_highlight = await page.evaluate(""" () => { const items = document.querySelectorAll('.item.highlight'); return items.length; } """) print(f"Number of highlighted items: {has_highlight}") finally: await browser_instance.close() async def demo_wait_conditions(): """Demo various wait conditions""" print("\n=== Wait Conditions Demo ===") async with browser(ws_endpoint="ws://localhost:8765") as browser_instance: page = await browser_instance.new_page() # Create a dynamic page html_content = """ Dynamic Content Test

Dynamic Content Test

Content will appear here...
""" await page.set_content(html_content) print("Dynamic page loaded") # Click load button print("\nClicking load button...") await page.click("#loadBtn") # Wait for content to change print("Waiting for content to load...") await page.wait_for_function(""" () => { const content = document.getElementById('content'); return content && content.classList.contains('loaded'); } """, timeout=5000) print("Content loaded!") # Wait for extra content print("Waiting for extra content...") extra_content = await page.wait_for_selector("#extraContent", timeout=5000) if extra_content: extra_text = await extra_content.inner_text() print(f"Extra content appeared: {extra_text}") # Wait with timeout print("\nWaiting for 2 seconds...") await page.wait_for_timeout(2000) print("Wait completed") async def demo_javascript_execution(): """Demo JavaScript execution capabilities""" print("\n=== JavaScript Execution Demo ===") browser_instance = Browser("ws://localhost:8765") await browser_instance.connect() try: page = await browser_instance.new_page() # Navigate to a simple page await page.goto("https://example.com") await asyncio.sleep(2) # Wait for page to load # Execute simple JavaScript print("\nExecuting simple JavaScript...") try: result = await page.evaluate("1 + 2") print(f"1 + 2 = {result}") except Exception as e: print(f"Error executing simple math: {e}") # Get page dimensions try: dimensions = await page.evaluate(""" () => { return { width: window.innerWidth, height: window.innerHeight, devicePixelRatio: window.devicePixelRatio || 1 } } """) print(f"Page dimensions: {dimensions}") except Exception as e: print(f"Error getting dimensions: {e}") # Modify page content print("\nModifying page content...") try: await page.evaluate(""" () => { const h1 = document.querySelector('h1'); if (h1) { h1.style.color = 'red'; h1.textContent = 'Modified by Playwright-style API!'; } } """) print("Page modified successfully") except Exception as e: print(f"Error modifying page: {e}") # Create new elements try: await page.evaluate(""" () => { const div = document.createElement('div'); div.id = 'custom-div'; div.style.cssText = 'position: fixed; top: 10px; right: 10px; ' + 'background: yellow; padding: 20px; ' + 'border: 2px solid black; z-index: 9999;'; div.textContent = 'Created via JavaScript!'; document.body.appendChild(div); } """) print("New element created") except Exception as e: print(f"Error creating element: {e}") await asyncio.sleep(2) # Pass arguments to JavaScript print("\nPassing arguments to JavaScript...") try: greeting = await page.evaluate( "(name) => `Hello, ${name}!`", "Playwright User" ) print(f"Greeting: {greeting}") except Exception as e: print(f"Error with argument passing: {e}") except Exception as e: print(f"Error in demo: {e}") finally: await browser_instance.close() async def demo_event_handling(): """Demo event handling capabilities""" print("\n=== Event Handling Demo ===") browser_instance = Browser("ws://localhost:8765") await browser_instance.connect() # Set up event listeners events_received = [] def on_browser_ready(data): events_received.append(("browser_ready", data)) print(f"Event: Browser ready - {data}") def on_load_started(data): events_received.append(("load_started", data)) print(f"Event: Load started - {data.get('url', 'unknown')}") def on_load_finished(data): events_received.append(("load_finished", data)) print(f"Event: Load finished - {data.get('url', 'unknown')}") def on_title_changed(data): events_received.append(("title_changed", data)) print(f"Event: Title changed - {data.get('title', 'unknown')}") # Register event listeners browser_instance.on("browser_ready", on_browser_ready) browser_instance.on("load_started", on_load_started) browser_instance.on("load_finished", on_load_finished) browser_instance.on("title_changed", on_title_changed) try: page = await browser_instance.new_page() print("\nNavigating to trigger events...") await page.goto("https://www.python.org") await asyncio.sleep(2) print(f"\nTotal events received: {len(events_received)}") # Navigate to another page print("\nNavigating to another page...") await page.goto("https://example.com") await asyncio.sleep(2) print(f"Total events received: {len(events_received)}") finally: await browser_instance.close() async def demo_backward_compatibility(): """Demo backward compatible API usage""" print("\n=== Backward Compatibility Demo ===") browser_instance = Browser("ws://localhost:8765") await browser_instance.connect() try: page = await browser_instance.new_page() # Old-style commands still work print("Using backward-compatible commands...") # navigate command result = await browser_instance._send_command({ "command": "navigate", "url": "https://example.com" }) print(f"Navigate result: {result}") await asyncio.sleep(2) # execute_js command result = await browser_instance._send_command({ "command": "execute_js", "script": "document.title" }) print(f"Page title via execute_js: {result}") # simulate_typing command result = await browser_instance._send_command({ "command": "simulate_typing", "selector": "h1", "text": "Hello", "delay": 0.1 }) print(f"Simulate typing result: {result}") # get_info command info = await browser_instance._send_command({ "command": "get_info" }) print(f"Browser info: {info}") finally: await browser_instance.close() async def run_all_demos(): """Run all demo functions""" demos = [ demo_basic_navigation, demo_playwright_style, demo_form_interaction, demo_element_queries, demo_wait_conditions, demo_javascript_execution, demo_event_handling, demo_backward_compatibility ] print("=" * 60) print("Playwright-style WebSocket Browser Control Demo") print("=" * 60) print("\nMake sure the browser server is running on ws://localhost:8765") print("Start it with: python browser_server_playwright.py") input("\nPress Enter to start demos...") for demo in demos: try: await demo() await asyncio.sleep(2) # Pause between demos except Exception as e: logger.error(f"Error in {demo.__name__}: {e}") import traceback traceback.print_exc() print("\n" + "=" * 60) print("All demos completed!") print("=" * 60) # Individual demo runners for testing async def main(): """Main entry point""" if len(sys.argv) > 1: demo_name = sys.argv[1] demos = { "navigation": demo_basic_navigation, "playwright": demo_playwright_style, "form": demo_form_interaction, "elements": demo_element_queries, "wait": demo_wait_conditions, "javascript": demo_javascript_execution, "events": demo_event_handling, "compatibility": demo_backward_compatibility, "all": run_all_demos } if demo_name in demos: await demos[demo_name]() else: print(f"Unknown demo: {demo_name}") print(f"Available demos: {', '.join(demos.keys())}") else: await run_all_demos() if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("\nDemo interrupted by user") except Exception as e: logger.error(f"Fatal error: {e}") import traceback traceback.print_exc()