chore: update watchlist features and fixes

This commit is contained in:
root
2026-02-28 09:22:57 +00:00
parent 4c96d0c1c5
commit 20bcc75b9b
64 changed files with 5193 additions and 77 deletions
+303
View File
@@ -0,0 +1,303 @@
#!/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)