From b3c646705a42a82d7dfa9052d5d7cc3b2e810026 Mon Sep 17 00:00:00 2001 From: Jaromir Obr Date: Mon, 7 Sep 2026 14:39:09 +0200 Subject: [PATCH] fix(typescript): no loader required under Bun Bun transpiles TypeScript natively, so `module.register()` is a no-op stub and a registered tsx/ts-node loader never runs. checkTypeScriptLoader() only string-matched the `require` array against a hardcoded list of Node loaders, so `require: ['tsx/esm']` was mandatory under Bun purely to satisfy that match, forcing tsx into devDependencies to do nothing on every run. Return true early when process.versions.bun is set. This is deliberately Bun-specific rather than "skip the check when the runtime handles TypeScript": Node cannot replace tsx here, as its native type stripping rejects enums and does not resolve extensionless relative imports. Adds unit tests for loaderCheck.js, which had no coverage, pinning both the new Bun branch and the existing Node behaviour. Fixes #5697 Co-Authored-By: Claude Opus 5 --- lib/utils/loaderCheck.js | 6 ++++ test/unit/utils/loaderCheck_test.js | 56 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 test/unit/utils/loaderCheck_test.js diff --git a/lib/utils/loaderCheck.js b/lib/utils/loaderCheck.js index bfec25718..bf5161f5c 100644 --- a/lib/utils/loaderCheck.js +++ b/lib/utils/loaderCheck.js @@ -6,10 +6,16 @@ * Check if a TypeScript loader is available for test files * Note: This checks if loaders are in the require array, not if packages are installed * Package installation is checked when actually requiring modules + * Always true under Bun, which transpiles TypeScript itself * @param {string[]} requiredModules - Array of required modules from config * @returns {boolean} */ export function checkTypeScriptLoader(requiredModules = []) { + // Bun transpiles TypeScript natively, so no loader is needed. + // Node is not treated the same way: its native type stripping rejects enums + // and does not resolve extensionless relative imports. + if (process.versions.bun) return true + // Check if a loader is configured in the require array return ( requiredModules.includes('tsx/esm') || diff --git a/test/unit/utils/loaderCheck_test.js b/test/unit/utils/loaderCheck_test.js new file mode 100644 index 000000000..512663cef --- /dev/null +++ b/test/unit/utils/loaderCheck_test.js @@ -0,0 +1,56 @@ +import { expect } from 'chai' +import { checkTypeScriptLoader, validateTypeScriptSetup } from '../../../lib/utils/loaderCheck.js' + +describe('TypeScript loader check', () => { + const hadBun = 'bun' in process.versions + const originalBun = process.versions.bun + + afterEach(() => { + if (hadBun) { + process.versions.bun = originalBun + } else { + delete process.versions.bun + } + }) + + describe('on Node', () => { + beforeEach(() => { + delete process.versions.bun + }) + + it('detects a configured loader', () => { + for (const loader of ['tsx/esm', 'tsx/cjs', 'tsx', 'ts-node/esm', 'ts-node/register', 'ts-node']) { + expect(checkTypeScriptLoader([loader]), loader).to.be.true + } + }) + + it('reports an error for TypeScript tests without a loader', () => { + expect(checkTypeScriptLoader([])).to.be.false + + const validation = validateTypeScriptSetup(['basic_test.ts'], []) + expect(validation.hasError).to.be.true + expect(validation.message).to.include('TypeScript Test Files Detected') + }) + + it('passes when there are no TypeScript test files', () => { + expect(validateTypeScriptSetup(['basic_test.js'], []).hasError).to.be.false + }) + }) + + describe('on Bun', () => { + beforeEach(() => { + process.versions.bun = '1.4.2' + }) + + // Bun transpiles TypeScript itself, so requiring tsx/ts-node is pointless (#5697) + it('needs no loader in the require array', () => { + expect(checkTypeScriptLoader([])).to.be.true + expect(validateTypeScriptSetup(['basic_test.ts'], []).hasError).to.be.false + }) + + it('still accepts a configured loader', () => { + expect(checkTypeScriptLoader(['tsx/esm'])).to.be.true + expect(validateTypeScriptSetup(['basic_test.ts'], ['tsx/esm']).hasError).to.be.false + }) + }) +})