Spaces:
Running
Running
| """ | |
| Screenshot capture tool for ChatUI Helper documentation | |
| Uses Playwright to automate browser interactions and capture screenshots | |
| """ | |
| import asyncio | |
| import os | |
| from pathlib import Path | |
| from playwright.async_api import async_playwright | |
| import logging | |
| from datetime import datetime | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') | |
| logger = logging.getLogger(__name__) | |
| # Screenshot configurations for each documentation step | |
| SCREENSHOT_CONFIGS = [ | |
| { | |
| "name": "main_interface", | |
| "url": "http://localhost:7860", | |
| "description": "Main interface with all tabs", | |
| "actions": [], | |
| "wait_time": 2000, | |
| "selector": None, # Full page | |
| "output": "img/main_interface.png" | |
| }, | |
| { | |
| "name": "config_tab", | |
| "url": "http://localhost:7860", | |
| "description": "Configuration tab", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"} | |
| ], | |
| "wait_time": 1000, | |
| "selector": None, | |
| "output": "img/config_tab.png" | |
| }, | |
| { | |
| "name": "template_dropdown", | |
| "url": "http://localhost:7860", | |
| "description": "Template selection dropdown", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "click", "selector": "div[data-testid='dropdown']", "nth": 0} | |
| ], | |
| "wait_time": 1000, | |
| "selector": "div.dropdown-menu", | |
| "output": "img/template_dropdown.png" | |
| }, | |
| { | |
| "name": "preview_tab", | |
| "url": "http://localhost:7860", | |
| "description": "Preview tab with chat interface", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Preview')"} | |
| ], | |
| "wait_time": 2000, | |
| "selector": None, | |
| "output": "img/preview_tab.png" | |
| }, | |
| { | |
| "name": "preview_chat_example", | |
| "url": "http://localhost:7860", | |
| "description": "Preview tab with example conversation", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Preview')"}, | |
| {"type": "wait", "time": 2000}, | |
| {"type": "type", "selector": "textarea[placeholder*='Type a message']", "text": "Hello! Can you help me understand quantum mechanics?"}, | |
| {"type": "click", "selector": "button:has-text('Send')"}, | |
| {"type": "wait", "time": 3000} | |
| ], | |
| "wait_time": 1000, | |
| "selector": None, | |
| "output": "img/preview_chat_example.png" | |
| }, | |
| { | |
| "name": "docs_tab", | |
| "url": "http://localhost:7860", | |
| "description": "Documentation tab", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Docs')"} | |
| ], | |
| "wait_time": 1000, | |
| "selector": None, | |
| "output": "img/docs_tab.png" | |
| }, | |
| { | |
| "name": "docs_quickstart", | |
| "url": "http://localhost:7860", | |
| "description": "Documentation quick start guide", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Docs')"}, | |
| {"type": "wait", "time": 1000}, | |
| {"type": "click", "selector": "button:has-text('📖 Quick Start Guide')"} | |
| ], | |
| "wait_time": 1000, | |
| "selector": None, | |
| "output": "img/docs_quickstart.png" | |
| }, | |
| { | |
| "name": "config_system_prompt", | |
| "url": "http://localhost:7860", | |
| "description": "System configuration section", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "wait", "time": 1000}, | |
| {"type": "scroll", "y": 500} | |
| ], | |
| "wait_time": 1000, | |
| "selector": None, | |
| "output": "img/config_system_prompt.png" | |
| }, | |
| { | |
| "name": "config_api_section", | |
| "url": "http://localhost:7860", | |
| "description": "API configuration section", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "wait", "time": 1000}, | |
| {"type": "scroll", "y": 1200} | |
| ], | |
| "wait_time": 1000, | |
| "selector": None, | |
| "output": "img/config_api_section.png" | |
| }, | |
| { | |
| "name": "generate_button", | |
| "url": "http://localhost:7860", | |
| "description": "Generate deployment package button", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "wait", "time": 1000}, | |
| {"type": "scroll", "y": 2000} | |
| ], | |
| "wait_time": 1000, | |
| "selector": "button:has-text('🗳️ Generate Deployment Package')", | |
| "output": "img/generate_button.png" | |
| } | |
| ] | |
| async def capture_screenshot(page, config): | |
| """Capture a single screenshot based on configuration""" | |
| logger.info(f"Capturing screenshot: {config['name']} - {config['description']}") | |
| try: | |
| # Navigate to URL | |
| await page.goto(config['url']) | |
| # Execute actions | |
| for action in config.get('actions', []): | |
| if action['type'] == 'click': | |
| selector = action['selector'] | |
| nth = action.get('nth', 0) | |
| if nth > 0: | |
| await page.locator(selector).nth(nth).click() | |
| else: | |
| await page.click(selector) | |
| await page.wait_for_timeout(500) | |
| elif action['type'] == 'type': | |
| await page.fill(action['selector'], action['text']) | |
| elif action['type'] == 'wait': | |
| await page.wait_for_timeout(action['time']) | |
| elif action['type'] == 'scroll': | |
| await page.evaluate(f"window.scrollBy(0, {action['y']})") | |
| await page.wait_for_timeout(500) | |
| # Wait for any animations to complete | |
| await page.wait_for_timeout(config.get('wait_time', 1000)) | |
| # Take screenshot | |
| output_path = Path(config['output']) | |
| output_path.parent.mkdir(parents=True, exist_ok=True) | |
| if config.get('selector'): | |
| # Screenshot of specific element | |
| element = page.locator(config['selector']) | |
| await element.screenshot(path=str(output_path)) | |
| else: | |
| # Full page screenshot | |
| await page.screenshot(path=str(output_path), full_page=False) | |
| logger.info(f"✅ Saved screenshot to {output_path}") | |
| return True | |
| except Exception as e: | |
| logger.error(f"❌ Failed to capture {config['name']}: {str(e)}") | |
| return False | |
| async def capture_all_screenshots(): | |
| """Capture all configured screenshots""" | |
| logger.info("Starting screenshot capture process...") | |
| # Ensure the app is running | |
| logger.info("Make sure the Gradio app is running on http://localhost:7860") | |
| async with async_playwright() as p: | |
| # Launch browser | |
| browser = await p.chromium.launch(headless=False) # Set to True for headless mode | |
| context = await browser.new_context( | |
| viewport={'width': 1280, 'height': 800}, | |
| device_scale_factor=2 # Higher quality screenshots | |
| ) | |
| page = await context.new_page() | |
| # Capture each screenshot | |
| success_count = 0 | |
| for config in SCREENSHOT_CONFIGS: | |
| if await capture_screenshot(page, config): | |
| success_count += 1 | |
| await page.wait_for_timeout(1000) # Brief pause between screenshots | |
| # Clean up | |
| await browser.close() | |
| logger.info(f"\nCapture complete! {success_count}/{len(SCREENSHOT_CONFIGS)} screenshots captured successfully.") | |
| # Create a summary report | |
| report_path = Path("img/screenshot_report.txt") | |
| with open(report_path, 'w') as f: | |
| f.write(f"Screenshot Capture Report\n") | |
| f.write(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") | |
| f.write(f"Total Screenshots: {len(SCREENSHOT_CONFIGS)}\n") | |
| f.write(f"Successful: {success_count}\n\n") | |
| f.write("Screenshots Generated:\n") | |
| for config in SCREENSHOT_CONFIGS: | |
| f.write(f"- {config['output']}: {config['description']}\n") | |
| logger.info(f"Report saved to {report_path}") | |
| async def capture_single_screenshot(name): | |
| """Capture a single screenshot by name""" | |
| config = next((c for c in SCREENSHOT_CONFIGS if c['name'] == name), None) | |
| if not config: | |
| logger.error(f"No configuration found for screenshot: {name}") | |
| return | |
| async with async_playwright() as p: | |
| browser = await p.chromium.launch(headless=False) | |
| context = await browser.new_context( | |
| viewport={'width': 1280, 'height': 800}, | |
| device_scale_factor=2 | |
| ) | |
| page = await context.new_page() | |
| await capture_screenshot(page, config) | |
| await browser.close() | |
| def main(): | |
| """Main entry point""" | |
| import sys | |
| if len(sys.argv) > 1: | |
| # Capture specific screenshot | |
| asyncio.run(capture_single_screenshot(sys.argv[1])) | |
| else: | |
| # Capture all screenshots | |
| asyncio.run(capture_all_screenshots()) | |
| if __name__ == "__main__": | |
| main() |