From bac09bee029b4096171a7adb360f220c86e3fa84 Mon Sep 17 00:00:00 2001 From: Deploy Bot Date: Mon, 25 May 2026 21:12:29 +0100 Subject: [PATCH] feat(dashboard): add SPA tab screenshot capture for visual testing --- tests/scripts/capture-dashboard-tabs.cjs | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/scripts/capture-dashboard-tabs.cjs diff --git a/tests/scripts/capture-dashboard-tabs.cjs b/tests/scripts/capture-dashboard-tabs.cjs new file mode 100644 index 0000000..2c301ee --- /dev/null +++ b/tests/scripts/capture-dashboard-tabs.cjs @@ -0,0 +1,81 @@ +const { chromium } = require('playwright'); +const fs = require('fs'); +const path = require('path'); + +(async () => { + const browser = await chromium.launch({ + headless: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const context = await browser.newContext({ + viewport: { width: 1280, height: 720 } + }); + + const page = await context.newPage(); + + const targetUrl = process.env.TARGET_URL || 'http://host.docker.internal:3003'; + + // Set up error capturing BEFORE navigation + const consoleLogs = []; + page.on('console', msg => { + if (msg.type() === 'error') { + consoleLogs.push(`[${msg.type()}] ${msg.text()}`); + } + }); + + const networkErrors = []; + page.on('requestfailed', request => { + const url = request.url(); + if (!url.includes('favicon')) { + networkErrors.push(`[${request.failure().errorText}] ${url}`); + } + }); + + console.log(`Navigating to ${targetUrl}`); + await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 30000 }); + + // Wait for page to load + await page.waitForTimeout(2000); + + // Create directories + const baselineDir = path.join(__dirname, '../visual/dashboard-tabs/baseline'); + const currentDir = path.join(__dirname, '../visual/dashboard-tabs/current'); + fs.mkdirSync(baselineDir, { recursive: true }); + fs.mkdirSync(currentDir, { recursive: true }); + + // Tab definitions matching the actual dashboard switchTab calls + const tabs = [ + { id: 'overview', name: 'overview' }, + { id: 'agents', name: 'all_agents' }, + { id: 'history', name: 'timeline' }, + { id: 'recommendations', name: 'recommendations' }, + { id: 'heatmap', name: 'heatmap' }, + { id: 'impact', name: 'impact' }, + ]; + + for (const tab of tabs) { + console.log(`Switching to ${tab.name} tab...`); + + await page.click(`button[onclick="switchTab('${tab.id}')"]`); + await page.waitForTimeout(1500); + + const screenshotPath = path.join(currentDir, `${tab.name}_desktop.png`); + await page.screenshot({ path: screenshotPath, fullPage: false }); + + const stats = fs.statSync(screenshotPath); + console.log(` Screenshot saved: ${screenshotPath} (${stats.size} bytes)`); + } + + await browser.close(); + + console.log('\n═══════════════════════════════════════════════════════════'); + console.log(' Dashboard Tab Screenshots'); + console.log('═══════════════════════════════════════════════════════════'); + console.log(` Target: ${targetUrl}`); + console.log(` Tabs: ${tabs.length}`); + console.log(` Output: ${currentDir}`); + console.log(` Console errors: ${networkErrors.length} (favicon excluded)`); + console.log(` Network errors: ${networkErrors.length}`); + console.log('═══════════════════════════════════════════════════════════'); +})();