// Exercise production bundles first, then loaded charts with isolated API fixtures. // The fixtures replace only the inference transport and never enter the app build. const { chromium } = require('playwright'); const { build } = require('esbuild'); const { createServer } = require('node:http'); const { readFile, mkdir } = require('node:fs/promises'); const path = require('node:path'); const assert = require('node:assert/strict'); const modelId = 'g413b-lmon-exp-207-x'; const model = { model_id: modelId, num_layers: 3, layer_types: ['attention', 'attention', 'attention'] }; const distribution = { instr_t: 0.35, instr_d1: 0.05, instr_d2: 0.05, data_t: 0.3, data_d1: 0.05, prompt: 0.1, lemon: 0.1 }; const spans = Object.keys(distribution).map((category, i) => ({ id: category, category, label: category, token_start: i, token_end: i + 1, })); const kvGroups = [0, 1].map(group_index => ({ group_index, num_heads: 2, dominant_category: 'instr_t', category_distribution: distribution, })); const prefill = { model, spans, attention_by_layer: Object.fromEntries(model.layer_types.map((layer_type, layer_index) => [layer_index, layer_type !== 'attention' ? { layer_type, layer_index, metrics: null, kv_groups: null } : { layer_type, layer_index, metrics: { ifr: 0.8, das: 0.75, leak: 0.2 }, span_attention_normalized: distribution, kv_groups: kvGroups, head_focus: ['instr_t', 'instr_t', 'data_t', 'instr_d1'], head_strength: [0.8, 0.7, 0.6, 0.5], }, ])), }; const generated = { model, spans, generated_tokens: ['12', '<|open_end|>'], attention_per_step: ['12', '<|open_end|>'].map((token, step_index) => ({ token, step_index, span_attention_normalized: distribution, })), }; const views = [ { id: 1, name: 'Layer Focus', required: ['Layer heatmap', 'Attention per span', 'KV-head groups', 'Metrics'] }, { id: 2, name: 'Generation Flow', required: ['Flow view', 'Attention distribution'] }, { id: 3, name: 'Failure Diagnosis', required: ['How outcome is computed', 'Layer chart', 'Head specialization', 'Diagnosis cards'] }, ]; (async () => { const fixtureExample = JSON.parse((await readFile(path.join(__dirname, 'new_dlb_examples.jsonl'), 'utf8')).trim().split('\n')[2]); const staticRoot = path.join(__dirname, 'src/static'); const server = createServer(async (request, response) => { const pathname = new URL(request.url, 'http://local').pathname; const file = path.resolve(staticRoot, '.' + (pathname === '/' ? '/index.html' : pathname)); if (!file.startsWith(staticRoot + path.sep)) { response.writeHead(403).end(); return; } try { const mime = { '.js': 'application/javascript', '.css': 'text/css', '.html': 'text/html', '.woff': 'font/woff', '.woff2': 'font/woff2' }; response.setHeader('Content-Type', mime[path.extname(file)] || 'application/octet-stream'); response.end(await readFile(file)); } catch { response.writeHead(404).end(); } }); await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); let browser; try { browser = await chromium.launch({ headless: true, executablePath: process.env.LLMON_CHROMIUM_PATH }); const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } }); const errors = []; page.on('pageerror', error => errors.push(error.message)); let fixtures = false; let inferenceCalls = 0; await page.route('**/api/**', async route => { const endpoint = new URL(route.request().url()).pathname; let json; switch (endpoint) { case '/api/health': json = { model_ready: fixtures, message: 'No test model configured' }; break; case '/api/models/list': json = { active_ids: fixtures ? [modelId] : [], model_meta: { [modelId]: { label: 'Test LLMON', color: '#a56eff' } }, }; break; case '/api/data/examples': json = fixtures ? [{ id: 0, instruction: fixtureExample.instruction }] : []; break; case '/api/data/example/0': json = { ...fixtureExample, llmon_prompt: fixtureExample.llmon_prompt_dirty }; break; case '/api/attention/prefill': inferenceCalls++; json = prefill; break; case '/api/attention/generate': inferenceCalls++; json = generated; break; case '/api/benchmark/results': inferenceCalls++; json = { results: [] }; break; default: throw new Error(`Unexpected API request: ${endpoint}`); } await route.fulfill({ json }); }); const base = `http://127.0.0.1:${server.address().port}`; async function checkHelpButtons() { const names = await page.locator('button[aria-haspopup="dialog"]').evaluateAll(elements => elements.map(e => e.getAttribute('aria-label'))); assert(names.length > 0, 'Expected help buttons'); const calls = inferenceCalls; for (const name of names) { const trigger = page.getByRole('button', { name, exact: true }); await trigger.scrollIntoViewIfNeeded(); await trigger.focus(); await trigger.press('Enter'); const dialog = page.getByRole('dialog', { name, exact: true }); await dialog.waitFor(); const box = await dialog.boundingBox(); const viewport = page.viewportSize(); assert(box && box.x >= 0 && box.y >= 0 && box.x + box.width <= viewport.width + 1 && box.y + box.height <= viewport.height + 1, `Help out of viewport: ${name} ${JSON.stringify({ box, viewport })}`); assert(await dialog.evaluate(e => e.scrollWidth <= e.clientWidth + 1), `Help content overflows: ${name}`); assert((await dialog.innerText()).length > 80, `Empty help: ${name}`); await page.keyboard.press('Escape'); await dialog.waitFor({ state: 'detached' }); assert(await trigger.evaluate(e => e === document.activeElement), 'Escape should restore trigger focus'); await trigger.click(); await page.getByRole('button', { name: `Close ${name}`, exact: true }).click(); await dialog.waitFor({ state: 'detached' }); assert(await page.locator('#root').evaluate(e => e.childElementCount > 0), 'Opening help must not blank the app'); } assert.equal(inferenceCalls, calls, 'Opening help must not trigger inference'); return names; } // This fails on the shipped createPortal regression, without model access. await page.goto(base + '/experiment_1/index.html', { waitUntil: 'networkidle' }); await checkHelpButtons(); assert.deepEqual(errors, []); console.log('Production bundles: help opens without model access or a page crash.'); fixtures = true; for (const view of views) { const html = await readFile(path.join(__dirname, `frontend/experiment_${view.id}/index.html`), 'utf8'); const source = html.match(/