Spaces:
Running
Running
| /** | |
| * Batch widget render verification — mimics a real PDF/DOCX export's | |
| * _renderWidgets() call to /api/render_charts with several widgets. | |
| * Confirms the shared singleton browser handles concurrent pages correctly. | |
| */ | |
| const http = require('http'); | |
| const BASE = process.env.BASE_URL || 'http://localhost:17861'; | |
| function chartWidget(title, type, labels) { | |
| return { | |
| type: 'chart', | |
| title, | |
| html: `<div style="width:650px;height:300px;"><canvas id="c"></canvas></div> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script> | |
| <script>new Chart(document.getElementById("c"),{type:"${type}",data:{labels:${JSON.stringify(labels)},datasets:[{data:[3,5,2,4]}]},options:{animation:false}});</script>` | |
| }; | |
| } | |
| function mermaidWidget(title, def) { | |
| return { | |
| type: 'mermaid', | |
| title, | |
| html: `<div class="mermaid">${def}</div> | |
| <script type="module"> | |
| import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs'; | |
| mermaid.initialize({ startOnLoad: true, theme: 'default' }); | |
| </script>` | |
| }; | |
| } | |
| const widgets = [ | |
| chartWidget('bar', 'bar', ['A', 'B', 'C']), | |
| chartWidget('line', 'line', ['1', '2', '3']), | |
| chartWidget('pie', 'pie', ['X', 'Y', 'Z']), | |
| mermaidWidget('flow', 'graph TD\n A[Start] --> B{Check}\n B -->|Yes| C[Go]\n B -->|No| D[Stop]'), | |
| chartWidget('doughnut', 'doughnut', ['P', 'Q']), | |
| ]; | |
| const body = JSON.stringify({ widgets, theme: 'light' }); | |
| const started = Date.now(); | |
| const req = http.request({ | |
| hostname: 'localhost', | |
| port: 17861, | |
| path: '/api/render_charts', | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, | |
| timeout: 180000, | |
| }, (res) => { | |
| const chunks = []; | |
| res.on('data', (c) => chunks.push(c)); | |
| res.on('end', () => { | |
| const elapsed = ((Date.now() - started) / 1000).toFixed(2); | |
| const data = JSON.parse(Buffer.concat(chunks).toString()); | |
| const results = data.results || []; | |
| const ok = results.filter((r) => r.success).length; | |
| console.log(`HTTP ${res.statusCode} in ${elapsed}s: ${ok}/${results.length} widgets OK`); | |
| for (const r of results) { | |
| console.log(` [${r.index}] ${r.type}/${r.title}: ${r.success ? 'OK len=' + r.dataUrl.length : 'FAIL ' + (r.error || '')}`); | |
| } | |
| }); | |
| }); | |
| req.on('error', (e) => { console.error('ERR', e.message); process.exit(1); }); | |
| req.write(body); | |
| req.end(); | |