Jest 无法加载 svg 文件

Kon*_*zak 12 javascript svg reactjs jestjs

在我的应用程序中,我使用 React 和 TypeScript。我尝试运行 Jest 测试,但出现以下错误:

C:\Users\e-KDKK\workspace\konrad\mikskarpety\src\images\icons\Sock.svg:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<svg xmlns="http://www.w3.org/2000/svg" width="18.725" height="23.947" viewBox="0 0 18.725 23.947">
                                                                                         ^

SyntaxError: Unexpected token <

  1 | import React, { FC } from 'react';
  2 | 
> 3 | import SockIcon from '../../images/icons/Sock.svg';
    | ^
  4 | 
  5 | export const Spinner: FC = () => {
  6 |   return (

  at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
  at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
  at Object.<anonymous> (src/components/Spinner/Spinner.tsx:3:1)
Run Code Online (Sandbox Code Playgroud)

这个文件甚至没有经过测试。我不知道为什么它试图编译它。我的jest.config.json文件只包含覆盖阈值。

我读到 jest 有时需要针对特定​​文件(如 SVG)进行额外的转换部分,但是当我添加到配置时

"transform": {
    "^.+\\.svg$": "jest-svg-transformer"
},
Run Code Online (Sandbox Code Playgroud)

我的错误信息仅更改为:

C:\Users\e-KDKK\workspace\konrad\mikskarpety\test\utils\debounce.test.ts:1 ({"Object.":function(module,exports,require,__dirname,__filename,global,jest){导入 { getVersion } from 'jest'; ^

SyntaxError: Unexpected token {

  at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
  at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
Run Code Online (Sandbox Code Playgroud)

这让我更加困惑。

您可以在此处找到该应用程序的代码:https : //github.com/KonradKlimczak/mikskarpety

Tom*_*ang 29

jest 不知道如何加载 js/jsx 以外的其他文件扩展名,您需要找到 jest.config.js并为 svg 文件添加转换器。

"transform": {
   "^.+\\.tsx?$": "ts-jest",
   "^.+\\.svg$": "<rootDir>/svgTransform.js"
},
Run Code Online (Sandbox Code Playgroud)

并使用以下内容在根目录中创建 svgTransform.js 文件(请参阅自定义转换器)。

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

链接:https : //jestjs.io/docs/en/configuration.html#transform-object-string-string

  • 这是这个答案的直接复制粘贴:/sf/answers/3276710811/ (6认同)
  • 目前看来这不起作用。同样的错误信息 (3认同)
  • 希望我能不止一次对此投赞成票。:) (2认同)

小智 18

在使用时jest-svg-transformer,对于我的设置,当放置在该部分下时它不起作用transformer。所以我必须将其添加到下面moduleNameMapper并且它起作用了。

yarn add jest-svg-transformer --dev
Run Code Online (Sandbox Code Playgroud)
 moduleNameMapper: {
    "^.+\\.svg$": "jest-svg-transformer",
  }
Run Code Online (Sandbox Code Playgroud)


Aha*_*yon 17

解决此问题的另一个更简单的选择是jest-svg-transformer.

只需安装它: npm i jest-svg-transformeryarn add jest-svg-transformer

并将 jest.config.js 添加到转换部分:

"transform": {
   ...
   "^.+\\.svg$": "jest-svg-transformer"
}
Run Code Online (Sandbox Code Playgroud)

  • 这是几年后的事了,但只是提醒其他人我尝试过这个 - 但它与最新版本的笑话(v29)不兼容 (2认同)

Gar*_*vae 14

SVG + 玩笑 = 痛苦

\n

当涉及到使用图像测试组件时,请做好承受一点痛苦的准备。\n最近,我花了一整天的时间来了解它在 Jest 中的工作原理。

\n

我明白了以下几点:

\n
    \n
  • 我们可以转换具有特定扩展名(而不是组件)的文件
  • \n
  • 我们可以根据需要转换所有图像,但大多数情况下,人们将图像转换为这些图像的名称,以获得类似于<img src="image.svg" />测试中的内容
  • \n
  • 开玩笑,不理解非 js 资产(没有自定义的东西)
  • \n
\n

问题

\n

让我们描述一个示例,如果我们不向 中添加 svg 转换器,该示例将返回错误。jest.config.js\n我将使用svg-jest库(稍后我将更详细地描述它)

\n
import vectorUpImg from \'./assets/icons/vector-up.svg\';\n\ntest(\'Renders svg as img src\', () => {\n  /* ... */\n  render(<img src={vectorUpImg} />);\n  /* ... */\n});\n
Run Code Online (Sandbox Code Playgroud)\n

上面的示例返回一个错误,如下所示:

\n
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n\nSyntaxError: Unexpected token \'<\'\n\n>  7 | import vectorUpSvg from \'assets/icons/v2/plain/vector-up.svg\';\n
Run Code Online (Sandbox Code Playgroud)\n

好的。让我们添加一个自定义转换器。\n我稍后会更详细地描述它,只要知道转换器会将(笑)\n我们的 svg 转换为字符串vector-up.svg,我们将进入控制台:

\n
 \xe2\x88\x9a Renders svg as img src (55 ms)\n\n  console.log\n    <body>\n      <div>\n        <img\n          src="vector-up.svg"\n        />\n      </div>\n    </body>\n
Run Code Online (Sandbox Code Playgroud)\n

好的,测试通过了。但是...\n如果我们想使用 svg 作为组件怎么办?

\n
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n\nSyntaxError: Unexpected token \'<\'\n\n>  7 | import vectorUpSvg from \'assets/icons/v2/plain/vector-up.svg\';\n
Run Code Online (Sandbox Code Playgroud)\n

上面的示例返回一个错误,如下所示:

\n
Warning: React.jsx: type is invalid -- expected a string (for built-in components) \nor a class/function (for composite components) but got: undefined. \nYou likely forgot to export your component from the file it\'s defined in, \nor you might have mixed up default and named imports.\n
Run Code Online (Sandbox Code Playgroud)\n

我们可以更改变压器\n(不要添加另一个变压器,因为变压器用于文件扩展名,我们不能为一个“.svg”扩展名添加两个不同的变压器),\n所以现在变压器将解析传入的内容并创建一些东西就像 svg 模块一样,所以在我们的测试中我们得到:

\n
\xe2\x88\x9a Renders svg as a ReactComponent. El by querySelector (48 ms)\n\n  console.log\n    <body>\n      <div>\n        <svg\n          data-jest-file-name="vector-up.svg"\n          data-jest-svg-name="vector-up"\n          data-testid="vector-up"\n        />\n      </div>\n    </body>\n\n
Run Code Online (Sandbox Code Playgroud)\n

酷,嗯?不...如果我们现在尝试将 svg 传递到 img src,我们将得到:

\n
 console.log\n    <body>\n      <div>\n        <img\n          src="[object Object]"\n        />\n      </div>\n    </body>\n\n
Run Code Online (Sandbox Code Playgroud)\n

糟糕...但今天我找到了解决方案。@ChromeQ \n对svg-jest \n库进行了修复,现在一切正常,但您需要添加一些配置,直到\n svg-jest的所有者更新包\n或合并@ChromeQ的PR或PR我。

\n

那么,让我们解决这个问题......

\n

我的解决方法

\n

我的jest.config.js

\n
 transform: {\n    ...\n    \'^.+\\\\.svg$\': \'<rootDir>/src/tests/transformers/svg.js\',\n    ...\n  },\n
Run Code Online (Sandbox Code Playgroud)\n

变压器src/tests/transformers/svg.js

\n
\n

我添加了@ChromeQ所做的更改,进行了一些重构,并添加了一些文档 - PR

\n
\n
 \xe2\x88\x9a Renders svg as img src (55 ms)\n\n  console.log\n    <body>\n      <div>\n        <img\n          src="vector-up.svg"\n        />\n      </div>\n    </body>\n
Run Code Online (Sandbox Code Playgroud)\n

我的测试:

\n
import { ReactComponent as VectorUpComponent } from \'./assets/icons/vector-up.svg\';\n\ntest(\'Renders svg as a ReactComponent. El by querySelector\', () => {\n  const { container } = render(<VectorUpComponent />);\n  const svg = container.querySelector(\'svg\');\n  expect(svg).toBeInTheDocument();\n});\n
Run Code Online (Sandbox Code Playgroud)\n

控制台愉快地返回:

\n
  \xe2\x88\x9a Renders svg as img src (46 ms)\n  \xe2\x88\x9a Renders svg as a ReactComponent (7 ms)\n\n  console.log\n    <body>\n      <div>\n        <img\n          src="vector-up.svg"\n        />\n      </div>\n    </body>\n\n      at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:90:13)\n\n  console.log\n    <body>\n      <div>\n        <svg\n          aria-label="icon-vector-up"\n          data-jest-file-name="vector-up.svg"\n          data-jest-svg-name="vector-up"\n          data-testid="vector-up"\n        />\n      </div>\n    </body>\n\n      at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:90:13)\n\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\n\n
Run Code Online (Sandbox Code Playgroud)\n

还有一件事:

\n

该库(如此处所述)分配一些属性:

\n
\n
    \n
  • data-jest-file-name:文件的名称(例如\'some-image.svg\')
  • \n
  • data-jest-svg-name:仅文件的名称部分(例如“some-image”)
  • \n
  • data-testid:与 data-jest-svg-name 相同,但与 @testing-library/react getByTestId() 一起使用
  • \n
\n
\n

因此,如果您想按属性在测试中查找渲染元素,则​​必须传递一些其他属性。\n在上面的示例中,我传递了该aria-label属性,然后在该标签处找到了我的 svg。\n或者您可以使用data-testid、由svg-jest初始化取决于您的文件名。\n或者您可以使用 找到它querySelector,如下例所示:

\n
Warning: React.jsx: type is invalid -- expected a string (for built-in components) \nor a class/function (for composite components) but got: undefined. \nYou likely forgot to export your component from the file it\'s defined in, \nor you might have mixed up default and named imports.\n
Run Code Online (Sandbox Code Playgroud)\n


Mau*_*ice 8

另一个选项(不特定于 React)是使用,jest-transform-stub因为它适用于您想要的任何非 JS 文件。

{
  "jest": {
    // ..
    "transform": {
      "^.+\\.js$": "babel-jest",
      ".+\\.(svg|css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 该包实际上什么也没做,只是返回一个空的 module.export。如果您不想为此添加新的依赖项,我推荐 Tom Pang 的答案。 (3认同)

Tho*_*mas 7

*.svg从导入node_modules

从1*.svg中的图标库导入文件时,我遇到了同样的问题。在部分中使用对我来说不起作用,我不得不在部分中使用它。node_modulesjest-transform-stub"transform"jest.config.js"moduleNameMapper"

对我有帮助的是(在jest.config.js):

module.exports = {
  ...
  moduleNameMapper: {
    '^.+.(svg)$': 'jest-transform-stub',
  }
};
Run Code Online (Sandbox Code Playgroud)

1其原因可以在jest-transform-stubREADME中找到。

默认情况下,Jest 不会将转换应用于 node_modules。您可以使用 moduleNameMapper 来解决这个问题。