import { chromium } from 'playwright'; import * as fs from 'fs'; const BASE_URL = 'http://localhost:3001'; const SCREENSHOTS_DIR = '/Users/messili/codebase/polyglot-alpha/ui/screenshots/factcheck'; async function main() { const browser = await chromium.launch(); const results = []; try { // ===== PAGE 1: HOME / console.log('Checking home page...'); const homePage = await browser.newPage({ viewport: { width: 1920, height: 1080 } }); await homePage.goto(BASE_URL); await homePage.waitForLoadState('networkidle'); await homePage.waitForTimeout(500); // Claim 1: LIVE/MOCK chip try { const modeButtons = await homePage.locator('button').filter({ hasText: /LIVE|MOCK/ }).first(); const visible = await modeButtons.isVisible().catch(() => false); const text = visible ? await modeButtons.textContent() : 'NOT_FOUND'; results.push({ claim: 1, status: visible ? 'TRUE' : 'FALSE', evidence: `Button: "${text}"` }); } catch (e) { results.push({ claim: 1, status: 'FALSE', evidence: 'Selector error' }); } // Claim 2: 5 flags try { const flags = await homePage.locator('img').filter({ hasText: /flag|language|lang/ }).all(); results.push({ claim: 2, status: flags.length >= 5 ? 'TRUE' : 'PARTIAL', evidence: `Found ${flags.length} flags` }); } catch { results.push({ claim: 2, status: 'FALSE', evidence: 'No flag elements found' }); } // Claim 3: Hero text const heroText = await homePage.locator('main h1, main h2').first().textContent().catch(() => ''); const hasHero = heroText.toLowerCase().includes('decentralized') && heroText.toLowerCase().includes('cross-language'); results.push({ claim: 3, status: hasHero ? 'TRUE' : 'FALSE', evidence: `Text: "${heroText.substring(0, 60)}..."` }); // Claim 4: Trigger demo buttons try { const triggerBtn = await homePage.locator('button').filter({ hasText: /Trigger|Demo|Start/ }).first(); const visible = await triggerBtn.isVisible().catch(() => false); const text = visible ? await triggerBtn.textContent() : 'NOT_FOUND'; results.push({ claim: 4, status: visible ? 'TRUE' : 'FALSE', evidence: `Button: "${text}"` }); } catch { results.push({ claim: 4, status: 'FALSE', evidence: 'No trigger button found' }); } // Claim 5: Mermaid diagram try { const mermaid = await homePage.locator('svg').first(); const visible = await mermaid.isVisible().catch(() => false); results.push({ claim: 5, status: visible ? 'PARTIAL' : 'FALSE', evidence: `Diagram visible: ${visible}` }); } catch { results.push({ claim: 5, status: 'FALSE', evidence: 'No diagram found' }); } // Claim 6: React Flow DAG try { const nodes = await homePage.locator('[class*="node"]').all(); results.push({ claim: 6, status: nodes.length === 11 ? 'TRUE' : 'PARTIAL', evidence: `Found ${nodes.length} nodes (expected 11)` }); } catch { results.push({ claim: 6, status: 'FALSE', evidence: 'No DAG found' }); } // Claim 7: Why now / Problem section try { const section = await homePage.locator('h2, h3').filter({ hasText: /Why|Problem/ }).first(); const visible = await section.isVisible().catch(() => false); results.push({ claim: 7, status: visible ? 'TRUE' : 'FALSE', evidence: `Section visible: ${visible}` }); } catch { results.push({ claim: 7, status: 'FALSE', evidence: 'No section found' }); } // Claim 8: Contract addresses try { const contracts = await homePage.locator('span, code').filter({ hasText: /0x[a-f0-9]/ }).all(); results.push({ claim: 8, status: contracts.length >= 5 ? 'TRUE' : 'PARTIAL', evidence: `Found ${contracts.length} contracts` }); } catch { results.push({ claim: 8, status: 'FALSE', evidence: 'No contracts found' }); } await homePage.screenshot({ path: `${SCREENSHOTS_DIR}/home.png` }); await homePage.close(); // ===== PAGE 2: /ABOUT console.log('Checking about page...'); const aboutPage = await browser.newPage({ viewport: { width: 1920, height: 1080 } }); await aboutPage.goto(`${BASE_URL}/about`); await aboutPage.waitForLoadState('networkidle'); // Claim 9: 5-phase pipeline try { const text = await aboutPage.locator('main').textContent(); const phases = (text.match(/phase/gi) || []).length; results.push({ claim: 9, status: phases >= 5 ? 'TRUE' : 'FALSE', evidence: `Found ${phases} phase mentions` }); } catch { results.push({ claim: 9, status: 'FALSE', evidence: 'Error reading text' }); } // Claim 10: How it works section try { const section = await aboutPage.locator('h2, h3').filter({ hasText: /How/ }).first(); const visible = await section.isVisible().catch(() => false); const text = visible ? await section.textContent() : 'NOT_FOUND'; results.push({ claim: 10, status: visible ? 'TRUE' : 'FALSE', evidence: `Section: "${text}"` }); } catch { results.push({ claim: 10, status: 'FALSE', evidence: 'No section found' }); } // Claim 11: Glossary try { const items = await aboutPage.locator('[class*="glossary"], [class*="component"], dl dt, li').all(); results.push({ claim: 11, status: items.length >= 11 ? 'TRUE' : 'PARTIAL', evidence: `Found ${items.length} items` }); } catch { results.push({ claim: 11, status: 'FALSE', evidence: 'No glossary found' }); } await aboutPage.screenshot({ path: `${SCREENSHOTS_DIR}/about.png` }); await aboutPage.close(); // ===== PAGE 3: /OPERATORS console.log('Checking operators page...'); const operatorsPage = await browser.newPage({ viewport: { width: 1920, height: 1080 } }); await operatorsPage.goto(`${BASE_URL}/operators`); await operatorsPage.waitForLoadState('networkidle'); // Claim 12: 3 seeder cards try { const cards = await operatorsPage.locator('[class*="card"], div[role="article"]').all(); results.push({ claim: 12, status: cards.length >= 3 ? 'TRUE' : 'PARTIAL', evidence: `Found ${cards.length} cards` }); } catch { results.push({ claim: 12, status: 'FALSE', evidence: 'No cards found' }); } // Claim 13: wins/bids 26% try { const winsBids = await operatorsPage.locator('text=/wins|bids/i').first(); const visible = await winsBids.isVisible().catch(() => false); results.push({ claim: 13, status: visible ? 'TRUE' : 'FALSE', evidence: `Visible: ${visible}` }); } catch { results.push({ claim: 13, status: 'FALSE', evidence: 'No wins/bids found' }); } // Claim 14: EMA dashed border try { const ema = await operatorsPage.locator('text=/EMA/').first(); const visible = await ema.isVisible().catch(() => false); results.push({ claim: 14, status: visible ? 'PARTIAL' : 'FALSE', evidence: `EMA visible: ${visible}` }); } catch { results.push({ claim: 14, status: 'FALSE', evidence: 'No EMA found' }); } // Claim 15: Buttons try { const allBtns = await operatorsPage.locator('button').all(); const btnTexts = await Promise.all(allBtns.slice(0, 20).map(b => b.textContent().catch(() => ''))); const hasAll = btnTexts.join('').includes('Claim') && btnTexts.join('').includes('Withdraw') && btnTexts.join('').includes('Register'); results.push({ claim: 15, status: hasAll ? 'TRUE' : 'PARTIAL', evidence: `Button count: ${allBtns.length}` }); } catch { results.push({ claim: 15, status: 'FALSE', evidence: 'Error checking buttons' }); } await operatorsPage.screenshot({ path: `${SCREENSHOTS_DIR}/operators.png` }); await operatorsPage.close(); // ===== PAGE 4: EVENT DETAIL console.log('Checking event detail...'); const eventsPage = await browser.newPage({ viewport: { width: 1920, height: 1080 } }); await eventsPage.goto(`${BASE_URL}/events`); await eventsPage.waitForLoadState('networkidle'); // Try to find event const eventLink = await eventsPage.locator('a').filter({ hasText: /[0-9]/ }).first(); let eventUrl = null; try { eventUrl = await eventLink.getAttribute('href'); } catch {} if (eventUrl) { const fullUrl = eventUrl.startsWith('/') ? BASE_URL + eventUrl : BASE_URL + '/' + eventUrl; console.log(`Opening event: ${fullUrl}`); const eventPage = await browser.newPage({ viewport: { width: 1920, height: 1080 } }); await eventPage.goto(fullUrl); await eventPage.waitForLoadState('networkidle'); await eventPage.waitForTimeout(1000); // Claim 16: Judge dossier try { const judges = await eventPage.locator('tr, [class*="judge"]').all(); const count = judges.length; results.push({ claim: 16, status: count >= 11 ? 'TRUE' : 'PARTIAL', evidence: `Found ${count} judge rows` }); } catch { results.push({ claim: 16, status: 'FALSE', evidence: 'No judges found' }); } // Claim 17: Attestation tx try { const tx = await eventPage.locator('span, code').filter({ hasText: /0xsim/ }).first(); const visible = await tx.isVisible().catch(() => false); results.push({ claim: 17, status: visible ? 'PARTIAL' : 'FALSE', evidence: `Tx visible: ${visible}` }); } catch { results.push({ claim: 17, status: 'FALSE', evidence: 'No tx found' }); } // Claim 18: Dossier button try { const btn = await eventPage.locator('button').filter({ hasText: /dossier|raw|JSON/i }).first(); const visible = await btn.isVisible().catch(() => false); results.push({ claim: 18, status: visible ? 'TRUE' : 'FALSE', evidence: `Button visible: ${visible}` }); } catch { results.push({ claim: 18, status: 'FALSE', evidence: 'No button found' }); } // Claim 19: IPFS link try { const ipfs = await eventPage.locator('text=/ipfs:/i').first(); const visible = await ipfs.isVisible().catch(() => false); results.push({ claim: 19, status: visible ? 'PARTIAL' : 'FALSE', evidence: `IPFS visible: ${visible}` }); } catch { results.push({ claim: 19, status: 'FALSE', evidence: 'No IPFS found' }); } // Claim 20: API payload button try { const btn = await eventPage.locator('button').filter({ hasText: /API|Payload/ }).first(); const visible = await btn.isVisible().catch(() => false); results.push({ claim: 20, status: visible ? 'TRUE' : 'FALSE', evidence: `Button visible: ${visible}` }); } catch { results.push({ claim: 20, status: 'FALSE', evidence: 'No button found' }); } // Claim 21: Fee split try { const fees = await eventPage.locator('[class*="fee"], tr').all(); results.push({ claim: 21, status: fees.length >= 2 ? 'TRUE' : 'PARTIAL', evidence: `Found ${fees.length} fee items` }); } catch { results.push({ claim: 21, status: 'FALSE', evidence: 'No fees found' }); } // Claim 22: Debate panel try { const panel = await eventPage.locator('[class*="debate"], [class*="agent"]').first(); const visible = await panel.isVisible().catch(() => false); results.push({ claim: 22, status: visible ? 'PARTIAL' : 'FALSE', evidence: `Panel visible: ${visible}` }); } catch { results.push({ claim: 22, status: 'FALSE', evidence: 'No debate panel found' }); } const filename = eventUrl.split('/').pop(); await eventPage.screenshot({ path: `${SCREENSHOTS_DIR}/event-${filename}.png` }); await eventPage.close(); } await eventsPage.close(); } catch (error) { console.error('Script error:', error.message); } finally { await browser.close(); } // Output results console.log('\n===== FACT-CHECK RESULTS =====\n'); results.forEach((r) => { console.log(`${r.claim}. Status: ${r.status} | ${r.evidence}`); }); fs.writeFileSync(`${SCREENSHOTS_DIR}/factcheck-results.json`, JSON.stringify(results, null, 2)); console.log(`\nResults saved.`); } main().catch(console.error);