Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make jest run with the same config as react-script test on a create-react-app?

I know I can run npm test which runs react-script test and it works, it successfully run the tests. But I'm interested in figuring out how to run jest directly with the same configuration react-script uses. Hopefully without having to replicate the configuration or ejecting the app. I started reading the source code of react-scripts but so far I couldn't figure it out.

The reasons for wanting this are:

  • My CRA project is part of a bigger project, and I could just run jest on the top level and run all tests.
  • In WebStorm, I can take advantage of the Jest integration, which includes:
    • Showing the list of tests that pass or fail, as they run.
    • Being able to run individual tests.
    • Doing code coverage.

If I run jest on my CRA app, I get this error:

PS C:\Users\pupeno\Documents\Flexpoint Tech\js\exp7\frontend> jest
 FAIL  src/App.test.tsx
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    SyntaxError: C:\Users\pupeno\Documents\Flexpoint Tech\js\exp7\frontend\src\App.test.tsx: Unexpected token (6:29)

      4 | 
      5 | test("renders Facebook link", () => {
    > 6 |   const {getByText} = render(<App/>)
        |                              ^
      7 |   const linkElement = getByText(/Loading.../i)
      8 |   expect(linkElement).toBeInTheDocument()
      9 | })

      at Parser._raise (node_modules/@babel/parser/src/parser/error.js:60:45)
      at Parser.raiseWithData (node_modules/@babel/parser/src/parser/error.js:55:17)
      at Parser.raise (node_modules/@babel/parser/src/parser/error.js:39:17)
      at Parser.unexpected (node_modules/@babel/parser/src/parser/util.js:149:16)
      at Parser.parseExprAtom (node_modules/@babel/parser/src/parser/expression.js:1174:20)
      at Parser.parseExprSubscripts (node_modules/@babel/parser/src/parser/expression.js:541:23)
      at Parser.parseMaybeUnary (node_modules/@babel/parser/src/parser/expression.js:521:21)
      at Parser.parseExprOps (node_modules/@babel/parser/src/parser/expression.js:312:23)
      at Parser.parseMaybeConditional (node_modules/@babel/parser/src/parser/expression.js:264:23)
      at Parser.parseMaybeAssign (node_modules/@babel/parser/src/parser/expression.js:212:21)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        2.234s
Ran all test suites.

I'm trying to do this without ejecting, to not lose the benefits of CRA. I understand that if I eject I can do pretty much whatever I want.

like image 558
pupeno Avatar asked Mar 02 '23 08:03

pupeno


1 Answers

create-react-app Jest configuration isn't supposed to be available without ejection. react-script test programmatically runs Jest with dynamically generated configuration. It's exported to static configuration file on eject.

The problem is that ejection still doesn't allow to run tests the same way with Jest CLI because in ejected project, Jest still runs programmatically via scripts/test.js. The script is responsible for setting up CRA environment variables, they should be additionally supplied to Jest CLI. This should be evaluated in either jest.config.js or globalSetup file:

process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';
require('react-scripts/config/env');

Eject

Considering that unejected projects doesn't provide any benefits that are inherent to generated projects like scaffolding, it's preferable to eject as soon as any customization is needed.

A configuration from ejected project

If it's necessary to keep the project unejected, it can be cloned and ejected, then Jest configuration (config/jest/*.* and jest entry from package.json) is transferred to unejected project. This can be achieved with Git branches.

A workaround

Alternatively, its possible to retrieve generated configuration similarly to how CRA does this via a hack that relies on react-scripts internals:

jest.config.js

process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';
require('react-scripts/config/env');

const path = require('path');
const createJestConfig = require('react-scripts/scripts/utils/createJestConfig');

module.exports = createJestConfig(
  relativePath => require.resolve(path.join('react-scripts', relativePath)),
  __dirname, // given that Jest config is in project root
  false
);
like image 83
Estus Flask Avatar answered Mar 05 '23 16:03

Estus Flask