Search code examples
javascripttypescriptjestjsts-jestparceljs

Jest is not transforming our built design system package


We have been building a design system in our company. We are using material ui as a base. The app and the design system work fine, but we have a small problem with Jest. When running the tests, we are getting the following error:

❯ npx jest                                                         ⏎
 FAIL  src/App.test.tsx
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • 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/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /Users/antoniogamizdelgado/badger/minimal-example/frontends/design-system/dist/main.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import $681qW$styledcomponents from "styled-components";
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      1 | import * as React from 'react';
    > 2 | import {Tab} from "design-system";
        | ^
      3 | import {render} from "@testing-library/react";
      4 |
      5 |

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1505:14)
      at Object.<anonymous> (src/App.test.tsx:2:1)

Luckily we have been able to create a minimal example to reproduce the problem, you can find it here -> https://github.com/antoniogamizbadger/minimal-example/tree/minimal-example-material.

The process to reproduce it is:

npm ci
npm run build

From package directory:

npm ci
npx jest

We have more files using imports, so not sure why the transformers we have already setup are not working. Any idea how to fix the configuration?


Solution

  • It's because by default Jest will not run anything in node_modules through the transformers. This is usually a safe assumption since third-party deps are typically already transpiled in such a way that the CommonJS version is right there in the tarball (which Jest needs by default) when the package is downloaded from NPM.

    But then things get a bit grey when you have internal-only modules you don't really publish and want to build from source for convenience as opposed to having multiple build steps for the dependent package, which sounds like your situation. Worth noting though this way of doing things is not really best practice since it means the module is not perfectly encapsulated since its build step is conceptually owned by another module -- but I admittedly do it as well 👀, and you do see it often in enterprise projects. The alternative is often judged to be too much of a chore to have multiple build-watch processes running in several packages to do local development.

    You can make Jest compile this module. Add this to your "jest" configuration in the package modules package.json. This will make everything transform apart from any module that is not design-system in node_modules.

     "transformIgnorePatterns": [ "node_modules/(?!design-system)" ]