112 lines
6.9 KiB
HTML
112 lines
6.9 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||
<title>WEVAL — NonReg OPUS</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Outfit:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root{--bg:#080b12;--surface:rgba(255,255,255,.03);--border:rgba(255,255,255,.06);--text:#94a3b8;--white:#f1f5f9;--accent:#6366f1;--teal:#00c896;--red:#ef4444;--gold:#f0c674;--r:12px}
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
body{font-family:"Outfit",system-ui,sans-serif;background:var(--bg);color:var(--text);font-size:15px;min-height:100vh}
|
||
.wrap{max-width:900px;margin:0 auto;padding:2rem 4%}
|
||
.hero{text-align:center;padding:3rem 0 2rem}
|
||
.badge{display:inline-block;background:rgba(99,102,241,.1);color:var(--accent);padding:6px 18px;border-radius:20px;font-size:.72rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;margin-bottom:1rem}
|
||
h1{font-size:2rem;font-weight:800;color:var(--white);margin-bottom:.5rem}
|
||
h1 em{color:var(--teal);font-style:normal}
|
||
.sub{color:var(--text);font-size:.95rem;margin-bottom:2rem}
|
||
.stats{display:flex;gap:1rem;justify-content:center;flex-wrap:wrap;margin-bottom:2rem}
|
||
.stat{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:.8rem 1.5rem;text-align:center}
|
||
.stat-num{font-family:"Space Mono";font-size:1.8rem;font-weight:700;color:var(--white)}
|
||
.stat-label{font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;margin-top:.2rem}
|
||
.stat.pass .stat-num{color:var(--teal)}
|
||
.stat.fail .stat-num{color:var(--red)}
|
||
.stat.total .stat-num{color:var(--accent)}
|
||
.btn-run{display:inline-flex;align-items:center;gap:8px;background:var(--accent);color:#fff;border:none;padding:16px 40px;border-radius:var(--r);font-family:inherit;font-size:1rem;font-weight:700;cursor:pointer;transition:.2s;margin-bottom:2rem}
|
||
.btn-run:hover{opacity:.9;transform:translateY(-1px)}
|
||
.btn-run:disabled{opacity:.5;cursor:not-allowed;transform:none}
|
||
.btn-run .spin{display:none;width:18px;height:18px;border:2px solid rgba(255,255,255,.3);border-top:2px solid #fff;border-radius:50%;animation:spin .8s linear infinite}
|
||
.btn-run.loading .spin{display:inline-block}
|
||
.btn-run.loading .play{display:none}
|
||
@keyframes spin{to{transform:rotate(360deg)}}
|
||
.output{background:rgba(0,0,0,.4);border:1px solid var(--border);border-radius:var(--r);padding:1.5rem;font-family:"Space Mono",monospace;font-size:.78rem;line-height:1.7;white-space:pre-wrap;max-height:70vh;overflow-y:auto;display:none}
|
||
.output.show{display:block}
|
||
.output .pass{color:#22c55e}
|
||
.output .fail{color:#ef4444}
|
||
.output .warn{color:#f59e0b}
|
||
.output .section{color:var(--accent);font-weight:700}
|
||
.output .header{color:var(--gold);font-weight:700}
|
||
.result-bar{display:none;margin:1.5rem 0;padding:1.5rem;border-radius:var(--r);text-align:center}
|
||
.result-bar.allpass{display:block;background:linear-gradient(135deg,rgba(34,197,94,.1),rgba(34,197,94,.05));border:1px solid rgba(34,197,94,.3)}
|
||
.result-bar.hasfail{display:block;background:linear-gradient(135deg,rgba(239,68,68,.1),rgba(239,68,68,.05));border:1px solid rgba(239,68,68,.3)}
|
||
.result-bar h2{font-size:1.5rem;margin-bottom:.3rem}
|
||
.result-bar.allpass h2{color:var(--teal)}
|
||
.result-bar.hasfail h2{color:var(--red)}
|
||
.ts{font-size:.75rem;color:#64748b;margin-top:1rem}
|
||
footer{text-align:center;padding:2rem;color:var(--text);font-size:.8rem;border-top:1px solid var(--border);margin-top:2rem}
|
||
footer a{color:var(--accent);text-decoration:none}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
<div class="hero">
|
||
<div class="badge">Quality Assurance</div>
|
||
<h1>NonReg <em>OPUS</em></h1>
|
||
<p class="sub">62 tests automatisés — IA, Sécurité, Audit, Pages, APIs</p>
|
||
<div class="stats">
|
||
<div class="stat total"><div class="stat-num" id="s-total">—</div><div class="stat-label">Tests</div></div>
|
||
<div class="stat pass"><div class="stat-num" id="s-pass">—</div><div class="stat-label">Pass</div></div>
|
||
<div class="stat fail"><div class="stat-num" id="s-fail">—</div><div class="stat-label">Fail</div></div>
|
||
</div>
|
||
<button class="btn-run" id="runBtn" onclick="runTests()">
|
||
<span class="play">▶</span>
|
||
<span class="spin"></span>
|
||
Lancer les tests
|
||
</button>
|
||
</div>
|
||
<div class="result-bar" id="resultBar"><h2 id="resultText"></h2><p id="resultDetail" style="color:var(--text);font-size:.85rem"></p></div>
|
||
<div class="output" id="output"></div>
|
||
<div class="ts" id="timestamp"></div>
|
||
</div>
|
||
<footer>
|
||
<a href="/">WEVAL Consulting</a> · <a href="/products/workspace.html">Workspace</a> · <a href="/pricing.html">Tarifs</a>
|
||
<br><small style="color:#475569">NonReg OPUS v2 — 62 tests — Architecture 3 serveurs (S204+S95+S151)</small>
|
||
· <a href="/trust-center.html">Trust Center</a> · <a href="/solution-finder.html">Solution Finder</a></footer>
|
||
<script>
|
||
async function runTests(){
|
||
const btn=document.getElementById("runBtn");
|
||
const out=document.getElementById("output");
|
||
const bar=document.getElementById("resultBar");
|
||
btn.classList.add("loading");btn.disabled=true;
|
||
out.className="output show";out.innerHTML="⏳ Exécution des 62 tests en cours...\n\n";
|
||
bar.className="result-bar";
|
||
document.getElementById("s-total").textContent="...";
|
||
document.getElementById("s-pass").textContent="...";
|
||
document.getElementById("s-fail").textContent="...";
|
||
try{
|
||
const r=await fetch("/api/nonreg-opus.php?k=WEVADS2026");
|
||
const txt=await r.text();
|
||
// Parse and colorize
|
||
let html=txt
|
||
.replace(/^(=+.*)$/gm,"<span class=\"header\">$1</span>")
|
||
.replace(/^(---.*---)$/gm,"<span class=\"section\">$1</span>")
|
||
.replace(/(✓[^\n]*)/g,"<span class=\"pass\">$1</span>")
|
||
.replace(/(✗[^\n]*)/g,"<span class=\"fail\">$1</span>")
|
||
.replace(/(⚠[^\n]*)/g,"<span class=\"warn\">$1</span>")
|
||
.replace(/(100%[^<]*ALL PASS)/g,"<span class=\"pass\" style=\"font-size:1.1em;font-weight:700\">$1</span>");
|
||
out.innerHTML=html;
|
||
// Extract counts
|
||
const pm=txt.match(/(\d+) PASS/);const fm=txt.match(/(\d+) FAIL/);const tm=txt.match(/(\d+) tests/);
|
||
const p=pm?parseInt(pm[1]):0;const f=fm?parseInt(fm[1]):0;const t=tm?parseInt(tm[1]):0;
|
||
document.getElementById("s-total").textContent=t;
|
||
document.getElementById("s-pass").textContent=p;
|
||
document.getElementById("s-fail").textContent=f;
|
||
if(f===0){bar.className="result-bar allpass";document.getElementById("resultText").textContent="✅ 100% — 6σ — ALL PASS";document.getElementById("resultDetail").textContent=p+" tests passés avec succès";}
|
||
else{bar.className="result-bar hasfail";document.getElementById("resultText").textContent="⚠️ "+f+" FAILS";document.getElementById("resultDetail").textContent=p+"/"+t+" tests passés";}
|
||
}catch(e){out.innerHTML="<span class=\"fail\">❌ Erreur: "+e.message+"</span>";}
|
||
btn.classList.remove("loading");btn.disabled=false;
|
||
document.getElementById("timestamp").textContent="Dernière exécution: "+new Date().toLocaleString("fr-FR");
|
||
}
|
||
</script>
|
||
</body>
|
||
</html> |