Gatsby: [v2] Jest + react-testing-library

Created on 19 Jul 2018  ·  10Comments  ·  Source: gatsbyjs/gatsby

Description

I want to run tests with Jest and react-testing-library in my Gatsby v2 project. The unit tests on my utitilities (which use module.exports, require) with Jest work without problems.

But when I want to use react-testing-library and use import I get the error:

Details:

    E:\Lennart\Documents\GitLab\xxx\node_modules\gatsby\cache-dir\gatsby-browser-entry.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import React from "react"
                                                                                             ^^^^^^

    SyntaxError: Unexpected token import

      1 | import React from 'react';
    > 2 | import { graphql } from 'gatsby';
        | ^
      3 | import PropTypes from 'prop-types';
      4 | import styled from 'react-emotion';
      5 | import format from 'date-fns/format';

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
      at Object.<anonymous> (src/components/DocFooter.jsx:2:1)
      at Object.<anonymous> (src/components/__tests__/DocFooter.js:3:1)

My files

jest.config.js

module.exports = {
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|mp3|mp4|svg|woff|woff2)$': '<rootDir>/test/__mocks__/fileMock.js',
  },
  testPathIgnorePatterns: ['/node_modules/', '<rootDir>/.cache/', '<rootDir>/src/_examples/'],
  globals: {
    __PATH_PREFIX__: '',
  },
  transform: {
    '^.+\\.js$': '<rootDir>/test/jest-preprocess.js',
    '^.+\\.jsx$': '<rootDir>/test/jest-preprocess.js',
  },
};

jest-preprocess.js

const babelOptions = {
  presets: ['@babel/preset-react', '@babel/preset-env'],
  plugins: ['syntax-class-properties', 'transform-class-properties'],
};

module.exports = require('babel-jest').createTransformer(babelOptions);

package.json

{
  "dependencies": {
    "cross-spawn": "^6.0.5",
    "date-fns": "^1.29.0",
    "emotion": "^9.2.6",
    "emotion-server": "^9.2.6",
    "emotion-theming": "^9.2.6",
    "gatsby": "^2.0.0-beta.42",
    "gatsby-image": "^2.0.0-beta.6",
    "gatsby-plugin-catch-links": "^2.0.2-beta.3",
    "gatsby-plugin-emotion": "^2.0.0-beta.2",
    "gatsby-plugin-lodash": "^3.0.1-beta.2",
    "gatsby-plugin-manifest": "^2.0.2-beta.2",
    "gatsby-plugin-netlify": "^2.0.0-beta.3",
    "gatsby-plugin-netlify-cache": "^0.1.0",
    "gatsby-plugin-offline": "^2.0.0-beta.3",
    "gatsby-plugin-react-helmet": "^3.0.0-beta.3",
    "gatsby-plugin-sharp": "^2.0.0-beta.5",
    "gatsby-plugin-sitemap": "^2.0.0-beta.2",
    "gatsby-plugin-typography": "^2.2.0-beta.2",
    "gatsby-remark-autolink-headers": "^2.0.0-beta.3",
    "gatsby-remark-design-system": "^1.0.16",
    "gatsby-remark-external-links": "^0.0.4",
    "gatsby-remark-prismjs": "^3.0.0-beta.3",
    "gatsby-remark-responsive-iframe": "^2.0.0-beta.2",
    "gatsby-source-filesystem": "^2.0.1-beta.5",
    "gatsby-transformer-remark": "^2.1.1-beta.3",
    "gatsby-transformer-sharp": "^2.1.1-beta.4",
    "polished": "^1.9.2",
    "prismjs": "^1.14.0",
    "prop-types": "^15.6.1",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-emotion": "^9.2.3",
    "react-helmet": "^5.2.0",
    "react-media": "^1.8.0",
    "react-transition-group": "^2.3.1",
    "react-typography": "^0.16.13",
    "typeface-lora": "^0.0.54",
    "typeface-source-sans-pro": "^0.0.54",
    "typography": "^0.16.17"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0-beta.54",
    "@babel/preset-env": "^7.0.0-beta.54",
    "@babel/preset-react": "^7.0.0-beta.54",
    "babel-core": "^7.0.0-0",
    "babel-eslint": "^8.2.3",
    "babel-jest": "^23.4.0",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-config-prettier": "^2.9.0",
    "eslint-plugin-import": "^2.12.0",
    "eslint-plugin-jest": "^21.17.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-prettier": "^2.6.0",
    "eslint-plugin-react": "^7.9.1",
    "jest": "^23.4.1",
    "jest-dom": "^1.8.1",
    "prettier": "^1.13.5",
    "react-testing-library": "^4.1.3"
  },
  "browserslist": [
    "> 1%",
    "IE >= 9",
    "last 2 versions"
  ]
}

