Files
APAW/agent-evolution/scripts/dashboard-smoke-test.ts
Deploy Bot 9b0f160587 feat(dashboard): unified data pipeline, verified benchmarks, and browser testing
- build-standalone-fixed.cjs: reads from 4 real sources (agents md, kilo-meta.json, model-benchmarks-verified.json, agent-versions.json); computes recommendations dynamically
- build-standalone-direct.cjs: direct data export + HTML embed pipeline
- dashboard-smoke-test.ts: Playwright E2E smoke test covering all 6 tabs
- model-benchmarks-verified.json: verified IF scores from artificialanalysis.ai for 15 models (SWE-bench unverifiable → null)
- agent-versions.json: 347 git history entries extracted for 34 agents
- kilo-meta.json: prompt-optimizer → qwen3.5-122b, memory-manager → deepseek-v4-pro-max
- index.html: Recommendations tab rendering updated for dynamic data
- Dockerfile + docker-compose.yml: mount-driven build, no image rebuild for data changes
- README.md: updated dashboard docs and verified benchmark sources
2026-05-25 21:05:14 +01:00

169 lines
4.7 KiB
TypeScript

#!/usr/bin/env bun
/**
* Dashboard smoke test - navigates all tabs and reports console errors.
* Run: bun run agent-evolution/scripts/dashboard-smoke-test.ts
*/
import { chromium, type Page } from 'playwright';
const TARGET = process.env.TARGET_URL || 'http://localhost:3003';
interface TabResult {
name: string;
selector: string;
errors: string[];
checks: string[];
}
async function clickTab(page: Page, tabId: string): Promise<void> {
await page.click(`button[onclick="switchTab('${tabId}')"]`);
await page.waitForTimeout(800);
}
async function runChecks(page: Page, tabId: string, checks: string[]): Promise<string[]> {
const results: string[] = [];
for (const check of checks) {
try {
const el = await page.$(check);
results.push(el ? `${check}` : ` ❌ MISSING: ${check}`);
} catch (e) {
results.push(` ❌ ERROR: ${check} | ${String(e).slice(0, 80)}`);
}
}
return results;
}
async function main() {
console.log(`Dashboard Smoke Test - ${TARGET}\n`);
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ viewport: { width: 1280, height: 720 } });
const page = await context.newPage();
const allErrors: string[] = [];
const allWarnings: string[] = [];
page.on('console', msg => {
const t = msg.type();
const txt = msg.text();
if (t === 'error') allErrors.push(txt);
else if (t === 'warning') allWarnings.push(txt);
});
page.on('pageerror', err => {
allErrors.push(`PAGE ERROR: ${err.message} ${err.stack?.slice(0, 200) || ''}`);
});
page.on('requestfailed', req => {
const url = req.url();
if (!url.includes('favicon')) {
allErrors.push(`NETWORK: ${req.method()} ${url} | ${req.failure()?.errorText}`);
}
});
// --- Tab definitions ---
const tabs = [
{
name: 'Overview',
id: 'overview',
checks: [
'#statsRow .stat-card',
'#recentTimeline .timeline-item',
'#recAgents .agent-card',
],
},
{
name: 'All Agents',
id: 'agents',
checks: [
'#agentsByCategory .category-section',
'#agentSearch',
'.agents-grid .agent-card',
],
},
{
name: 'Timeline',
id: 'history',
checks: [
'#fullTimeline .timeline-item',
'.timeline-wrap .timeline-title',
],
},
{
name: 'Recommendations',
id: 'recommendations',
checks: [
'#allRecommendations .rec-card',
],
},
{
name: 'Heatmap',
id: 'heatmap',
/* Note: heatmap uses hmTable which may throw if model_benchmarks is empty */
checks: [
'#hmTable tbody tr',
'.hm-legend-track',
],
},
// Impact tab is NOT in tab bar (click is on onclick="switchTab('impact')")
{
name: 'Impact',
id: 'impact',
checks: [
'#agentScoreChart',
'#modelDistChart',
'#migrationImpactChart',
],
},
];
const results: TabResult[] = [];
for (const tab of tabs) {
await page.goto(`${TARGET}/`, { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForTimeout(1500);
if (tab.id !== 'overview') {
await clickTab(page, tab.id);
}
const checks = await runChecks(page, tab.id, tab.checks);
results.push({
name: tab.name,
selector: tab.id,
errors: [...allErrors],
checks,
});
allErrors.length = 0;
allWarnings.length = 0;
}
await browser.close();
// --- Report ---
console.log('═══════════════════════════════════════════════════');
console.log(' Smoke Test Results');
console.log('═══════════════════════════════════════════════════\n');
let totalIssues = 0;
for (const r of results) {
const issues = r.errors.filter(e => !e.includes('favicon'));
totalIssues += issues.length;
console.log(`\n[${r.name}]`);
console.log(r.checks.join('\n'));
if (issues.length > 0) {
console.log(' ❌ Console errors:');
issues.forEach(e => console.log(` ${e.slice(0, 120)}`));
}
}
console.log('\n═══════════════════════════════════════════════════');
console.log(` Total issues: ${totalIssues}`);
console.log('═══════════════════════════════════════════════════');
process.exit(totalIssues > 0 ? 1 : 0);
}
main().catch(e => { console.error(e); process.exit(1); });