import { test } from 'node:test'; import assert from 'node:assert/strict'; import { IsolateRunner, FunctionError } from '../src/runtime/isolate.js'; test('passes event through a noop transform', async () => { const r = new IsolateRunner({ memoryLimitMB: 64, timeoutMs: 1000 }); const code = ` function transform(event) { return event; } `; const got = await r.run(code, { message_id: 'm1', type: 'track' }); assert.equal(got.message_id, 'm1'); }); test('mutates event properties', async () => { const r = new IsolateRunner({ memoryLimitMB: 64, timeoutMs: 1000 }); const code = ` function transform(event) { event.properties = event.properties || {}; event.properties.tagged = true; return event; } `; const got = await r.run(code, { message_id: 'm1', type: 'track' }); assert.equal(got.properties.tagged, true); }); test('returns null to drop event', async () => { const r = new IsolateRunner({ memoryLimitMB: 64, timeoutMs: 1000 }); const code = `function transform(event) { return null; }`; const got = await r.run(code, { message_id: 'm1', type: 'track' }); assert.equal(got, null); }); test('rejects code without transform()', async () => { const r = new IsolateRunner({ memoryLimitMB: 64, timeoutMs: 1000 }); await assert.rejects( () => r.run(`const x = 1;`, { message_id: 'm1', type: 'track' }), (err) => err instanceof FunctionError && err.kind === 'runtime', ); }); test('times out infinite loops', async () => { const r = new IsolateRunner({ memoryLimitMB: 64, timeoutMs: 100 }); const code = `function transform(event) { while (true) {} return event; }`; await assert.rejects( () => r.run(code, { message_id: 'm1', type: 'track' }), (err) => err instanceof FunctionError && err.kind === 'timeout', ); });