Jest: Jest não funciona com JSX que importa CSS

Criado em 7 mar. 2017  ·  24Comentários  ·  Fonte: facebook/jest

Deseja solicitar um recurso ou relatar um bug ?
Erro

Qual é o comportamento atual?
Se app.jsx tiver import './app.css'; é impossível executar o teste, recebi este erro:

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.

Qual é o comportamento esperado?
Para executar testes sem erro...

Forneça sua configuração exata do Jest e mencione seu Jest, nó, versão yarn/npm e sistema operacional.

SO: Linux Ubuntu 16.04
Jest: mais recente
Fio: mais recente
Nó: mais recente
babel-jest : mais recente

.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
        },

jest: NODE_ENV=client jest -u

PS Tudo funciona bem se eu comentar/remover import './app.css';

Comentários muito úteis

Resolvi isso usando a chave moduleNameMapper nas configurações do jest no arquivo package.json

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

Depois disso, você precisará criar os dois arquivos conforme descrito abaixo

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

Se você estiver usando módulos CSS, é melhor simular um proxy para habilitar pesquisas className.
portanto, suas configurações serão alteradas para:

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

Mas você precisará instalar o pacote identity-obj-proxy como uma dependência de desenvolvimento, ou seja

yarn add identity-obj-proxy -D

Para maiores informações. Você pode consultar os documentos do jest

Todos 24 comentários

@maximderbin Obrigado!

@maximderbin Obrigado! Ele resolve meu problema adicionando moduleNameMapper

@svipben @maximderbin @simonxl onde devo adicionar este moduleNameMapper?
Vejo no doc que devemos adicioná-lo no packag.json, mas qual?
tnx

@sarahmarciano moduleNameMapper faz parte da sua configuração. Por padrão, você pode definir a configuração em package.json (aquele que apresenta jest nas dependências) na chave "jest", assim:

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

Resolvi isso usando a chave moduleNameMapper nas configurações do jest no arquivo package.json

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

Depois disso, você precisará criar os dois arquivos conforme descrito abaixo

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

Se você estiver usando módulos CSS, é melhor simular um proxy para habilitar pesquisas className.
portanto, suas configurações serão alteradas para:

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

Mas você precisará instalar o pacote identity-obj-proxy como uma dependência de desenvolvimento, ou seja

yarn add identity-obj-proxy -D

Para maiores informações. Você pode consultar os documentos do jest

Observe que as abordagens recomendadas aqui não funcionarão se seus módulos CSS exportarem valores dos quais seus arquivos JSX dependem. A maioria dos guias assume que você está usando apenas módulos CSS para exportar nomes de classes. Eu gostaria que houvesse um guia para zombar adequadamente de módulos CSS.

@matthew-dean o que você quer dizer com "módulos CSS zombando adequadamente"? Você pode descrever seu caso de uso um pouco mais? Eu tenho uma grande experiência usando 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}} />
}

Este é um exemplo artificial, apenas demonstrando que você pode compartilhar constantes (valores) entre módulos CSS e JS, e que renderização condicional ou props dinâmicas podem ser atribuídas com base em valores.

Mas com identity-obj-proxy , esses valores não podem ser convertidos em inteiros, muito menos os valores reais que estão presentes. Portanto, se você tiver código JSX que depende de constantes definidas em seus módulos CSS, não poderá testar isso sem zombar adequadamente do módulo CSS (tendo um objeto retornado que tenha os valores como inteiros testáveis). identity-obj-proxy apenas assume que seus módulos CSS contêm um objeto com nada mais do que nomes de classes CSS com escopo; ele não suporta o outro aspecto dos módulos CSS que é a capacidade de exportar valores/constantes que por sua vez são usados ​​em operações JS.

@SimenB

Aliás, consegui zombar do módulo CSS com sucesso assim:

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

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

Espero que seja útil para outra pessoa que está usando todos os recursos dos módulos CSS e, como eu, estava arrancando os cabelos com o conselho padrão "apenas use identity-obj-proxy ".

Eu resolvi esse problema usando 'jest-transform-css'.
Após a instalação, adicionei o abaixo na configuração do jest.

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

Agora os arquivos css serão transpilados assim como os arquivos js.

@matthew-dean onde você escreveu o mock do módulo CSS e como você o referenciou ao jest?

