Jest: Jest 不适用于导入 CSS 的 JSX

创建于 2017-03-07  ·  24评论  ·  资料来源: facebook/jest

您要请求功能还是报告错误
漏洞

当前的行为是什么?
如果app.jsximport './app.css';则无法运行测试,我收到此错误:

yarn run:test v0.21.3
$ NODE_ENV=client jest -u
 FAIL  src/__tests__/app.test.js
  ● Test suite failed to run

    /home/svipben/Documents/react-boilerplate/src/client/app/app.css:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){body {
                                                                                                  ^
    SyntaxError: Unexpected token {

      at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:320:12)
      at Object.<anonymous> (src/client/app/app.jsx:7:1)
      at Object.<anonymous> (src/__tests__/app.test.js:2:12)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.693s
Ran all test suites.
error Command failed with exit code 1.

预期的行为是什么?
运行测试没有错误...

请提供您的确切 Jest 配置并提及您的 Jest、节点、yarn/npm 版本和操作系统。

操作系统:Linux Ubuntu 16.04
笑话:最新
纱线:最新
节点:最新
babel-jest : 最新

.babelrc:

        "client": {
            "presets": [
                "latest", // All you need to compile what's in ES2015+
                "flow", // Flow support
                "react", // Strip flow types and transform JSX
                "stage-2" // Experimental syntax extensions
            ],
            "sourceMaps": true // Compile with Source Maps
        },

笑话: NODE_ENV=client jest -u

PS 如果我评论/删除import './app.css'; ,一切运行良好

最有用的评论

我通过在 package.json 文件的 jest 配置中使用moduleNameMapper键解决了这个问题

{
   "jest":{
        "moduleNameMapper":{
             "\\.(css|less|sass|scss)$": "<rootDir>/__mocks__/styleMock.js",
             "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
        }
   }
}

在此之后,您将需要创建两个文件,如下所述

  • __mocks__/styleMock.js
module.exports = {};
  • __mocks__/fileMock.js
module.exports = 'test-file-stub';

如果您使用的是 CSS 模块,那么最好模拟代理以启用类名查找。
因此您的配置将更改为:

{
  "jest":{
     "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less|scss|sass)$": "identity-obj-proxy"
    },
  }
}

但是您需要安装identity-obj-proxy包作为开发依赖项,即

yarn add identity-obj-proxy -D

了解更多信息。 你可以参考jest docs

所有24条评论

@maximderbin谢谢!

@maximderbin谢谢! 它通过添加moduleNameMapper解决了我的问题

@svipben @maximderbin @simonxl我必须在哪里添加这个moduleNameMapper?
我在文档中看到我们应该将它添加到 packag.json 但哪个?
tnx

@sarahmarciano moduleNameMapper是您配置的一部分。 默认情况下,您可以在“jest”键下设置 package.json 中的配置(在依赖项中具有 jest 功能的配置),如下所示:

{
  "dependencies": {...}
  "jest": {
    "moduleNameMapper": {...}
  }
}

我通过在 package.json 文件的 jest 配置中使用moduleNameMapper键解决了这个问题

{
   "jest":{
        "moduleNameMapper":{
             "\\.(css|less|sass|scss)$": "<rootDir>/__mocks__/styleMock.js",
             "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
        }
   }
}

在此之后,您将需要创建两个文件,如下所述

  • __mocks__/styleMock.js
module.exports = {};
  • __mocks__/fileMock.js
module.exports = 'test-file-stub';

如果您使用的是 CSS 模块,那么最好模拟代理以启用类名查找。
因此您的配置将更改为:

{
  "jest":{
     "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less|scss|sass)$": "identity-obj-proxy"
    },
  }
}

但是您需要安装identity-obj-proxy包作为开发依赖项,即

yarn add identity-obj-proxy -D

了解更多信息。 你可以参考jest docs

请注意,如果您的 CSS 模块导出 JSX 文件所依赖的值,则此处推荐的方法将不起作用。 大多数指南假定您只使用 CSS 模块来导出类名。 我希望有一个正确模拟 CSS 模块的指南。

@matthew-dean “正确模拟 CSS 模块”是什么意思? 你能再描述一下你的用例吗? 我有很好的使用identity-obj-proxy的经验

