#!/usr/bin/env node /** * Runtime smoke test: connect to Node-RED WebSocket debug and verify * that key nodes are producing output within a timeout period. */ const http = require('http'); const TIMEOUT_MS = 15000; const NR_URL = 'http://localhost:1880'; async function fetchJSON(url) { return new Promise((resolve, reject) => { http.get(url, res => { const chunks = []; res.on('data', c => chunks.push(c)); res.on('end', () => { try { resolve(JSON.parse(Buffer.concat(chunks))); } catch (e) { reject(new Error(`Parse error from ${url}: ${e.message}`)); } }); }).on('error', reject); }); } (async () => { const errors = []; // REST-based checks: verify Node-RED is healthy console.log('=== Runtime Health Checks ==='); try { const settings = await fetchJSON(`${NR_URL}/settings`); console.log('PASS: Node-RED is responding, version:', settings.editorTheme ? 'custom' : 'default'); } catch (e) { console.log('FAIL: Node-RED not responding:', e.message); errors.push('Node-RED not responding'); } // Check that flows are loaded try { const flows = await fetchJSON(`${NR_URL}/flows`); const wwtp = flows.filter(n => n.z === 'demo_tab_wwtp'); if (wwtp.length > 50) { console.log(`PASS: ${wwtp.length} nodes loaded on WWTP tab`); } else { console.log(`FAIL: Only ${wwtp.length} nodes on WWTP tab (expected >50)`); errors.push('Too few nodes'); } } catch (e) { console.log('FAIL: Cannot read flows:', e.message); errors.push('Cannot read flows'); } // Check inject nodes are running (they have repeat timers) try { const flows = await fetchJSON(`${NR_URL}/flows`); const injects = flows.filter(n => n.type === 'inject' && n.repeat && n.z === 'demo_tab_wwtp'); console.log(`PASS: ${injects.length} inject nodes with timers on WWTP tab`); // Verify the q_in inject nodes are still there const qinInjects = injects.filter(n => n.id.includes('_flow') || n.id.includes('_tick')); console.log(`PASS: ${qinInjects.length} q_in/tick inject timers active`); } catch (e) { console.log('FAIL: Cannot check inject nodes:', e.message); errors.push('Cannot check inject nodes'); } console.log('\n=== RESULT ==='); if (errors.length === 0) { console.log('ALL RUNTIME CHECKS PASSED'); } else { console.log(`${errors.length} FAILURE(S):`, errors.join(', ')); process.exit(1); } })().catch(err => { console.error('Runtime check failed:', err.message); process.exit(1); });