React+TypeScript项目Jest遇意外token错误(MUI组件相关)
问题:引入MUI内部DemoContainer后Jest测试报错"Unexpected token 'export'"
在使用React、TypeScript、Jest及React-testing-Library的项目中,引入@mui/x-date-pickers/internals/demo下的DemoContainer组件后,Jest提示遇到意外token 'export',测试套件运行失败。
错误详情
Jest encountered an unexpected token Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax. Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration. By default "node_modules" folder is ignored by transformers. Here's what you can do: • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it. • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config. • If you need a custom transformation specify a "transform" option in your config. • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option. You'll find more details and examples of these config options in the docs: https://jestjs.io/docs/configuration For information about custom transformations, see: https://jestjs.io/docs/code-transformation Details: E:\Git\node_modules\@mui\x-date-pickers\internals\demo\index.js:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { DemoContainer, DemoItem } from './DemoContainer'; ^^^^^^ SyntaxError: Unexpected token 'export' 6 | import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; 7 | import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; > 8 | import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; | ^ 9 | import { useTranslation } from 'react-i18next'; 10 | import { Checked, Unchecked } from '../../../assets/images'; 11 | import dayjs, { Dayjs } from 'dayjs'; at Runtime.createScriptFromCode (node_modules/jest/node_modules/jest-runtime/build/index.js:1796:14) at Object.require (src/components/common/weekTimeComponent/index.tsx:8:1) at Object.require (src/pages/manageLocation/component/ManageLocationAddEditComponent.tsx:3:1) at Object.require (src/pages/manageLocation/component/manageLocationDetailComponent.tsx:7:1) at Object.<anonymous> (tests/pages/manageLocation/manageLocationDetailComponent.test.tsx:8:1)
jest.config.js配置
module.exports = { globals: { 'ts-jest': { diagnostics: false, }, }, setupFiles: ['<rootDir>/tests/setup/test-shim.js', '<rootDir>/tests/setup/test-setup.js'], moduleFileExtensions: ['ts', 'tsx', 'js'], preset: 'ts-jest/presets/js-with-ts', transform: { '^.+\.(ts|tsx)$': 'ts-jest', }, moduleNameMapper: { '\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/tests/setup/fileMock.js', '\.(css|less)$': '<rootDir>/tests/setup/styleMock.js', uuid: require.resolve('uuid'), }, moduleDirectories: ['node_modules', 'src'], testMatch: ['**/tests/**/*.test.(ts|tsx|js)'], collectCoverage: false, testEnvironment: 'jsdom', }
报错组件定义代码
import * as React from 'react'; import { SxProps, Theme } from '@mui/material/styles'; interface DemoGridProps { children: React.ReactNode; components: string[]; sx?: SxProps<Theme>; } interface DemoItemProps { label?: React.ReactNode; component?: string; children: React.ReactNode; } export declare function DemoItem(props: DemoItemProps): React.JSX.Element; export declare function DemoContainer(props: DemoGridProps): React.JSX.Element;
解决方案
核心原因:Jest默认跳过node_modules目录下文件的转译,但@mui/x-date-pickers/internals/demo输出的是未转译的ES模块语法,导致Jest无法解析export关键字。
方案1:配置Jest转译指定MUI包
修改jest.config.js,添加transformIgnorePatterns配置,让Jest对指定的MUI包进行转译:
module.exports = { // 保留原有所有配置... transformIgnorePatterns: [ 'node_modules/(?!(@mui/x-date-pickers|@mui/material|@mui|@emotion/react|@emotion/styled)/)' ], };
该配置的含义是:除了括号内列出的包之外,其他node_modules下的文件均跳过转译。
方案2:Mock DemoContainer组件
如果测试逻辑不需要依赖DemoContainer的真实功能,可以直接在测试文件中Mock该组件,避免加载未转译的模块:
// 在对应测试文件的顶部添加以下代码 jest.mock('@mui/x-date-pickers/internals/demo', () => ({ DemoContainer: ({ children }: { children: React.ReactNode }) => <div>{children}</div>, DemoItem: ({ children }: { children: React.ReactNode }) => <div>{children}</div>, }));
方案3:检查Babel配置(若使用Babel)
如果项目同时使用Babel,确保babel.config.js中包含对ES模块的转译配置,例如:
module.exports = { presets: [ '@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript' ] };
内容的提问来源于stack exchange,提问作者Archan Bhalani
相关产品推荐
相关产品推荐

