Jest: Jest не работает с JSX, который импортирует CSS

Созданный на 7 мар. 2017  ·  24Комментарии  ·  Источник: facebook/jest

Вы хотите запросить функцию или сообщить об ошибке ?
Ошибка

Каково текущее поведение?
Если у app.jsx есть import './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=клиентская шутка -u

PS Все работает хорошо, если я прокомментирую/удалю import './app.css';

Самый полезный комментарий

Я решил это, используя ключ moduleNameMapper в настройках jest в файле package.json.

{
   "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, лучше смоделировать прокси-сервер, чтобы включить поиск className.
следовательно, ваши конфигурации изменятся на:

{
  "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

Чтобы получить больше информации. Вы можете обратиться к шутливым документам

Все 24 Комментарий

@maximderbin Спасибо!

@maximderbin Спасибо! Это решает мою проблему, добавляя moduleNameMapper

@svipben @maximderbin @simonxl куда мне добавить этот модульNameMapper?
Я вижу в документе, что мы добавим его в package.json, но в какой?
спасибо

@sarahmarciano moduleNameMapper является частью вашей конфигурации. По умолчанию вы можете установить конфигурацию в package.json (тот, который содержит jest в зависимостях) под ключом «jest», например:

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

Я решил это, используя ключ moduleNameMapper в настройках jest в файле package.json.

{
   "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, лучше смоделировать прокси-сервер, чтобы включить поиск className.
следовательно, ваши конфигурации изменятся на:

{
  "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

Чтобы получить больше информации. Вы можете обратиться к шутливым документам

Обратите внимание, что рекомендуемые здесь подходы не будут работать, если ваши модули 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.

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

Теперь файлы css будут транспилироваться так же, как и файлы js.

@matthew-dean, где вы написали макет модуля CSS и как вы ссылаетесь на него для шутки?

Я использую внешний пакет, и он импортирует свои файлы в один файл, используя следующее:
<strong i="6">@import</strong> "progress-tracker/progress-tracker-variables.scss";

Всякий раз, когда я запускаю Jest, чтобы начать тестирование
image
появляется ошибка выше. Я уже указал мокап css внутри package.json
image

Я с нетерпением жду помощи по этому вопросу. Есть какие-нибудь хитрости, предложения?

Изменить: я пробовал пакеты babel-jest и identity-obj-proxy, и ни один из них не работал. Проблема все еще сохраняется.

Редактировать 2: Также я попробовал приведенную ниже конфигурацию в соответствии с решениями, с которыми я столкнулся в Интернете.
image

Я использую Babel 7 , babel-jest ^24.5.0 , Jest ^24.1.0 .

Следуя приведенному выше совету, я все еще получаю эту ошибку, когда пытаюсь import функцию или объект в тестовый файл Jest (например, 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']
}

Что, в свою очередь, настраивает Enzyme:

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

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

import Error
Я изо всех сил пытаюсь решить почти ту же проблему, когда мой файл scss содержит операторы @import . Тест завершается с ошибкой SyntaxError: неверный или неожиданный токен. Может кто-нибудь помочь мне, пожалуйста?

Я следовал решениям, приведенным выше, но ни одно из них, похоже, не работает для меня.

Я смог решить эту проблему, добавив @babel/polyfill в качестве зависимости от разработчиков.

то же самое @ftomas82

Я решил это, используя ключ moduleNameMapper в настройках jest в файле package.json.

{
   "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, лучше смоделировать прокси-сервер, чтобы включить поиск className.
следовательно, ваши конфигурации изменятся на:

{
  "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-transform-css.
После установки добавил следующее в конфиг jest.

"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":{ "moduleNameMapper": { "\\.(css|less|scss|sass|css?raw)$": "identity-obj-proxy" },

тем не менее, я получаю тестовую ошибку в строке импорта. Любая идея, как издеваться над необработанным импортом?

Решение @import Неожиданный токен=:)

Установить пакет:
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 рейтинги