#!/usr/bin/env node /** * run-sx-tests.js — Run SX deftest forms in the Node WASM harness. * * Loads island definitions + test file, runs all registered tests, * reports results. * * Usage: * node tests/node/run-sx-tests.js [test-file.sx] */ const { createSxEnv } = require('./sx-harness'); const fs = require('fs'); const path = require('path'); const DEFAULT_TEST_FILE = path.resolve(__dirname, '../../spec/tests/test-reactive-islands.sx'); const ISLAND_SRC = path.resolve(__dirname, '../../sx/sx/reactive-islands/index.sx'); async function main() { const testFile = process.argv[2] || DEFAULT_TEST_FILE; const origLog = console.log; const origErr = console.error; origLog(`=== SX Test Runner (Node+WASM) ===`); origLog(`Test file: ${path.basename(testFile)}\n`); const t0 = Date.now(); const env = await createSxEnv({ html: '
', }); // Load island definitions const islandSrc = fs.readFileSync(ISLAND_SRC, 'utf8'); env.load(islandSrc); // Load test file const testSrc = fs.readFileSync(testFile, 'utf8'); env.load(testSrc); // Get registered tests const tests = env.eval('_island-tests'); const testList = tests?.items || []; if (testList.length === 0) { origLog('No tests found (check _island-tests registry)'); env.close(); process.exit(1); } origLog(`Running ${testList.length} tests...\n`); let passed = 0, failed = 0; const failures = []; for (const test of testList) { const name = test.name; const fn = test.fn; try { env.K.callFn(fn, []); passed++; origLog(` \u2713 ${name}`); } catch (e) { failed++; const msg = e.message || String(e); // Extract the assertion message from the error const clean = msg.replace(/^Error:\s*/, '').replace(/\s*\(in .*$/, ''); origErr(` \u2717 ${name}: ${clean}`); failures.push({ name, error: clean }); } } env.close(); const dt = Date.now() - t0; origLog(`\n=== ${passed} passed, ${failed} failed (${dt}ms) ===`); if (failures.length > 0) { origLog('\nFailures:'); for (const f of failures) origLog(` ${f.name}: ${f.error}`); } process.exit(failed > 0 ? 1 : 0); } main().catch(e => { console.error(e); process.exit(1); });