Files
weval-l99/l99-deep-visual.py
2026-04-13 12:43:21 +02:00

161 lines
7.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""L99 DEEP VISUAL TEST — 3 pages with screenshots, video, UX overlap detection"""
import json, time, os, urllib.request, urllib.parse
SITE = "https://weval-consulting.com"
GROQ_KEY = os.popen("grep GROQ_KEY /etc/weval/secrets.env | cut -d= -f2").read().strip()
SNAP_DIR = "/opt/weval-l99/screenshots/deep-visual-12avr"
VID_DIR = "/opt/weval-l99/videos"
LOG = "/opt/weval-l99/logs/l99-deep-visual.json"
os.makedirs(SNAP_DIR, exist_ok=True)
os.makedirs(VID_DIR, exist_ok=True)
PAGES = [
("/agents-archi.html", "agents-archi", 15000),
("/enterprise-model.html", "enterprise-model", 10000),
("/wevia-meeting-rooms.html", "meeting-rooms", 8000),
]
results = []
def log_r(name, status, detail=""):
results.append({"name": name, "status": status, "detail": detail[:200], "ts": time.strftime("%H:%M:%S")})
icon = {"P": "\u2705", "F": "\u274c", "W": "\u26a0"}.get(status, "?")
print(f" {icon} {name}: {detail[:100]}", flush=True)
try:
from playwright.sync_api import sync_playwright
with sync_playwright() as pw:
br = pw.chromium.launch(headless=True, args=["--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage"])
# Login
print("== LOGIN ==", flush=True)
cx = br.new_context(
viewport={"width": 1920, "height": 1080},
ignore_https_errors=True,
record_video_dir=VID_DIR,
record_video_size={"width": 1920, "height": 1080}
)
pg = cx.new_page()
pg.goto(f"{SITE}/login", timeout=15000)
pg.wait_for_timeout(1000)
pg.fill("input[name='user']", "yacine")
pg.fill("input[name='pass']", "Weval@2026")
pg.click("button[type='submit']")
pg.wait_for_timeout(3000)
log_r("login", "P" if "/login" not in pg.url else "F", pg.url[:60])
for path, name, wait_ms in PAGES:
print(f"\n== {name.upper()} ==", flush=True)
try:
pg.goto(f"{SITE}{path}", timeout=20000, wait_until="domcontentloaded")
pg.wait_for_timeout(wait_ms)
body = pg.evaluate("document.body.innerText.length") or 0
title = pg.title() or ""
log_r(f"{name}-load", "P" if body > 100 else "F", f"{body}ch title={title[:40]}")
# Full page screenshot
pg.screenshot(path=f"{SNAP_DIR}/{name}-full.png", full_page=True)
log_r(f"{name}-screenshot", "P", "full page captured")
# Viewport screenshot
pg.screenshot(path=f"{SNAP_DIR}/{name}-viewport.png")
log_r(f"{name}-viewport", "P", "viewport captured")
# UX overlap detection via JS
overlaps = pg.evaluate("""() => {
const els = document.querySelectorAll('div, span, a, button, h1, h2, h3, p, td');
const rects = [];
let overlaps = 0;
let details = [];
for (const el of els) {
const r = el.getBoundingClientRect();
if (r.width < 5 || r.height < 5 || r.top > 5000) continue;
const text = (el.innerText || '').trim().substring(0, 20);
if (!text) continue;
for (const prev of rects) {
if (r.left < prev.right && r.right > prev.left &&
r.top < prev.bottom && r.bottom > prev.top &&
Math.abs(r.left - prev.left) > 5) {
overlaps++;
if (details.length < 5) {
details.push(text + ' overlaps ' + prev.text);
}
}
}
rects.push({left: r.left, right: r.right, top: r.top, bottom: r.bottom, text: text});
}
return {count: overlaps, details: details};
}""")
overlap_count = overlaps.get("count", 0) if overlaps else 0
overlap_details = overlaps.get("details", []) if overlaps else []
if overlap_count > 10:
log_r(f"{name}-ux-overlap", "W", f"{overlap_count} overlaps: {'; '.join(overlap_details[:3])}")
else:
log_r(f"{name}-ux-overlap", "P", f"{overlap_count} overlaps (OK)")
# Check for JS errors
js_errors = pg.evaluate("""() => {
return window.__playwright_errors || [];
}""")
if js_errors and len(js_errors) > 0:
log_r(f"{name}-js-errors", "W", f"{len(js_errors)} JS errors")
else:
log_r(f"{name}-js-errors", "P", "0 JS errors")
# Check canvas/WebGL for agents-archi
if "archi" in name:
has_canvas = pg.evaluate("!!document.querySelector('canvas')")
log_r(f"{name}-3d-canvas", "P" if has_canvas else "F", f"Canvas: {has_canvas}")
# Check agent count
agent_count = pg.evaluate("""() => {
const cards = document.querySelectorAll('.ag-card, .agent-card, .room-card, [class*=agent], [class*=room]');
return cards.length;
}""")
log_r(f"{name}-agent-count", "P" if agent_count > 0 else "W", f"{agent_count} visible elements")
# Scroll test
pg.evaluate("window.scrollTo(0, document.body.scrollHeight)")
pg.wait_for_timeout(1000)
pg.screenshot(path=f"{SNAP_DIR}/{name}-bottom.png")
log_r(f"{name}-scroll", "P", "scrolled to bottom")
except Exception as e:
log_r(f"{name}-error", "F", str(e)[:100])
# Close + save video
pg.close()
cx.close()
br.close()
except Exception as e:
log_r("playwright", "F", str(e)[:100])
# Results
p = len([r for r in results if r["status"] == "P"])
f = len([r for r in results if r["status"] == "F"])
w = len([r for r in results if r["status"] == "W"])
t = len(results)
score = p * 100 // t if t else 0
print(f"\n{'='*60}", flush=True)
print(f"DEEP VISUAL: {p}/{t} ({score}%) | FAIL={f} WARN={w}", flush=True)
json.dump({"date": time.strftime("%Y-%m-%d %H:%M"), "pass": p, "fail": f, "warn": w, "total": t, "score": score, "results": results}, open(LOG, "w"), indent=2)
# Groq analysis of overlaps
if w > 0 and GROQ_KEY:
warns = "; ".join([f"{r['name']}: {r['detail']}" for r in results if r["status"] == "W"])
body_data = json.dumps({"model": "llama-3.3-70b-versatile", "messages": [{"role": "user", "content": f"UX visual test warns:\n{warns}\nDiagnose and suggest CSS fixes in 3 lines:"}], "max_tokens": 200}).encode()
req = urllib.request.Request("https://api.groq.com/openai/v1/chat/completions", body_data, {"Authorization": f"Bearer {GROQ_KEY}", "Content-Type": "application/json"})
try:
resp = json.loads(urllib.request.urlopen(req, timeout=15).read())
diag = resp["choices"][0]["message"]["content"]
print(f"\n\U0001f9e0 Groq UX: {diag}", flush=True)
except:
pass
print(f"\nScreenshots: {SNAP_DIR}/", flush=True)
print(f"Videos: {VID_DIR}/", flush=True)