docs/solutions/test-failures/2026-04-16-bun-root-config-cannot-carry-legacy-hyperscript-tsx-fixtures.md
Legacy Slate TSX fixture lanes do not compile through the Slate hyperscript path
under raw bun test in this repo.
Without help, Bun turns fixture JSX like <element>word</element> into
React-style element objects instead of Slate hyperscript output.
That shows up in the current dynamic-import lanes:
packages/slate-hyperscript/test/index.spec.ts importing
packages/slate-hyperscript/test/fixtures/*.tsxpackages/slate/test/index.spec.ts importing the full packages/slate/test/**
fixture corpuspackages/slate-history/test/index.spec.ts importing the full
packages/slate-history/test/** fixture corpusThe official Bun docs say per-file JSX pragmas are supported, and
Bun.Transpiler does honor them. The problem was the plain runtime import path
used by the dynamic fixture imports, not the pragma contract itself.
The current slate-hyperscript Bun lane imports test/fixtures/*.tsx from
index.spec.ts. A preload regex that targets a dead or non-imported spec path
does nothing for the actual failing modules.
bunfig.tomlThat is still the wrong fix. It papers over the import path and breaks the single-root Bun setup.
Keep the legacy fixture syntax and fix the import path that Bun actually uses.
Use one scoped preload transform in config/bun-test-setup.ts that targets the legacy fixture directories directly:
packages/slate-hyperscript/test/**/*.tsxpackages/slate/test/**/*.tsx excluding the Bun spec entrypointsFor plain legacy fixtures, keep the files as bare TSX and let the preload
inject import { jsx } from 'slate-hyperscript' before running the classic JSX
transform. Only keep a local const jsx = createHyperscript(...) inside files
that truly need a custom factory.
For the current slate and slate-history Bun lanes, keep the shared editor
helpers and let the fixtures import a side-effect-free package-local index.js
helper for jsx:
index.js files side-effect free so fixtures can
import jsx from them without re-entering an old suite bootstrapimport type instead of papering over the errorThat keeps all legacy Slate fixture packages on the single root Bun config while letting Bun own the migrated fixture lanes.
The real contract was not "Bun cannot run Slate JSX tests."
It was "raw Bun runtime imports are not reproducing the hyperscript pragma path for the imported fixture modules."
Using Bun.Transpiler inside a scoped preload gives Bun the transform path it
actually needs while keeping the single root config. The important detail is
scope: the preload has to intercept the TSX files that Bun is dynamically
importing, not some neighboring spec filename. A broad test-directory rule also
avoids turning filename suffixes into tooling metadata, and the injected stock
import removes the per-file pragma and import { jsx } boilerplate for
ordinary fixtures.
test/**/*.ts tree, keep the Bun
entrypoint off that glob so Mocha does not accidentally execute it.bunfig.toml only if there is a real runtime reason, not
to emulate old Babel behavior.pnpm install
pnpm turbo build --filter=./packages/slate-hyperscript
pnpm turbo typecheck --filter=./packages/slate-hyperscript
pnpm turbo build --filter=./packages/slate
pnpm turbo typecheck --filter=./packages/slate
pnpm exec tsc --project config/tsconfig.test.json --noEmit
bun test ./packages/slate-hyperscript/test/index.spec.ts
bun test ./packages/slate/test/bun/editor-above.spec.tsx
pnpm test:bun
pnpm test:mocha
pnpm lint