Files
ohm_streaming/test_watchlist_e2e.py
2026-02-28 09:22:57 +00:00

304 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
End-to-end Playwright tests for watchlist integration
Tests: /watchlist page functionality - filters, settings, scheduler, refresh
"""
import asyncio
import json
from pathlib import Path
from playwright.async_api import async_playwright
BASE_URL = "http://localhost:3000"
EVIDENCE_DIR = Path(".sisyphus/evidence")
EVIDENCE_DIR.mkdir(parents=True, exist_ok=True)
async def main():
# First get auth token
import httpx
resp = httpx.post(
f"{BASE_URL}/api/auth/login",
json={"username": "e2etest", "password": "password123"},
)
token_data = resp.json()
token = token_data.get("access_token")
user = token_data.get("user", {})
print(f"Got token for user: {user.get('username')}")
async with async_playwright() as p:
browser = await p.chromium.launch(
args=["--no-sandbox", "--disable-setuid-sandbox"]
)
context = await browser.new_context(viewport={"width": 1920, "height": 1080})
page = await context.new_page()
# Set auth BEFORE navigation
await page.add_init_script(f"""
window.localStorage.setItem('auth_token', '{token}');
window.localStorage.setItem('user', '{json.dumps(user)}');
""")
results = []
# Test 1: Navigate to /watchlist
print("\n=== Test 1: Navigate to /watchlist ===")
await page.goto(f"{BASE_URL}/watchlist")
await page.wait_for_load_state("networkidle")
await page.wait_for_timeout(2000)
await page.screenshot(
path=str(EVIDENCE_DIR / "01_watchlist_page.png"), full_page=True
)
title = await page.title()
url = page.url
page_loaded = "Watchlist" in title and "login" not in url.lower()
results.append(("Navigate to /watchlist", page_loaded))
print(f"Page title: {title}, URL: {url}")
# Test 2: Verify watchlist tab is active (highlighted)
print("\n=== Test 2: Verify watchlist tab highlighted ===")
active_tab = await page.query_selector(
'button.tab.active:has-text("Watchlist")'
)
is_active = active_tab is not None
await page.screenshot(
path=str(EVIDENCE_DIR / "02_tab_highlighted.png"), full_page=True
)
results.append(("Watchlist tab highlighted", is_active))
# Test 3: Verify header/nav matches other tabs
print("\n=== Test 3: Verify header/nav ===")
header = await page.query_selector("h1")
tabs = await page.query_selector_all(".tabs .tab")
has_header = header is not None
has_tabs = len(tabs) >= 4
await page.screenshot(
path=str(EVIDENCE_DIR / "03_header_nav.png"), full_page=True
)
results.append(("Header/nav present", has_header and has_tabs))
print(f"Found {len(tabs)} tabs, header: {has_header}")
# Test 4: Verify scheduler panel displays correctly
print("\n=== Test 4: Verify scheduler panel ===")
scheduler = await page.query_selector(
'.scheduler-status, #schedulerStatus, [class*="scheduler"]'
)
has_scheduler = scheduler is not None
start_btn = await page.query_selector(
'#startSchedulerBtn, [onclick*="startScheduler"]'
)
stop_btn = await page.query_selector(
'#stopSchedulerBtn, [onclick*="stopScheduler"]'
)
check_btn = await page.query_selector(
'[onclick*="CheckAll"], button:has-text("Vérifier")'
)
await page.screenshot(
path=str(EVIDENCE_DIR / "04_scheduler_panel.png"), full_page=True
)
results.append(("Scheduler panel displays", has_scheduler))
print(
f"Scheduler: {has_scheduler}, Start btn: {start_btn is not None}, Stop btn: {stop_btn is not None}, Check btn: {check_btn is not None}"
)
# Test 5: Test filter tabs (All/Active/Paused/Completed)
print("\n=== Test 5: Test filter tabs ===")
filter_tabs = await page.query_selector_all(
'.filter-tabs .filter-tab, [class*="filter-tab"]'
)
await page.screenshot(
path=str(EVIDENCE_DIR / "05_filter_tabs.png"), full_page=True
)
filter_names = []
for i, tab in enumerate(filter_tabs):
try:
tab_text = await tab.text_content()
filter_names.append(tab_text.strip())
await tab.click()
await page.wait_for_timeout(500)
except Exception as e:
print(f"Error clicking filter {i}: {e}")
await page.screenshot(
path=str(EVIDENCE_DIR / "05_filters_clicked.png"), full_page=True
)
results.append(("Filter tabs present and clickable", len(filter_tabs) >= 4))
print(f"Found filter tabs: {filter_names}")
# Test 6: Test settings modal
print("\n=== Test 6: Test settings modal ===")
settings_btn = await page.query_selector(
'button:has-text("Paramètres"), button:has-text("Settings"), [onclick*="settings"]'
)
if settings_btn:
await settings_btn.click()
await page.wait_for_timeout(1000)
await page.screenshot(
path=str(EVIDENCE_DIR / "06_settings_open.png"), full_page=True
)
# Close modal - try multiple methods
modal_closed = False
for selector in [
"#settingsModal button[onclick*='closeSettingsModal']",
"#settingsModal button:has-text('×')",
'button:has-text("Fermer")',
'button:has-text("Close")',
]:
try:
close_btn = await page.query_selector(selector)
if close_btn:
await close_btn.click()
modal_closed = True
break
except:
continue
# If still not closed, evaluate JS to close
if not modal_closed:
try:
await page.evaluate("closeSettingsModal()")
modal_closed = True
except:
pass
if not modal_closed:
await page.keyboard.press("Escape")
modal_closed = False
for selector in [
"#settingsModal button.close",
'[class*="modal"] .close',
'button:has-text("Fermer")',
'button:has-text("Close")',
]:
try:
close_btn = await page.query_selector(selector)
if close_btn:
await close_btn.click()
modal_closed = True
break
except:
continue
if not modal_closed:
await page.keyboard.press("Escape")
await page.wait_for_timeout(1000)
await page.screenshot(
path=str(EVIDENCE_DIR / "06_settings_closed.png"), full_page=True
)
results.append(("Settings modal works", True))
print("Settings modal opened and closed")
else:
await page.screenshot(
path=str(EVIDENCE_DIR / "06_settings_not_found.png"), full_page=True
)
results.append(("Settings modal works", False))
print("Settings button not found")
# Test 7: Verify 30-second status refresh
print("\n=== Test 7: Check for refresh interval ===")
page_content = await page.content()
has_refresh = "setInterval" in page_content
has_scheduler_interval = (
"loadSchedulerStatus" in page_content or "scheduler" in page_content.lower()
)
await page.screenshot(
path=str(EVIDENCE_DIR / "07_refresh_check.png"), full_page=True
)
results.append(
("Refresh mechanism present", has_refresh or has_scheduler_interval)
)
print(
f"Has setInterval: {has_refresh}, Has scheduler refresh: {has_scheduler_interval}"
)
# Test 8: Test tab switching
print("\n=== Test 8: Test tab switching ===")
try:
# Force close any modal first
await page.keyboard.press("Escape")
await page.wait_for_timeout(500)
home_tab = await page.query_selector('button.tab:has-text("Accueil")')
if home_tab:
await home_tab.click()
await page.wait_for_timeout(1000)
await page.screenshot(
path=str(EVIDENCE_DIR / "08_home_tab.png"), full_page=True
)
watchlist_tab = await page.query_selector(
'button.tab:has-text("Watchlist")'
)
if watchlist_tab:
await watchlist_tab.click()
await page.wait_for_timeout(1000)
await page.screenshot(
path=str(EVIDENCE_DIR / "08_back_to_watchlist.png"), full_page=True
)
results.append(("Tab switching works", True))
except Exception as e:
print(f"Tab switching error: {e}")
results.append(("Tab switching works", False))
# Test 9: Direct /web#watchlist URL
print("\n=== Test 9: Test /web#watchlist URL ===")
await page.goto(f"{BASE_URL}/web#watchlist")
await page.wait_for_load_state("networkidle")
await page.wait_for_timeout(2000)
await page.screenshot(
path=str(EVIDENCE_DIR / "09_web_hash_watchlist.png"), full_page=True
)
watchlist_content = await page.query_selector(
".watchlist-container, #watchlistContainer"
)
results.append(
("/web#watchlist loads watchlist", watchlist_content is not None)
)
# Test 10: Test /watchlist redirect
print("\n=== Test 10: Verify /watchlist returns content ===")
await page.goto(f"{BASE_URL}/watchlist")
await page.wait_for_load_state("networkidle")
content = await page.content()
has_watchlist_content = (
"watchlist" in content.lower() and "ma watchlist" in content.lower()
)
results.append(("/watchlist page has content", has_watchlist_content))
# Print results
print("\n" + "=" * 60)
print("TEST RESULTS:")
print("=" * 60)
passed = 0
for name, result in results:
status = "PASS" if result else "FAIL"
print(f"[{status}] {name}")
if result:
passed += 1
print("=" * 60)
print(f"Total: {passed}/{len(results)} tests passed")
# Save results
with open(EVIDENCE_DIR / "test_results.txt", "w") as f:
f.write("Watchlist Integration Test Results\n")
f.write("=" * 60 + "\n")
for name, result in results:
status = "PASS" if result else "FAIL"
f.write(f"[{status}] {name}\n")
f.write("=" * 60 + "\n")
f.write(f"Total: {passed}/{len(results)} tests passed\n")
await browser.close()
return passed >= len(results) * 0.8
if __name__ == "__main__":
success = asyncio.run(main())
exit(0 if success else 1)