127 lines
5.9 KiB
Python
127 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""WEVIA Playwright Visual Test Runner — Screenshot all capabilities"""
|
|
import asyncio, json, time, os, sys
|
|
from playwright.async_api import async_playwright
|
|
|
|
SSDIR = "/var/www/html/test-report/screenshots"
|
|
RESULTS_FILE = "/var/www/html/test-report/playwright-results.json"
|
|
BASE = "https://weval-consulting.com"
|
|
os.makedirs(SSDIR, exist_ok=True)
|
|
|
|
# Test definitions: (id, label, message, wait_seconds)
|
|
TESTS = [
|
|
("greeting", "👋 Greeting", "Bonjour, presente WEVAL Consulting en 3 phrases", 12),
|
|
("pdf-audit", "📄 PDF Audit Cyber", "Genere un PDF audit cybersecurite pour une PME marocaine", 45),
|
|
("pdf-cdc", "📋 PDF Cahier des Charges", "Genere un cahier des charges pour un projet ERP SAP migration", 45),
|
|
("swot", "📊 SWOT", "Analyse SWOT de la transformation digitale bancaire au Maroc", 45),
|
|
("ishikawa", "🔬 Ishikawa", "Diagramme Ishikawa causes-effets probleme de stock en entreprise", 45),
|
|
("porter", "📈 Porter", "5 forces de Porter pour le marche du cloud computing au Maghreb", 45),
|
|
("mermaid", "📐 Mermaid Schema", "Schema mermaid du processus achats en 5 etapes", 45),
|
|
("python", "🐍 Python ETL", "Ecris un pipeline ETL Python complet avec pandas pour traiter un CSV", 40),
|
|
("react", "⚛️ React Dashboard", "Cree un composant React dashboard KPI avec 4 cartes et graphique", 40),
|
|
("image", "🎨 Image Art", "Genere une image artistique futuriste de smart city au Maroc", 12),
|
|
("logo", "✏️ Logo SVG", "Genere 4 variantes logo pour DataVision startup IA au Maroc", 40),
|
|
("websearch", "🌐 Web Search", "Quelles sont les dernieres actualites au Maroc cette semaine ?", 20),
|
|
("consulting", "🏢 SAP vs Oracle", "Compare SAP S/4HANA vs Oracle Fusion Cloud ERP en 5 criteres", 45),
|
|
("skills", "🧠 Skills", "Quelles sont tes 20 competences completes ?", 15),
|
|
("long-content", "📝 Long Content", "Ecris un article complet de 1500 mots sur la transformation digitale des banques au Maroc avec introduction, 5 parties et conclusion", 60),
|
|
]
|
|
|
|
async def run_tests(test_ids=None):
|
|
results = []
|
|
async with async_playwright() as pw:
|
|
browser = await pw.chromium.launch(headless=True, args=["--no-sandbox", "--disable-dev-shm-usage"])
|
|
ctx = await browser.new_context(viewport={"width": 1400, "height": 900})
|
|
page = await ctx.new_page()
|
|
|
|
# Login
|
|
print("🔐 Login...")
|
|
await page.goto(f"{BASE}/login.html", wait_until="networkidle", timeout=15000)
|
|
await page.fill('#user', "yacine")
|
|
await page.fill('#pass', "YacineWeval2026")
|
|
await page.click("button")
|
|
await page.wait_for_timeout(3000)
|
|
|
|
# Go to WEVIA
|
|
print("🏠 WEVIA...")
|
|
await page.goto(f"{BASE}/wevia-ia/wevia.html", wait_until="networkidle", timeout=15000)
|
|
await page.wait_for_timeout(2000)
|
|
await page.screenshot(path=f"{SSDIR}/pw-home.png")
|
|
|
|
for tid, label, msg, wait in TESTS:
|
|
if test_ids and tid not in test_ids:
|
|
continue
|
|
|
|
print(f"🧪 {label}...")
|
|
t0 = time.time()
|
|
try:
|
|
# Click "Nouvelle discussion" to start fresh
|
|
try:
|
|
new_btn = page.locator("text=Nouvelle discussion").first
|
|
if await new_btn.is_visible(timeout=2000):
|
|
await new_btn.click()
|
|
await page.wait_for_timeout(1500)
|
|
except:
|
|
pass
|
|
|
|
# Find and fill input
|
|
inp = page.locator("textarea, input[placeholder*='question'], input[placeholder*='message'], #messageInput, .chat-input").first
|
|
await page.wait_for_timeout(3000)
|
|
await inp.fill(msg, force=True)
|
|
await page.wait_for_timeout(300)
|
|
|
|
# Send
|
|
try:
|
|
send = page.locator("button.send-btn, #sendBtn, button[type='submit'], .send-message, button:has(svg[viewBox])").first
|
|
await send.click(timeout=3000)
|
|
except:
|
|
await inp.press("Enter")
|
|
|
|
# Wait for response
|
|
await page.wait_for_timeout(wait * 1000)
|
|
|
|
# Scroll to bottom of chat
|
|
await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
|
|
await page.wait_for_timeout(500)
|
|
|
|
# Screenshot
|
|
ss_path = f"{SSDIR}/pw-{tid}.png"
|
|
await page.screenshot(path=ss_path, full_page=False)
|
|
|
|
elapsed = round(time.time() - t0, 1)
|
|
results.append({
|
|
"id": tid, "label": label, "status": "pass",
|
|
"time": elapsed, "screenshot": f"pw-{tid}.png",
|
|
"message": msg
|
|
})
|
|
print(f" ✅ {label} ({elapsed}s)")
|
|
|
|
except Exception as e:
|
|
elapsed = round(time.time() - t0, 1)
|
|
results.append({
|
|
"id": tid, "label": label, "status": "error",
|
|
"time": elapsed, "error": str(e)[:200],
|
|
"screenshot": None, "message": msg
|
|
})
|
|
print(f" ❌ {label}: {e}")
|
|
|
|
await browser.close()
|
|
|
|
# Save results
|
|
output = {
|
|
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
"total": len(results),
|
|
"pass": sum(1 for r in results if r["status"] == "pass"),
|
|
"fail": sum(1 for r in results if r["status"] != "pass"),
|
|
"tests": results
|
|
}
|
|
with open(RESULTS_FILE, "w") as f:
|
|
json.dump(output, f, ensure_ascii=False)
|
|
print(f"\n{'✅' if output['fail']==0 else '⚠️'} {output['pass']}/{output['total']} — Results: {RESULTS_FILE}")
|
|
return output
|
|
|
|
if __name__ == "__main__":
|
|
# Accept test IDs as args: python3 pw-tests.py greeting pdf-audit swot
|
|
test_ids = sys.argv[1:] if len(sys.argv) > 1 else None
|
|
asyncio.run(run_tests(test_ids))
|