Vite Vue TS Three项目中Jest测试运行失败问题求助
解决Jest测试中的ES模块语法错误问题
问题场景
项目基于Vite+Vue3+TypeScript+Three.js开发,配置Jest进行单元测试时,多次尝试调整配置仍持续出现SyntaxError: Cannot use import statement outside a module错误,以下是详细的代码、配置及报错信息:
测试代码
import {Line} from "../src/modules/objs/line"; import {SceneWrapper} from "../src/modules/scene/sceneWrapper"; import * as THREE from "three"; import {DrawProfile} from "../src/modules/operations/draw/drawProfile"; import {snapIndicator} from "../src/modules/config/objs"; describe('snaps', () => { let sceneWrapper = new SceneWrapper(new HTMLCanvasElement()); let lineStart = new THREE.Vector3(0, 0, 0); let cursorStart = sceneWrapper.getScreenCoordsFromSceneCoords(lineStart); let line = new Line(lineStart, new THREE.Vector3(10, 10, 10)); sceneWrapper.scene.add(line); test('Box appear', () => { let operation = new DrawProfile(sceneWrapper); let startEvent = new PointerEvent('', {clientX: cursorStart.x, clientY: cursorStart.y}); operation.searchSnapsHandler(startEvent); expect(operation.snap).toBeDefined(); expect(sceneWrapper.scene).toContain(snapIndicator); expect(snapIndicator.position).toBe(lineStart); }); });
初始jest.config.cjs
module.exports = { preset: 'ts-jest/presets/js-with-ts-esm', testEnvironment: 'jsdom', };
第一次报错
/Users/a/Programming/JavaScript/CAD/test/main.test.ts:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { Line } from "../src/modules/objs/line"; ^^^^^^ SyntaxError: Cannot use import statement outside a module
修改后的jest.config.cjs
module.exports = { preset: 'ts-jest/presets/js-with-ts-esm', testEnvironment: 'jsdom', moduleNameMapper: { '(\\.{1,2}/.*)\\.js$': '$1', }, };
第二次报错
/Users/a/Programming/JavaScript/CAD/node_modules/three/examples/jsm/controls/OrbitControls.js:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { ^^^^^^ SyntaxError: Cannot use import statement outside a module 7 | import {SceneType} from "./sceneType"; 8 | import {Scene3DView} from "./scenes/scene3DView"; > 9 | import {OrbitControls} from "three/examples/jsm/controls/OrbitControls"; | ^ 10 | import {cameraFarPlane, cameraFov, cameraNearPlane} from "../config/dims"; 11 | import {Operation} from "../operations/operation"; 12 | import {defaultOrbitControlsMouseHandlers, startSceneType} from "../config/others";
使用NODE_OPTIONS=--experimental-vm-modules jest后的报错
/Users/a/Programming/JavaScript/CAD/node_modules/vue/dist/vue.runtime.esm-bundler.js:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { initCustomFormatter, warn } from '@vue/runtime-dom'; ^^^^^^ SyntaxError: Cannot use import statement outside a module
tsconfig.json配置
{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "NodeNext", "moduleResolution": "NodeNext", "strict": true, "jsx": "preserve", "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "lib": ["ESNext", "DOM"], "skipLibCheck": true, "noEmit": true, "sourceMap": true, "allowJs": true }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], "references": [{ "path": "./tsconfig.node.json" }] }
package.json配置
{ "name": "cad", "private": true, "version": "0.0.0", "type": "module", "scripts": { "lint": "eslint . --ext .js,.jsx,.ts,.tsx", "dev": "vite", "test": "jest", "build": "vue-tsc && vite build", "preview": "vite preview" }, "dependencies": { "pinia": "^2.0.33", "sass": "^1.58.3", "scss": "^0.2.4", "three": "^0.150.1", "vue": "^3.2.45" }, "devDependencies": { "@types/jest": "^29.5.5", "@types/node": "^18.15.11", "@types/three": "^0.149.0", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", "@vitejs/plugin-vue": "^4.0.0", "autoprefixer": "^10.4.14", "eslint": "^8.36.0", "eslint-plugin-vue": "^9.10.0", "esm": "^3.2.25", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "postcss": "^8.4.21", "tailwindcss": "^3.2.7", "ts-jest": "^29.1.1", "typescript": "^4.9.5", "vite": "^4.1.0", "vue-tsc": "^1.0.24" } }
解决方案
针对项目"type": "module"的ESM模式,结合TypeScript、Vue、Three.js等依赖的特性,调整Jest配置如下:
1. 重新配置jest.config.cjs
module.exports = { preset: 'ts-jest', testEnvironment: 'jsdom', extensionsToTreatAsEsm: ['.ts', '.tsx', '.vue'], moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', '^three/examples/jsm/(.*)$': '<rootDir>/node_modules/three/examples/jsm/$1' }, transform: { '^.+\\.tsx?$': [ 'ts-jest', { useESM: true, }, ], '^.+\\.vue$': '@vue/vue3-jest' }, globals: { 'ts-jest': { useESM: true } } };
2. 更新package.json的测试脚本
{ "scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" } }
3. 补充安装Vue测试依赖
npm install -D @vue/vue3-jest
4. 调整tsconfig.json(可选)
确保TypeScript模块配置与Jest的ESM模式兼容:
{ "compilerOptions": { "module": "ESNext", "moduleResolution": "NodeNext" } }
验证
运行npm run test,Jest将正确识别所有ES模块导入,解决语法错误问题。
内容的提问来源于stack exchange,提问作者Intolighter
相关产品推荐
相关产品推荐

