使用Jest+Testing Library测试Swiper组件遇export语法错误求助
Jest测试Swiper组件时遇到Unexpected token 'export'错误的解决方法
问题场景
使用Jest和Testing Library测试React(Next.js)项目中的Swiper组件时,触发「Jest encountered an unexpected token 'export'」错误,调整transform和transformIgnorePatterns参数后仍未解决。
错误信息
FAIL src/components/BestSeller/BestSeller.test.tsx ● Test suite failed to run 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: D:\Web\nextjs-thebookstore\client\node_modules\swiper\swiper.esm.js:13 export { default as Swiper, default } from './core/core.js'; ^^^^^^ SyntaxError: Unexpected token 'export' 9 | 10 | const BestSeller: React.FunctionComponent<{ books: IBook[] }> = ({ books }) => { > 11 | console.log(books); | ^ 12 | const year = new Date().getFullYear(); 13 | SwiperCore.use([Autoplay, Grid, Navigation]); 14 | at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1495:14) at Object.<anonymous> (src/components/BestSeller/BestSeller.tsx:11:55) at Object.<anonymous> (src/components/index.ts:20:58) at Object.<anonymous> (src/components/BestSeller/BestSeller.test.tsx:7:21)
相关配置与代码
jest.config.js
const nextJest = require('next/jest'); const createJestConfig = nextJest({ // Provide the path to your Next.js app to load next.config.js and .env files in your test environment dir: './', }); // Add any custom config to be passed to Jest const customJestConfig = { setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], roots: ['<rootDir>/src'], moduleNameMapper: { // Handle module aliases (this will be automatically configured for you soon) '^@/components/src/(.*)$': '<rootDir>/src/components/$1', '^@/pages/src/(.*)$': '<rootDir>/src/pages/$1', }, testEnvironment: 'jest-environment-jsdom', transform: { '\\.[jt]sx?$': 'babel-jest', }, }; // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async module.exports = createJestConfig(customJestConfig);
BestSeller.test.tsx
import { render, screen } from '@testing-library/react'; import { BestSeller } from '@/components'; import React from 'react'; const DUMMY_BOOKS = [ { id: '1as3ds21vcd3123dxas', title: 'The Silent History', genre: ['history, fantasy'], price: 32, discount: true, discountPrice: 27, bestSeller: true, featuredImage: 'https://...', }, ]; describe('BestSeller Component', () => { beforeEach(() => { render(<BestSeller books={DUMMY_BOOKS} />); }); it('should header text render correctly', () => { expect(screen.getByTestId('best-seller-title')).toHaveTextContent(/bestsellers/i); }); });
BestSeller.tsx
import React from 'react'; import SwiperCore, { Autoplay, Grid, Navigation } from 'swiper'; import { Swiper, SwiperSlide } from 'swiper/react'; import { Book } from '../../components'; import { IBook } from '../../../typescript'; import 'swiper/css'; import 'swiper/css/grid'; import 'swiper/css/navigation'; const BestSeller: React.FunctionComponent<{ books: IBook[] }> = ({ books }) => { const year = new Date().getFullYear(); SwiperCore.use([Autoplay, Grid, Navigation]); return ( <div className="mt-10 px-4 xs:px-12 sm:20 md:px-[100px]"> <h1 data-testid="best-seller-title" className="text-3xl sm:text-4xl font-medium"> bestsellers </h1> <p className="text-base sm:text-lg font-thin">top selling books of {year}</p> <Swiper className="mt-6" grid={{ rows: 1, fill: 'row' }} spaceBetween={15} slidesPerView={1} breakpoints={{ 320: { slidesPerView: 1 }, 440: { slidesPerView: 2 }, 640: { slidesPerView: 3 }, 1000: { slidesPerView: 4 }, 1200: { slidesPerView: 5 }, }} allowSlidePrev={true} allowSlideNext={true} navigation={true} loop={true} autoplay={{ delay: 3000, pauseOnMouseEnter: true }} modules={[Grid, Autoplay, Navigation]} > {books.map((book: IBook) => ( <SwiperSlide key={book.id}> <Book {...book} /> </SwiperSlide> ))} </Swiper> </div> ); }; export default BestSeller;
解决方法
方法1:让Jest转换Swiper及其依赖
修改jest.config.js中的transformIgnorePatterns,将Swiper、ssr-window和dom7(Swiper的核心依赖)加入转换白名单——这些包使用ESM语法,默认被Jest忽略转换,导致语法报错:
const customJestConfig = { // ... 原有配置 transformIgnorePatterns: [ '/node_modules/(?!swiper|ssr-window|dom7)', ], };
这段配置表示:除swiper、ssr-window、dom7之外,其他node_modules文件均不转换。
方法2:Mock Swiper组件(快速跳过依赖问题)
如果不需要测试Swiper的交互逻辑,仅验证组件的基础渲染(比如标题),可以直接Mock Swiper相关模块,避免加载真实的Swiper代码。
在jest.setup.js中添加:
jest.mock('swiper/react', () => ({ Swiper: ({ children }) => <div data-testid="swiper">{children}</div>, SwiperSlide: ({ children }) => <div>{children}</div>, })); jest.mock('swiper', () => ({ default: jest.fn(), use: jest.fn(), }));
也可以在单个测试文件顶部添加上述Mock代码。
方法3:检查Babel配置(Next.js项目)
确保Babel配置支持Next.js语法,在项目根目录创建babel.config.js:
{ "presets": ["next/babel"] }
内容的提问来源于stack exchange,提问作者Tolgahan
相关产品推荐
相关产品推荐

