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 + }) + }) +})