Question

I couldn't find any example for Jest + Gatsby v2. How can I get this working? I already looked at this issue:
https://github.com/gatsbyjs/gatsby/issues/2932

help wanted question or discussion

Most helpful comment

Hey. You need to add this to your jest config:

        "transformIgnorePatterns": [
            "node_modules/(?!(gatsby)/)"
        ]

The problem is the same that I had in #6527. Babel is ignoring node_modules (as it should), but Gatsby has some non-transpiled files in cache-dir. Changing it to the pattern above means it ignores node_modules, except gatsby.

All 10 comments

Hey. You need to add this to your jest config:

        "transformIgnorePatterns": [
            "node_modules/(?!(gatsby)/)"
        ]

The problem is the same that I had in #6527. Babel is ignoring node_modules (as it should), but Gatsby has some non-transpiled files in cache-dir. Changing it to the pattern above means it ignores node_modules, except gatsby.

@ascorbic Thanks! That solved my import issue.

Now I got issues with emotion:

 FAIL  src/components/__tests__/DocFooter.js
  ● Test suite failed to run

    You're trying to use the styled shorthand without babel-plugin-emotion.
    Please install and setup babel-plugin-emotion or use the function call syntax(`styled('div')` instead of `styled.div`)

       6 | import settings from '../../config/settings';
       7 |
    >  8 | const Wrapper = styled.div`
         |                        ^
       9 |   display: flex;
      10 |   justify-items: center;
      11 |   padding: 1rem 0;

      at Object.get (node_modules/create-emotion-styled/src/index.js:201:19)
      at Object.<anonymous> (src/components/DocFooter.jsx:8:24)
      at Object.<anonymous> (src/components/__tests__/DocFooter.js:3:1)

I did install babel-plugin-emotion and put it into the plugins array.

You mean the plugins array in jest-preprocess.js?

Yes.

const babelOptions = {
  presets: ['@babel/preset-react', '@babel/preset-env'],
  plugins: ['syntax-class-properties', 'transform-class-properties', 'emotion'],
};

module.exports = require('babel-jest').createTransformer(babelOptions);

I'm using Gatsby's emotion plugin which sets the babel plugin for the rest of the site.

Update: I put emotion in first place, installed jest-emotion and did a jest --clearCache. Solved the issue.

New issue came up:

 FAIL  src/components/__tests__/DocFooter.js
  ● Test suite failed to run

    It appears like Gatsby is misconfigured. Gatsby related `graphql` calls are supposed to only be evaluated at compile time, and then
 compiled away,. Unfortunately, something went wrong and the query was left in the compiled code.

    .Unless your site has a complex or custom babel/Gatsby configuration this is likely a bug in Gatsby.

      88 | };
      89 |
    > 90 | export const fragment = graphql`
         |              ^
      91 |   fragment DocFooter on MarkdownRemark {
      92 |     parent {
      93 |       ... on File {

      at graphql (node_modules/gatsby/cache-dir/gatsby-browser-entry.js:33:9)
      at Object.<anonymous> (src/components/DocFooter.jsx:90:14)
      at Object.<anonymous> (src/components/__tests__/DocFooter.js:3:1)

After removing the fragment, the error obviously went away. I'm fine with that right now, I don't have to use the fragment.

I also had to wrap my component in my ThemeProvider. Is there a better solution instead of wrapping each component in future tests?

import React from 'react';
import { render, cleanup } from 'react-testing-library';
import { ThemeProvider } from 'emotion-theming';
import DocFooter from '../DocFooter';
import theme from '../../../config/theme';

const docMock = {
  parent: {
    relativePath: 'product/foundations/accessibility.md',
  },
};

afterEach(cleanup);

test('Displaying the different options in the DocFooter', () => {
  const { getByTestId, rerender } = render(
    <ThemeProvider theme={theme}>
      <DocFooter doc={docMock} editLink lastUpdated date={1531949762} />
    </ThemeProvider>
  );
});

@ascorbic Got everything working now also with emotion. Do you want to create a Doc on testing with me? You can reach me on Discord

I've made a PR for a first draft doc. I'd welcome feedback: #6678

Closing this issue as PRs for this will merge soon.

Ran into this problem yesterday. For jest to work, you need to enable modules: 'commonjs' option for @babel/preset-env.

Was this page helpful?
0 / 5 - 0 ratings