Jest:SVG require引起“SyntaxError:Unexpected token <”

51

不确定在哪里查找此错误。

使用TypeScript与React,以及Jest和Enzyme进行单元测试。

Package.json 示例:

"scripts": {
    "start": "node server.js",
    "bundle": "cross-env NODE_ENV=production webpack -p",
    "test": "jest"
  },
  "jest": {
    "transform": {
      "^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
    },
    "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "json"
    ]
  }

运行 npm test 的结果是:

FAIL src/components/Component.test.tsx

 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<?xml version="1.0" encoding="UTF-8"?>
                                                                                             ^

    SyntaxError: Unexpected token <

编辑:看起来问题发生在我使用require加载静态.svg文件的第一个位置。为什么它不能处理呢?有没有一种方法可以在使用require时忽略抛出此错误?


尝试移除 xml 标签,只包含以下的 svg 标签。 - Agney
Gawd Jest 真是让人烦人的。 - GN.
5个回答

60
Jest不使用Webpack,因此它不知道如何加载除js/jsx之外的其他文件扩展名。要添加对其他扩展名的支持,您需要编写自定义转换器。其中一个转换器是TypeScript转换器,您可以在配置中定义该转换器,如下所示:
"transform": {
   "^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},

现在你需要为svg文件添加转换器。让我们扩展你的jest配置

"transform": {
       "^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js",
       "^.+\\.svg$": "<rootDir>/svgTransform.js" 
    },

并在您的根目录中创建svgTransform.js文件,其内容如下

module.exports = {
  process() {
    return { code: 'module.exports = {};' };
  },
  getCacheKey() {
    // The output is always the same.
    return 'svgTransform';
  },
};

当然,这是一个基本的转换器,总是返回相同的值。

文档链接:https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object


没问题!我删除了我的评论,因为你已经修复了它。 - Matthias
1
在React测试库中,我没有preprocessor.js文件,它是什么样子的? - mattsmith5

9
如果您已经使用了@svgr/webpack模块,允许webpack处理导入svg文件,@svgr提供了一个页面,介绍如何在Jest中进行测试。资源在这里 为了保存记录而复制。

/__mocks__/svgrMock.js

import * as React from 'react'
export default 'SvgrURL'
export const ReactComponent = 'div'

package.json
"jest": {
  "moduleNameMapper": {
    "\\.svg": "<rootDir>/__mocks__/svgrMock.js"
  }
}

5

您可以使用npm包jest-transform-stub

在Jest配置文件中添加转换代码,如下:

"transform": {
  ...
  "^.+\\.svg$": "jest-transform-stub",
  ...
}

Same transform can be use for any asset file.
  ".+\\.(css|less|sass|scss|png|jpg|gif|ttf|woff|woff2|svg)$": "jest-transform-stub",


1
  1. 使用类似以下的__mocks__/svgMock.js文件来模拟您的SVG:
import React from "react";
export default "SvgURL";
export const ReactComponent = ({ width, height }) => (
  <div>
    w-{width} h-{height}
  </div>
);

2. 通过修改jest.config.js文件中的以下属性,告诉Jest在哪里找到这个SVG模拟器:
  moduleNameMapper: {
    "\\.svg": "<rootDir>/__mocks__/svgMock.js",
  },

0

您需要编辑位于根目录下的jest.config.js文件。

transform对象内添加以下行:

 '^.+\\.svg$': './svgTransform.js'

所以你的 jest.config.js 文件应该长这样:

module.exports = {
  rootDir: '.',
  testEnvironment: 'jsdom',
  transform: {
    '^.+\\.(j|t)sx?$': 'babel-jest',
    '^.+\\.svg$': './svgTransform.js',
  },
//...
}

然后在根目录下创建一个名为svgTransform.js的文件,并添加以下内容:

module.exports = {
  process() {
    return 'module.exports = {};'
  },
  getCacheKey() {
    // The output is always the same.
    return 'svgTransform'
  },
}

如果您正在观察模式下运行测试,请确保完全停止测试套件并重新启动。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接