const { spawn } = require('node:child_process');
const { Beam } = require('../pkg/beam.js');
const RELAY_PORT = 4990;
const HTTP_PORT = RELAY_PORT + 1;
function startRelay() {
return new Promise((resolve, reject) => {
const child = spawn('target/debug/beam', [
'start', '--port', String(RELAY_PORT),
'--memory-storage', 'true', '--redb-storage', 'false',
'--allow-public-space', 'true'
], {
cwd: __dirname + '/..',
stdio: ['ignore', 'pipe', 'pipe']
});
child.stdout.on('data', d => process.stderr.write('[relay] ' + d));
child.stderr.on('data', d => process.stderr.write('[relay] ' + d));
const net = require('node:net');
const deadline = Date.now() + 10000;
const tryConnect = () => {
const sock = net.connect(RELAY_PORT, '127.0.0.1');
sock.on('connect', () => { sock.destroy(); resolve(child); });
sock.on('error', () => {
if (Date.now() > deadline) reject(new Error('relay did not start'));
else setTimeout(tryConnect, 50);
});
};
tryConnect();
});
}
function fetchMetrics() {
return fetch(`http://127.0.0.1:${HTTP_PORT}/metrics`).then(r => r.json());
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
console.log('=== BEAM WASM Node.js Integration Test ===\n');
console.log('Starting relay on port', RELAY_PORT, '...');
const relay = await startRelay();
console.log('Relay started.');
const client1 = new Beam();
client1.connect(`ws://127.0.0.1:${RELAY_PORT}`);
const client2 = new Beam();
client2.connect(`ws://127.0.0.1:${RELAY_PORT}`);
console.log('Waiting for WebSocket connections...');
await sleep(1000);
const c1Received = [];
const c2Received = [];
client1.on('chat', (v) => { c1Received.push(v); console.log(' client1 received:', v); });
client2.on('chat', (v) => { c2Received.push(v); console.log(' client2 received:', v); });
await sleep(200);
console.log('\nDirection 1: client1 → client2');
client1.put('chat.001', 'from_client_1');
await sleep(1000);
console.log('Direction 2: client2 → client1');
client2.put('chat.002', 'from_client_2');
await sleep(1000);
client1.stop();
client2.stop();
const metrics = await fetchMetrics();
console.log('\n--- Relay Metrics ---');
console.log(' messages_parsed:', metrics.messages_parsed);
console.log(' messages_relayed:', metrics.messages_relayed);
console.log(' ws_messages_sent:', metrics.ws_messages_sent);
console.log('\n--- Results ---');
console.log(' client1 received:', JSON.stringify(c1Received));
console.log(' client2 received:', JSON.stringify(c2Received));
let passed = 0;
let failed = 0;
if (c2Received.some(v => v.includes('from_client_1'))) {
console.log(' ✅ client2 received from_client_1');
passed++;
} else {
console.log(' ❌ client2 did NOT receive from_client_1');
failed++;
}
if (c1Received.some(v => v.includes('from_client_2'))) {
console.log(' ✅ client1 received from_client_2');
passed++;
} else {
console.log(' ❌ client1 did NOT receive from_client_2');
failed++;
}
if (metrics.messages_parsed >= 4) {
console.log(' ✅ relay processed messages:', metrics.messages_parsed);
passed++;
} else {
console.log(' ❌ relay did not process enough messages:', metrics.messages_parsed);
failed++;
}
if (metrics.messages_relayed >= 2) {
console.log(' ✅ relay forwarded messages:', metrics.messages_relayed);
passed++;
} else {
console.log(' ❌ relay did not forward enough messages:', metrics.messages_relayed);
failed++;
}
relay.kill('SIGTERM');
await sleep(200);
console.log(`\n=== ${passed} passed, ${failed} failed ===\n`);
process.exit(failed > 0 ? 1 : 0);
}
main().catch(err => {
console.error('Test error:', err);
process.exit(1);
});