- real-fit-engine.py: refactored to support --from-report, improved Ollama v1/chat/completions compatibility, agent name normalization - run-focused-eval.py: run evaluations for specific agent/model pairs from CLI - test_ollama_minimal.py/test_real_api.py: Ollama API connectivity tests - real-fit-architecture.md: architecture overview document - tests/scripts/: E2E landing test, analytics capture, evolution heatmap verification - Remove real-fit-recalc.py (superseded by --from-report flag)
90 lines
3.3 KiB
JavaScript
90 lines
3.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Quick capture + element check for Analytics Hierarchy Section
|
|
*/
|
|
|
|
const { chromium } = require('playwright');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const TARGET_URL = process.env.TARGET_URL || 'http://localhost:3002';
|
|
const OUTPUT_DIR = process.env.OUTPUT_DIR || '/app/tests/visual/current';
|
|
|
|
(async () => {
|
|
if (!fs.existsSync(OUTPUT_DIR)) {
|
|
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
}
|
|
|
|
const browser = await chromium.launch({
|
|
headless: true,
|
|
args: ['--disable-setuid-sandbox', '--no-sandbox'],
|
|
});
|
|
|
|
const page = await browser.newPage({
|
|
viewport: { width: 1280, height: 900 },
|
|
});
|
|
|
|
console.log(`Navigating to: ${TARGET_URL}`);
|
|
await page.goto(TARGET_URL, { waitUntil: 'networkidle', timeout: 60000 });
|
|
await page.waitForTimeout(3000);
|
|
|
|
// Scroll to "Аналитическая иерархия"
|
|
const heading = page.locator('text=Аналитическая иерархия').first();
|
|
if (await heading.isVisible().catch(() => false)) {
|
|
console.log('Scrolling to Аналитическая иерархия section...');
|
|
await heading.scrollIntoViewIfNeeded();
|
|
await page.evaluate(() => window.scrollBy(0, -60));
|
|
await page.waitForTimeout(1500);
|
|
} else {
|
|
console.log('Heading not found, fallback scroll');
|
|
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight / 3));
|
|
await page.waitForTimeout(1500);
|
|
}
|
|
|
|
// Scroll further down to reveal cards 3 and 4 (heatmap, commands table)
|
|
await page.evaluate(() => window.scrollBy(0, 900));
|
|
await page.waitForTimeout(1000);
|
|
|
|
const screenshotPath = path.join(OUTPUT_DIR, 'analytics_section.png');
|
|
await page.screenshot({ path: screenshotPath, fullPage: false });
|
|
console.log(`Screenshot saved to: ${screenshotPath}`);
|
|
|
|
// Check for each card's evidence (use Russian text as it appears in the page)
|
|
const checks = [
|
|
{ label: 'Model tree with collapsible categories', text: 'Модели → Категории → Агенты' },
|
|
{ label: 'Category bars', text: 'Дистрибуция по категориям' },
|
|
{ label: 'Fit-score heatmap', text: 'Fit-score распределение' },
|
|
{ label: 'Commands table', text: 'Команды' },
|
|
];
|
|
|
|
const results = { visible: {}, issues: [] };
|
|
|
|
for (const c of checks) {
|
|
const found = await page.locator(`text=${c.text}`).first().isVisible({ timeout: 3000 }).catch(() => false);
|
|
if (found) {
|
|
const textContent = await page.locator(`text=${c.text}`).first().textContent({ timeout: 3000 }).catch(() => '');
|
|
results.visible[c.label] = textContent;
|
|
} else {
|
|
results.issues.push(`${c.label} (searching text "${c.text}") — NOT FOUND`);
|
|
}
|
|
}
|
|
|
|
const reportPath = path.join(OUTPUT_DIR, 'analytics_section_report.json');
|
|
fs.writeFileSync(reportPath, JSON.stringify(results, null, 2));
|
|
console.log(`Report saved to: ${reportPath}`);
|
|
|
|
// Also write summary to stdout
|
|
console.log('\n=== Scan Results ===');
|
|
if (Object.keys(results.visible).length === 4) {
|
|
console.log('All 4 analytics cards are visible.');
|
|
} else {
|
|
console.log(`Visible: ${Object.keys(results.visible).join(', ')}`);
|
|
console.log(`Missing: ${results.issues.join(', ')}`);
|
|
}
|
|
|
|
await browser.close();
|
|
})().catch((err) => {
|
|
console.error('Fatal error:', err);
|
|
process.exit(1);
|
|
});
|