Problem
#508 makes webjs run on both Node and Bun and adds a cross-runtime SMOKE (test/bun/smoke.mjs: boot + SSR + TS strip + a server-action RPC round-trip) that runs under both, plus a Bun CI job for it. That proves the critical path, but it is not the FULL suite. Remix 3 (the portability-branded peer) runs its ENTIRE per-package suite under Bun (test:bun scripts everywhere), which is how the long tail of Bun-specific incompatibilities gets caught (a node:* API Bun implements differently, an edge case in fs/crypto/streams, a timing quirk).
Why this is its own issue (not part of #508)
The existing suite is written against node:test (test/before/after). Bun's own bun test runner is Jest-shaped and its node:test compat is imperfect: running a node:test file as bun --bun <file> fails today with Cannot use beforeAll() outside of the test runner. Run "bun test". So getting the full suite green under Bun is a real harness-compatibility effort (adapting the runner invocation, triaging Bun-vs-Node test failures that are harness artifacts vs genuine framework bugs), separate from shipping the runtime support itself. The #508 smoke runs under Bun precisely because it is a plain assert script, not a node:test file.
Design / approach
- Decide the invocation: either drive
node:test files through Bun's node:test compat (investigate bun test discovery + the global-injection issue), or a thin adapter that runs each *.test.js/*.test.mjs under bun <file> with the node:test shim, or split a Bun-runnable subset.
- Add a CI job (matrix) that runs the suite (or a defined subset) under Bun alongside the Node job.
- Triage every Bun failure: fix genuine framework incompatibilities (these are the valuable finds), and quarantine/skip the ones that are pure Bun-test-runner-harness artifacts with a documented reason.
- Likely surfaces to watch:
fs.watch recursive behavior, node:crypto digests, AsyncLocalStorage propagation, the WebSocket path (ws), streaming RPC over Bun's Request/Response, the serializer with Blob/File/FormData.
Acceptance criteria
Follow-up to #508.
Problem
#508 makes webjs run on both Node and Bun and adds a cross-runtime SMOKE (
test/bun/smoke.mjs: boot + SSR + TS strip + a server-action RPC round-trip) that runs under both, plus a Bun CI job for it. That proves the critical path, but it is not the FULL suite. Remix 3 (the portability-branded peer) runs its ENTIRE per-package suite under Bun (test:bunscripts everywhere), which is how the long tail of Bun-specific incompatibilities gets caught (anode:*API Bun implements differently, an edge case in fs/crypto/streams, a timing quirk).Why this is its own issue (not part of #508)
The existing suite is written against
node:test(test/before/after). Bun's ownbun testrunner is Jest-shaped and its node:test compat is imperfect: running a node:test file asbun --bun <file>fails today withCannot use beforeAll() outside of the test runner. Run "bun test". So getting the full suite green under Bun is a real harness-compatibility effort (adapting the runner invocation, triaging Bun-vs-Node test failures that are harness artifacts vs genuine framework bugs), separate from shipping the runtime support itself. The #508 smoke runs under Bun precisely because it is a plain assert script, not a node:test file.Design / approach
node:testfiles through Bun's node:test compat (investigatebun testdiscovery + the global-injection issue), or a thin adapter that runs each*.test.js/*.test.mjsunderbun <file>with the node:test shim, or split a Bun-runnable subset.fs.watchrecursive behavior,node:cryptodigests,AsyncLocalStoragepropagation, the WebSocket path (ws), streaming RPC over Bun's Request/Response, the serializer with Blob/File/FormData.Acceptance criteria
agent-docs/testing.md.Follow-up to #508.