Spaces:
Running
Running
| import time | |
| import subprocess | |
| import os | |
| import signal | |
| from playwright.sync_api import sync_playwright | |
| def test_full_app_flow(): | |
| # 1. Start backend | |
| backend_env = os.environ.copy() | |
| backend_env["CI_MODE"] = "true" | |
| python_path = "./venv/bin/python3" if os.path.exists("./venv/bin/python3") else "python3" | |
| backend_proc = subprocess.Popen( | |
| [python_path, "backend/app.py"], | |
| stdout=open("backend.log", "w"), | |
| stderr=subprocess.STDOUT, | |
| preexec_fn=os.setsid, | |
| env=backend_env | |
| ) | |
| # 2. Start frontend (Vite) | |
| frontend_proc = subprocess.Popen( | |
| ["npm", "run", "dev"], | |
| cwd="frontend", | |
| stdout=open("frontend.log", "w"), | |
| stderr=subprocess.STDOUT, | |
| preexec_fn=os.setsid | |
| ) | |
| try: | |
| # Polling for servers to start | |
| print("Waiting for servers to start...") | |
| import socket | |
| def wait_for_port(port, timeout=30): | |
| start_time = time.time() | |
| while time.time() - start_time < timeout: | |
| try: | |
| with socket.create_connection(("localhost", port), timeout=1): | |
| return True | |
| except: | |
| time.sleep(1) | |
| return False | |
| if not wait_for_port(8000) or not wait_for_port(5173): | |
| print("Servers failed to start in time.") | |
| return | |
| with sync_playwright() as p: | |
| browser = p.chromium.launch(headless=True) | |
| page = browser.new_page() | |
| # Handle dialogs (alerts) | |
| page.on("dialog", lambda dialog: (print(f"DIALOG: {dialog.message}"), dialog.dismiss())) | |
| # Capture console logs | |
| page.on("console", lambda msg: print(f"PAGE LOG: {msg.text}")) | |
| page.on("pageerror", lambda err: print(f"PAGE ERROR: {err}")) | |
| # Navigate to frontend | |
| print("Navigating to frontend...") | |
| page.goto("http://localhost:5173", wait_until="networkidle") | |
| # Login | |
| print("Logging in...") | |
| page.fill("input[placeholder='admin or user']", "admin") | |
| page.fill("input[placeholder='••••••••']", "admin123") | |
| page.click("button:has-text('Login')") | |
| page.wait_for_selector("text=Dashboard", timeout=20000) | |
| # Verify Title | |
| print(f"Page title: {page.title()}") | |
| assert "BIAF-offASR" in page.content() or "Translation" in page.content() or "Offline" in page.content() | |
| # Navigate to Text Translate | |
| print("Checking Text Translate...") | |
| page.click("text=Text Translate") | |
| page.wait_for_selector("textarea", timeout=20000) | |
| # Perform a translation | |
| print("Testing translation UI...") | |
| page.fill("textarea", "Hello world") | |
| # Wait a bit for React to update state | |
| time.sleep(1) | |
| # Click Translate | |
| print("Clicking Translate button...") | |
| translate_btn = page.locator("button.btn-primary:has-text('Translate')") | |
| print(f"Button visible: {translate_btn.is_visible()}") | |
| print(f"Button enabled: {translate_btn.is_enabled()}") | |
| translate_btn.click() | |
| # Wait for result to appear | |
| print("Waiting for translation result...") | |
| try: | |
| # We expect [CI MOCK] in the output | |
| page.wait_for_selector("text=[CI MOCK]", timeout=30000) | |
| print("Translation successful!") | |
| # Verify detected language badge appears | |
| if "Detected:" in page.content(): | |
| print("Detected language badge found!") | |
| except Exception as e: | |
| print(f"Translation failed or timed out: {e}") | |
| page.screenshot(path="e2e_failure.png") | |
| print("Screenshot saved to e2e_failure.png") | |
| # Log the output area specifically | |
| output_content = page.locator(".output-box").inner_text() | |
| print(f"Output box content: '{output_content}'") | |
| raise e | |
| browser.close() | |
| finally: | |
| # Cleanup processes | |
| print("Backend logs:") | |
| if os.path.exists("backend.log"): | |
| with open("backend.log", "r") as f: | |
| print(f.read()) | |
| print("Frontend logs:") | |
| if os.path.exists("frontend.log"): | |
| with open("frontend.log", "r") as f: | |
| print(f.read()) | |
| try: | |
| os.killpg(os.getpgid(backend_proc.pid), signal.SIGTERM) | |
| except ProcessLookupError: | |
| pass | |
| try: | |
| os.killpg(os.getpgid(frontend_proc.pid), signal.SIGTERM) | |
| except ProcessLookupError: | |
| pass | |
| print("Servers stopped.") | |
| if __name__ == "__main__": | |
| test_full_app_flow() | |