:export {
  sizeMobile: $size-mobile / 1px;
  sizePhablet: $size-phablet / 1px;
  sizeSmallTablet: $size-small-tablet / 1px;
  sizeTablet: $size-tablet / 1px;
  sizeDesktop: $size-desktop / 1px;
  sizeLargeDesktop: $size-large-desktop / 1px;
}
import styles from './variables.scss'

const tileSize = parseFloat(styles.sizeTablet) / 3
//...
render() {
  return <Tile style={{width: tileSize}} />
}

这是一个人为的例子,只是演示了您可以在 CSS 模块和 JS 之间共享常量(值),并且可以根据值分配条件渲染或动态道具。

但是使用identity-obj-proxy ,这些值不能转换为整数,更不用说存在的实际值了。 因此,如果您的 JSX 代码依赖于 CSS 模块中定义的常量,那么如果不正确模拟 CSS 模块(返回的对象具有可测试整数的值),您将无法对其进行测试。 identity-obj-proxy仅假定您的 CSS 模块包含一个对象,该对象仅具有范围的 CSS 类名; 它不支持 CSS 模块的另一个方面,即导出值/常量的能力,这些值/常量又在 JS 操作中使用。

@SimenB

顺便说一句,我能够像这样成功地模拟 CSS 模块:

const styles = require('styles/variables.scss')

jest.mock('styles/variables.scss', () => {
  return {
    sizePhablet: 500,
    sizeSmallTablet: 768,
    sizeTablet: 1024,
    sizeDesktop: 1440,
    sizeLargeDesktop: 1920
  }
})

希望这对使用 CSS 模块的所有功能的其他人有用,并且像我一样,在所有默认的“只使用identity-obj-proxy ”建议中撕毁他们的头发。

我通过使用“jest-transform-css”解决了这个问题。
安装后,在 jest config 中添加以下内容。

"transform": {
      "^.+\\.js$": "babel-jest",
      ".+\\.(css|styl|less|sass|scss)$": "jest-transform-css"
    }

现在 css 文件将像 js 文件一样被转译。

@matthew-dean 您在哪里编写了 CSS 模块的模拟以及如何将它引用到 jest?

我正在使用外部包,它使用以下命令将自己的文件导入到单个文件中:
<strong i="6">@import</strong> "progress-tracker/progress-tracker-variables.scss";

每当我运行 Jest for 开始测试时
image
上面的错误出现了。 我已经在 package.json 中指定了 css 模型
image

我期待获得有关该问题的一些帮助。 有什么技巧、建议吗?

编辑:我已经尝试过 babel-jest 和 identity-obj-proxy 包,但都没有。 问题仍然存在。

编辑2:我也根据我在网上遇到的解决方案尝试了下面的配置。
image

我正在使用 Babel 7 , babel-jest ^24.5.0 , Jest ^24.1.0

遵循上述建议后,当我尝试将目标文件(例如import Post.test.js Post.js ) 导入一个 CSS 文件 - 例如./postStyles.css

Jest encountered an unexpected token

SyntaxError: Unexpected token .

Details:

    /Users/ben/Desktop/Work/code/bengrunfeld/src/front-end/components/Post/postStyles.css:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.post h1, .post h2, .post h3 {

      3 |
      4 | import { PostText } from './styles'
    > 5 | import './postStyles.css'

根据上面链接的文章,这是我的package.json

"jest": {
    "moduleFileExtensions": ["js", "jsx"],
    "moduleDirectories": ["node_modules", "bower_components", "shared"],

    "moduleNameMapper": {
      "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
      "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js",

      "^react(.*)$": "<rootDir>/vendor/react-master$1",
      "^config$": "<rootDir>/configs/app-config.js"
    }
  },

在根目录中,我有__mocks__/styleMock.js ,其中包含以下代码:

module.exports = {};

最后,我的jest.config.js

module.exports = {
  setupFiles: ['<rootDir>/src/test/setup.js']
}

依次配置酶:

import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

Enzyme.configure({ adapter: new Adapter() })

import Error
我正在努力解决我的 scss 文件包含@import语句的几乎相同的问题。 测试失败并告诉 SyntaxError:无效或意外令牌。 有人可以帮我吗?

我遵循了上面给出的解决方案,但似乎没有一个对我有用

我能够通过添加@babel/polyfill作为开发依赖项来解决这个问题

同样在这里@ftomas82

我通过在 package.json 文件的 jest 配置中使用moduleNameMapper键解决了这个问题

{
   "jest":{
        "moduleNameMapper":{
             "\\.(css|less|sass|scss)$": "<rootDir>/__mocks__/styleMock.js",
             "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
        }
   }
}

在此之后,您将需要创建两个文件,如下所述

  • __mocks__/styleMock.js
module.exports = {};
  • __mocks__/fileMock.js
module.exports = 'test-file-stub';

如果您使用的是 CSS 模块,那么最好模拟代理以启用类名查找。
因此您的配置将更改为:

{
  "jest":{
     "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less|scss|sass)$": "identity-obj-proxy"
    },
  }
}

