257 lines
11 KiB
Python
257 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
WEVAL Playwright NonReg — visual regression + JS error detection
|
|
Outputs JSON for consumption by nonreg-api.php
|
|
Tests: WEVADS IA, Homepage, OpenClaw, Ethica, DeerFlow, WEVIA
|
|
"""
|
|
import json, sys, time
|
|
|
|
try:
|
|
from playwright.sync_api import sync_playwright
|
|
except ImportError:
|
|
print(json.dumps({"error": "playwright not installed"}))
|
|
sys.exit(1)
|
|
|
|
results = []
|
|
|
|
def test(name, fn):
|
|
t0 = time.time()
|
|
try:
|
|
detail = fn()
|
|
results.append({"name": name, "status": "PASS", "ms": round((time.time()-t0)*1000), "detail": detail})
|
|
except Exception as e:
|
|
results.append({"name": name, "status": "FAIL", "ms": round((time.time()-t0)*1000), "detail": str(e)[:200]})
|
|
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch(headless=True, args=['--no-sandbox','--disable-dev-shm-usage'])
|
|
|
|
# ═══ WEVADS IA — the critical one (black screen regression) ═══
|
|
def test_wevads():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://weval-consulting.com/wevads-ia/", wait_until="networkidle", timeout=15000)
|
|
time.sleep(2)
|
|
# Check sidebar visible
|
|
sb = page.evaluate("() => { const el = document.querySelector('.sidebar, [class*=sidebar], #sidebar, nav'); return el ? getComputedStyle(el).display : 'NOT_FOUND'; }")
|
|
# Check main content visible
|
|
ma = page.evaluate("() => { const el = document.querySelector('.main, [class*=main], main, #main, .content'); return el ? getComputedStyle(el).display : 'NOT_FOUND'; }")
|
|
# Check key functions exist
|
|
go_fn = page.evaluate("() => typeof window.go === 'function'")
|
|
enter_fn = page.evaluate("() => typeof window.enter === 'function'")
|
|
dollar_fn = page.evaluate("() => typeof window.$ === 'function'")
|
|
ctx.close()
|
|
|
|
if js_errors:
|
|
raise Exception(f"{len(js_errors)} JS errors: {js_errors[0]}")
|
|
|
|
parts = []
|
|
if sb not in ['none','NOT_FOUND']: parts.append(f"SB={sb}")
|
|
else: raise Exception(f"sidebar display={sb}")
|
|
if ma not in ['none','NOT_FOUND']: parts.append(f"MA={ma}")
|
|
else: raise Exception(f"main display={ma}")
|
|
parts.append(f"go={'Y' if go_fn else 'N'}")
|
|
parts.append(f"enter={'Y' if enter_fn else 'N'}")
|
|
parts.append(f"$={'Y' if dollar_fn else 'N'}")
|
|
parts.append(f"JS_errors=0")
|
|
return ", ".join(parts)
|
|
|
|
test("PW WEVADS-IA dashboard", test_wevads)
|
|
|
|
# ═══ HOMEPAGE ═══
|
|
def test_homepage():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://weval-consulting.com/", wait_until="networkidle", timeout=15000)
|
|
title = page.title()
|
|
hero = page.query_selector("h1, .hero, [class*=hero]")
|
|
ctx.close()
|
|
if js_errors: raise Exception(f"{len(js_errors)} JS errors")
|
|
return f"title={title[:40]}, hero={'Y' if hero else 'N'}, JS=0"
|
|
|
|
test("PW Homepage", test_homepage)
|
|
|
|
# ═══ OPENCLAW ═══
|
|
def test_openclaw():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://weval-consulting.com/openclaw.html", wait_until="networkidle", timeout=15000)
|
|
time.sleep(1)
|
|
sidebar = page.query_selector(".sidebar, [class*=sidebar]")
|
|
providers = page.evaluate("() => document.querySelectorAll('.provider-btn, [class*=provider]').length")
|
|
ctx.close()
|
|
if js_errors: raise Exception(f"{len(js_errors)} JS errors")
|
|
return f"sidebar={'Y' if sidebar else 'N'}, providers={providers}, JS=0"
|
|
|
|
test("PW OpenClaw", test_openclaw)
|
|
|
|
# ═══ ETHICA ═══
|
|
def test_ethica():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://ethica.wevup.app/ethica-app-v3.html", wait_until="networkidle", timeout=15000)
|
|
title = page.title()
|
|
ctx.close()
|
|
if js_errors: raise Exception(f"{len(js_errors)} JS errors")
|
|
return f"title={title[:40]}, JS=0"
|
|
|
|
test("PW Ethica dashboard", test_ethica)
|
|
|
|
# ═══ DEERFLOW ═══
|
|
def test_deerflow():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
resp = page.goto("https://weval-consulting.com/deerflow/", wait_until="networkidle", timeout=15000)
|
|
ctx.close()
|
|
if resp.status >= 400: raise Exception(f"HTTP {resp.status}")
|
|
return f"HTTP {resp.status}, JS_errors={len(js_errors)}"
|
|
|
|
test("PW DeerFlow", test_deerflow)
|
|
|
|
# ═══ CRONS MONITOR ═══
|
|
def test_monitor():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://weval-consulting.com/crons-monitor.html", wait_until="networkidle", timeout=15000)
|
|
time.sleep(1)
|
|
tabs = page.evaluate("() => document.querySelectorAll('.tab').length")
|
|
ctx.close()
|
|
if js_errors: raise Exception(f"{len(js_errors)} JS errors")
|
|
return f"tabs={tabs}, JS=0"
|
|
|
|
test("PW Crons Monitor", test_monitor)
|
|
|
|
# ═══ CRM ═══
|
|
def test_crm():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://weval-consulting.com/crm.html", wait_until="networkidle", timeout=15000)
|
|
ctx.close()
|
|
if js_errors: raise Exception(f"{len(js_errors)} JS errors")
|
|
return f"JS=0"
|
|
|
|
test("PW CRM", test_crm)
|
|
|
|
# ═══ WEVIA WIDGET ═══
|
|
def test_widget():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://weval-consulting.com/wevia-widget.html", wait_until="networkidle", timeout=15000)
|
|
input_el = page.query_selector("input, textarea, [contenteditable]")
|
|
ctx.close()
|
|
if js_errors: raise Exception(f"{len(js_errors)} JS errors")
|
|
return f"input={'Y' if input_el else 'N'}, JS=0"
|
|
|
|
test("PW WEVIA Widget", test_widget)
|
|
|
|
# ═══ NODE --CHECK on WEVADS SPA (JS syntax) ═══
|
|
def test_node_check():
|
|
import subprocess
|
|
# Download the SPA and extract JS
|
|
r = subprocess.run(["node", "--check", "/var/www/html/wevads-ia/index.html"],
|
|
capture_output=True, text=True, timeout=10)
|
|
# node --check won't work on HTML, so extract inline JS
|
|
import re
|
|
html = open("/var/www/html/wevads-ia/index.html").read()
|
|
scripts = re.findall(r'<script[^>]*>(.*?)</script>', html, re.DOTALL)
|
|
total_js = sum(len(s) for s in scripts)
|
|
# Write combined JS to temp file
|
|
combined = "\n".join(scripts)
|
|
with open("/tmp/wevads-check.js", "w") as f:
|
|
f.write(combined)
|
|
r = subprocess.run(["node", "--check", "/tmp/wevads-check.js"],
|
|
capture_output=True, text=True, timeout=10)
|
|
if r.returncode != 0:
|
|
raise Exception(f"Syntax error: {r.stderr[:150]}")
|
|
return f"0 syntax errors, {len(scripts)} scripts, {total_js} chars"
|
|
|
|
test("PW WEVADS node --check", test_node_check)
|
|
|
|
|
|
# ═══ 502 REGRESSION TESTS — SSO protected routes ═══
|
|
def test_wevia_cyber():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
resp = page.goto("https://weval-consulting.com/wevia-cyber", wait_until="networkidle", timeout=15000)
|
|
status = resp.status
|
|
ctx.close()
|
|
# 302 = SSO redirect (OK), 502 = REGRESSION!
|
|
if status == 502: raise Exception("502 Bad Gateway REGRESSION!")
|
|
if status == 503: raise Exception("503 Service Unavailable!")
|
|
return f"HTTP {status} (SSO redirect OK)"
|
|
|
|
test("PW wevia-cyber (502 guard)", test_wevia_cyber)
|
|
|
|
def test_wevia_monitor():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
resp = page.goto("https://weval-consulting.com/wevia-monitor", wait_until="networkidle", timeout=15000)
|
|
status = resp.status
|
|
ctx.close()
|
|
if status == 502: raise Exception("502 Bad Gateway REGRESSION!")
|
|
if status == 503: raise Exception("503 Service Unavailable!")
|
|
return f"HTTP {status} (SSO redirect OK)"
|
|
|
|
test("PW wevia-monitor (502 guard)", test_wevia_monitor)
|
|
|
|
def test_wevia_go_live():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
resp = page.goto("https://weval-consulting.com/wevia-go-live.html", wait_until="networkidle", timeout=15000)
|
|
status = resp.status
|
|
ctx.close()
|
|
if status >= 500: raise Exception(f"HTTP {status} SERVER ERROR!")
|
|
return f"HTTP {status}"
|
|
|
|
test("PW wevia-go-live (502 guard)", test_wevia_go_live)
|
|
|
|
# ═══ TEST REPORT PAGES — ensure they load ═══
|
|
def test_nonreg_dashboard():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
js_errors = []
|
|
page.on("pageerror", lambda e: js_errors.append(str(e)[:100]))
|
|
page.goto("https://weval-consulting.com/test-report/full-nonreg-dashboard.html", wait_until="networkidle", timeout=15000)
|
|
ctx.close()
|
|
if js_errors: raise Exception(f"{len(js_errors)} JS errors")
|
|
return f"JS=0"
|
|
|
|
test("PW NonReg Dashboard", test_nonreg_dashboard)
|
|
|
|
def test_visual_proof():
|
|
ctx = browser.new_context(viewport={"width": 1280, "height": 800}, ignore_https_errors=True)
|
|
page = ctx.new_page()
|
|
page.goto("https://weval-consulting.com/test-report/visual-proof-report.html", wait_until="networkidle", timeout=15000)
|
|
images = page.evaluate("() => document.querySelectorAll('img').length")
|
|
ctx.close()
|
|
return f"{images} images loaded"
|
|
|
|
test("PW Visual Proof Report", test_visual_proof)
|
|
|
|
browser.close()
|
|
|
|
passed = sum(1 for r in results if r["status"] == "PASS")
|
|
failed = len(results) - passed
|
|
|
|
print(json.dumps({
|
|
"pass": passed,
|
|
"fail": failed,
|
|
"total": len(results),
|
|
"tests": results
|
|
}))
|