2025-08-11 13:28:18 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
Comprehensive Demo of Playwright-style WebSocket Browser Control
|
|
|
|
Shows both backward-compatible and new Playwright-style APIs.
|
|
|
|
"""
|
|
|
|
|
2025-07-17 00:51:02 +02:00
|
|
|
import asyncio
|
2025-08-11 13:28:18 +02:00
|
|
|
import logging
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
from datetime import datetime
|
|
|
|
from client import Browser, Playwright, browser
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# 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()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Navigate to a website
|
|
|
|
print("Navigating to example.com...")
|
|
|
|
await page.goto("https://example.com")
|
2025-07-17 00:51:02 +02:00
|
|
|
await asyncio.sleep(2)
|
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Get page info
|
|
|
|
title = await page.title()
|
|
|
|
url = await page.url()
|
|
|
|
print(f"Title: {title}")
|
|
|
|
print(f"URL: {url}")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Navigate to another page
|
|
|
|
print("\nNavigating to Python.org...")
|
|
|
|
await page.goto("https://www.python.org")
|
|
|
|
await asyncio.sleep(2)
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Go back
|
|
|
|
print("Going back...")
|
|
|
|
await page.go_back()
|
|
|
|
await asyncio.sleep(2)
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# 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()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
async def demo_playwright_style():
|
|
|
|
"""Demo Playwright-style API usage"""
|
|
|
|
print("\n=== Playwright-Style API Demo ===")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Using Playwright launcher
|
|
|
|
playwright = Playwright()
|
|
|
|
browser_instance = await playwright.chromium.launch(ws_endpoint="ws://localhost:8765")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
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()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
async def demo_form_interaction():
|
|
|
|
"""Demo form interaction capabilities"""
|
|
|
|
print("\n=== Form Interaction Demo ===")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
async with browser(ws_endpoint="ws://localhost:8765") as browser_instance:
|
|
|
|
page = await browser_instance.new_page()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Create a test form
|
|
|
|
html_content = """
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>Test Form</title>
|
|
|
|
<style>
|
|
|
|
body { font-family: Arial, sans-serif; margin: 40px; }
|
|
|
|
.form-group { margin-bottom: 15px; }
|
|
|
|
label { display: block; margin-bottom: 5px; }
|
|
|
|
input, select, textarea { padding: 8px; width: 300px; }
|
|
|
|
button { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }
|
|
|
|
button:hover { background: #0056b3; }
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Test Form</h1>
|
|
|
|
<form id="testForm">
|
|
|
|
<div class="form-group">
|
|
|
|
<label for="name">Name:</label>
|
|
|
|
<input type="text" id="name" name="name" required>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
|
|
|
<label for="email">Email:</label>
|
|
|
|
<input type="email" id="email" name="email" required>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
|
|
|
<label for="country">Country:</label>
|
|
|
|
<select id="country" name="country">
|
|
|
|
<option value="">Select a country</option>
|
|
|
|
<option value="us">United States</option>
|
|
|
|
<option value="uk">United Kingdom</option>
|
|
|
|
<option value="ca">Canada</option>
|
|
|
|
<option value="au">Australia</option>
|
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
|
|
|
<label>
|
|
|
|
<input type="checkbox" id="newsletter" name="newsletter">
|
|
|
|
Subscribe to newsletter
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
|
|
|
<label>Gender:</label>
|
|
|
|
<label><input type="radio" name="gender" value="male"> Male</label>
|
|
|
|
<label><input type="radio" name="gender" value="female"> Female</label>
|
|
|
|
<label><input type="radio" name="gender" value="other"> Other</label>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
|
|
|
<label for="comments">Comments:</label>
|
|
|
|
<textarea id="comments" name="comments" rows="4"></textarea>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<button type="submit">Submit</button>
|
|
|
|
</form>
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
<div id="result" style="margin-top: 20px; padding: 20px; background: #f0f0f0; display: none;">
|
|
|
|
<h2>Form Submitted!</h2>
|
|
|
|
<div id="resultContent"></div>
|
|
|
|
</div>
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
<script>
|
|
|
|
document.getElementById('testForm').addEventListener('submit', function(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(e.target);
|
|
|
|
const data = Object.fromEntries(formData.entries());
|
|
|
|
|
|
|
|
document.getElementById('resultContent').innerHTML =
|
|
|
|
'<pre>' + JSON.stringify(data, null, 2) + '</pre>';
|
|
|
|
document.getElementById('result').style.display = 'block';
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
"""
|
|
|
|
|
|
|
|
# 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")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
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 = """
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>Element Query Test</title>
|
|
|
|
<style>
|
|
|
|
.item { padding: 10px; margin: 5px; background: #f0f0f0; }
|
|
|
|
.hidden { display: none; }
|
|
|
|
.highlight { background: yellow; }
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Element Query Test</h1>
|
|
|
|
<div class="container">
|
|
|
|
<div class="item" data-id="1">Item 1</div>
|
|
|
|
<div class="item" data-id="2">Item 2</div>
|
|
|
|
<div class="item hidden" data-id="3">Item 3 (Hidden)</div>
|
|
|
|
<div class="item" data-id="4">Item 4</div>
|
|
|
|
<button id="toggleBtn">Toggle Item 3</button>
|
|
|
|
<button id="highlightBtn">Highlight All</button>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
|
|
document.getElementById('toggleBtn').addEventListener('click', () => {
|
|
|
|
const item3 = document.querySelector('[data-id="3"]');
|
|
|
|
item3.classList.toggle('hidden');
|
|
|
|
});
|
|
|
|
|
|
|
|
document.getElementById('highlightBtn').addEventListener('click', () => {
|
|
|
|
document.querySelectorAll('.item').forEach(item => {
|
|
|
|
item.classList.add('highlight');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
"""
|
|
|
|
|
|
|
|
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()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
async def demo_wait_conditions():
|
|
|
|
"""Demo various wait conditions"""
|
|
|
|
print("\n=== Wait Conditions Demo ===")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
async with browser(ws_endpoint="ws://localhost:8765") as browser_instance:
|
|
|
|
page = await browser_instance.new_page()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Create a dynamic page
|
|
|
|
html_content = """
|
|
|
|
<!DOCTYPE html>
|
2025-07-17 00:51:02 +02:00
|
|
|
<html>
|
|
|
|
<head>
|
2025-08-11 13:28:18 +02:00
|
|
|
<title>Dynamic Content Test</title>
|
2025-07-17 00:51:02 +02:00
|
|
|
<style>
|
2025-08-11 13:28:18 +02:00
|
|
|
.content { padding: 20px; margin: 20px; background: #f0f0f0; }
|
|
|
|
.loading { color: #999; }
|
|
|
|
.loaded { color: #333; font-weight: bold; }
|
2025-07-17 00:51:02 +02:00
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
2025-08-11 13:28:18 +02:00
|
|
|
<h1>Dynamic Content Test</h1>
|
|
|
|
<button id="loadBtn">Load Content</button>
|
|
|
|
<div id="content" class="content loading">Content will appear here...</div>
|
2025-07-17 00:51:02 +02:00
|
|
|
|
|
|
|
<script>
|
2025-08-11 13:28:18 +02:00
|
|
|
document.getElementById('loadBtn').addEventListener('click', () => {
|
|
|
|
const content = document.getElementById('content');
|
|
|
|
content.textContent = 'Loading...';
|
|
|
|
content.className = 'content loading';
|
|
|
|
|
|
|
|
// Simulate async loading
|
|
|
|
setTimeout(() => {
|
|
|
|
content.textContent = 'Content loaded successfully!';
|
|
|
|
content.className = 'content loaded';
|
|
|
|
|
|
|
|
// Add more content after another delay
|
|
|
|
setTimeout(() => {
|
|
|
|
const extra = document.createElement('div');
|
|
|
|
extra.id = 'extraContent';
|
|
|
|
extra.textContent = 'Extra content added!';
|
|
|
|
content.appendChild(extra);
|
|
|
|
}, 1000);
|
|
|
|
}, 2000);
|
|
|
|
});
|
2025-07-17 00:51:02 +02:00
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
"""
|
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
await page.set_content(html_content)
|
|
|
|
print("Dynamic page loaded")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Click load button
|
|
|
|
print("\nClicking load button...")
|
|
|
|
await page.click("#loadBtn")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# 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!")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# 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({
|
2025-07-17 00:51:02 +02:00
|
|
|
"command": "execute_js",
|
2025-08-11 13:28:18 +02:00
|
|
|
"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}")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# get_info command
|
|
|
|
info = await browser_instance._send_command({
|
|
|
|
"command": "get_info"
|
|
|
|
})
|
|
|
|
print(f"Browser info: {info}")
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
finally:
|
|
|
|
await browser_instance.close()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
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)
|
2025-07-17 00:51:02 +02:00
|
|
|
|
2025-08-11 13:28:18 +02:00
|
|
|
# Individual demo runners for testing
|
2025-07-17 00:51:02 +02:00
|
|
|
async def main():
|
2025-08-11 13:28:18 +02:00
|
|
|
"""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())}")
|
2025-07-17 00:51:02 +02:00
|
|
|
else:
|
2025-08-11 13:28:18 +02:00
|
|
|
await run_all_demos()
|
2025-07-17 00:51:02 +02:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2025-08-11 13:28:18 +02:00
|
|
|
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()
|