但是您需要安装identity-obj-proxy包作为开发依赖项,即

yarn add identity-obj-proxy -D

了解更多信息。 你可以参考jest docs

它对我有用。 谢谢!!!

我通过使用“jest-transform-css”解决了这个问题。
安装后,在 jest config 中添加以下内容。

"transform": {
      "^.+\\.js$": "babel-jest",
      ".+\\.(css|styl|less|sass|scss)$": "jest-transform-css"
    }

现在 css 文件将像 js 文件一样被转译。

谢谢,兄弟@krajasekhar
它对我有用👍

我将建议的配置添加到packages.json ,但没有成功,然后我意识到我的项目根目录中有一个jest.config.js ,Jest 在packages.json上使用该配置文件。

这里是我的jest.config.js文件供参考:

module.exports = {
  setupFilesAfterEnv: ['<rootDir>/.setup-tests.js'],
  testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
  transform: {
    '^.+\\.js$': 'babel-jest',
    '.+\\.(css|styl|less|sass|scss)$': 'jest-transform-css',
  },
};

我必须在我的代码中导入原始 css

import "./cloud.css?raw"

我还修改了 jest 配置
"jest":{ "moduleNameMapper": { "\\.(css|less|scss|sass|css?raw)$": "identity-obj-proxy" },

仍然,我在导入行上遇到测试错误。 知道如何模拟原始导入吗?

@import Unexpected token=的解决方法=:)

安装包:
npm i --save-dev identity-obj-proxy

添加 jest.config.js

module.exports = {
  "moduleNameMapper": {
    "\\.(css|less|scss)$": "identity-obj-proxy"
  }
}

如果有人到达这里:
这个模块是我见过的最新的: https ://www.npmjs.com/package/jest-css-modules-transform

transform: { '^.+\\.(js|jsx|ts|tsx)$': '<rootDir>/node_modules/babel-jest', ".+\\.(css|styl|less|sass|scss)$": "jest-css-modules-transform" }, transformIgnorePatterns: [ '/node_modules/', '^.+\\.module\\.(css|sass|scss)$', ], moduleNameMapper: { '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy' },

我将建议的配置添加到packages.json ,但没有成功,然后我意识到我的项目根目录中有一个jest.config.js ,Jest 在packages.json上使用该配置文件。

这里是我的jest.config.js文件供参考:

module.exports = {
  setupFilesAfterEnv: ['<rootDir>/.setup-tests.js'],
  testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
  transform: {
    '^.+\\.js$': 'babel-jest',
    '.+\\.(css|styl|less|sass|scss)$': 'jest-transform-css',
  },
};

感谢所有提出解决方案的人,特别是@Shadoow! 这是一种逻辑的事情,但我错过了......配置文件将用于 package.json 中的设置

简而言之,对于新人来说,对我有用的是我们的社区梦之队提出的多种解决方案的结合:

1) 创建一个 jest.config.json 文件

touch jest.config.json open jest.config.json

2) 安装 jest-transform-css:

yarn add jest-transform-css -D

3) 这就是你的 jest 配置文件的样子:

module.exports = {
  preset: 'ts-jest/presets/js-with-babel',
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)$': './jest.mock.js',
  },
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/assets/'],
  transform: {
    '^.+\\.jsx?$': 'babel-jest',
    '\\.(css|less|scss|sass)$': 'jest-transform-css',
  },
};

4) 更新你的 package.json (首先,将你所有的 JEST 配置,如果你有的话,转移到新的 jest 配置文件中),那么神奇的地方就在这里:

"test": "jest --config ./jest.config.js"

谢谢大家!

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

hramos picture hramos  ·  3评论

paularmstrong picture paularmstrong  ·  3评论

StephanBijzitter picture StephanBijzitter  ·  3评论

Secretmapper picture Secretmapper  ·  3评论

Antho2407 picture Antho2407  ·  3评论