Estou usando um pacote externo e ele importa seus próprios arquivos para um único arquivo usando o seguinte:
<strong i="6">@import</strong> "progress-tracker/progress-tracker-variables.scss";

Sempre que executo o Jest para começar a testar
image
aparece o erro acima. Eu já especifiquei o mockup css dentro do package.json
image

Estou ansioso para obter alguma ajuda sobre esse problema. Algum truque, sugestão?

Edit: Eu tentei os pacotes babel-jest e identity-obj-proxy e nenhum deles funcionou. O problema ainda persiste.

Edit 2: Também tentei a configuração abaixo de acordo com as soluções que encontrei na web.
image

Estou usando Babel 7 , babel-jest ^24.5.0 , Jest ^24.1.0 .

Depois de seguir o conselho acima, ainda estou recebendo este erro quando tento import uma função ou objeto em um arquivo de teste Jest (por exemplo Post.test.js ) quando o arquivo de destino (por exemplo Post.js ) importa um arquivo CSS - por exemplo ./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'

De acordo com o artigo vinculado acima, isso está no meu 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"
    }
  },

e no diretório raiz, tenho __mocks__/styleMock.js que possui o seguinte código:

module.exports = {};

Por fim, meus jest.config.js :

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

Que por sua vez configura Enzyme:

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

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

import Error
Estou lutando para resolver quase o mesmo problema em que meu arquivo scss contém instruções @import . Falha no teste informando SyntaxError: token inválido ou inesperado. Alguém pode me ajudar por favor?

Eu segui as soluções dadas acima, mas nenhuma delas parece estar funcionando para mim

Consegui resolver isso adicionando @babel/polyfill como uma dependência de desenvolvimento

mesmo aqui @ftomas82

Resolvi isso usando a chave moduleNameMapper nas configurações do jest no arquivo package.json

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

Depois disso, você precisará criar os dois arquivos conforme descrito abaixo

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

Se você estiver usando módulos CSS, é melhor simular um proxy para habilitar pesquisas className.
portanto, suas configurações serão alteradas para:

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

Mas você precisará instalar o pacote identity-obj-proxy como uma dependência de desenvolvimento, ou seja

yarn add identity-obj-proxy -D

Para maiores informações. Você pode consultar os documentos do jest

Funcionou para mim. Obrigado!!!

Eu resolvi esse problema usando 'jest-transform-css'.
Após a instalação, adicionei o abaixo na configuração do jest.

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

Agora os arquivos css serão transpilados assim como os arquivos js.

Obrigado, mano @krajasekhar
Funciona comigo 👍

Adicionei a configuração sugerida a packages.json , sem sucesso, então percebi que tinha um jest.config.js no diretório raiz do meu projeto, Jest usa esse arquivo de configuração em packages.json .

Para referência aqui está meu arquivo 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',
  },
};

Eu tenho que importar um css bruto no meu código

import "./cloud.css?raw"

Eu também modifiquei a configuração do jest
"jest":{ "moduleNameMapper": { "\\.(css|less|scss|sass|css?raw)$": "identity-obj-proxy" },

ainda assim, estou recebendo erro de teste na linha de importação. Alguma idéia de como simular importação bruta?

Solução de @import Unexpected token= :)

Instale o pacote:
npm i --save-dev identity-obj-proxy

Adicione jest.config.js

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

Se alguém chegar aqui:
Este módulo é o mais atualizado que já vi: 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' },

Adicionei a configuração sugerida a packages.json , sem sucesso, então percebi que tinha um jest.config.js no diretório raiz do meu projeto, Jest usa esse arquivo de configuração em packages.json .

Para referência aqui está meu arquivo 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',
  },
};

Obrigado a todos que apresentaram uma solução e especialmente a você @Shadoow! Era um tipo de coisa lógica, mas estava faltando isso ... o arquivo de configuração será usado sobre as configurações em package.json

Em suma, para os recém-chegados, o que funcionou para mim foi uma união de várias soluções apresentadas pelo nosso time dos sonhos da comunidade:

1) crie um arquivo jest.config.json

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

2) Instale o jest-transform-css:

yarn add jest-transform-css -D

3) É assim que seu arquivo de configuração do jest deve ficar:

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) Atualize seu package.json (primeiro, transfira todas as suas configurações do JEST, se você tiver alguma lá, para o novo arquivo de configuração do jest), então a mágica vai aqui:

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

Tks a todos!

Esta página foi útil?
0 / 5 - 0 avaliações