Wednesday, 25 August 2021

Configuring Jest with Rollup and Typescript

I created an app within a monorepo (Lerna) using yarn workspace.

The architecture of the app is as follow:

my-monorepo
├── node_modules
├── packages
│   ├── package1(shared components)
│   ├── package2(other package consuming the shared components)
│   │     └── ./jest.config.js
├── package.json

The problem

the problem is jest is throwing the following error when trying to use package1 in package2 in any test, and I haven't found a way to fix it.

● Test suite failed to run

    Jest encountered an unexpected token

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

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

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io
/docs/en/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can spe
cify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option i
n 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:

    C:\Users\my-user\Desktop\my-monorepo\node_module
s\antd\es\date-picker\generatePicker\index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__fi
lename,global,jest){import _extends from "@babel/runtime/helpers/esm/exte
nds";

                    ^^^^^^

According the error, I'm trying to import a file which Jest cannot parse, so the problem comes from the package1, so the first thing that comes to my mind is: maybe I'm doing something wrong in rollup in package1 and the final bundle comes in some format that jest doesn't understand...

Jest config

Jest config located in package2, where i want to consume package1:

// jest.config.js in package2

const config = {
  roots: ['src'],
  setupFilesAfterEnv: ['./jest.setup.ts'],
  moduleFileExtensions: ['ts', 'tsx', 'js'],
  testPathIgnorePatterns: ['node_modules/'],
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  testMatch: ['**/*.test.(ts|tsx)'],
  moduleNameMapper: {
    // Mocks out all these file formats when tests are run.
    '\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
      'identity-obj-proxy',
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
  },
};

export default config;

Rollup config

This is the rollup configuration in package1:

// rollup.config.js

import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from 'rollup-plugin-typescript2';
import postcss from 'rollup-plugin-postcss';
import copy from 'rollup-plugin-copy';
import json from '@rollup/plugin-json';
import svgr from '@svgr/rollup';
import { visualizer } from 'rollup-plugin-visualizer';

import pkg from './package.json';

export default {
  input: 'src/index.tsx',
  output: [
    {
      file: pkg.main,
      format: 'cjs',
      exports: 'named',
      sourcemap: true,
    },
    {
      file: pkg.module,
      format: 'esm',
      exports: 'named',
      sourcemap: true,
    },
  ],
  plugins: [
    peerDepsExternal({
      includeDependencies: true,
    }),
    json(),
    svgr(),
    resolve({ extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'] }),
    commonjs({
      include: /\**node_modules\**/,
    }),
    typescript({
      useTsconfigDeclarationDir: true,
      exclude: ['*.d.ts', '**/*.d.ts', '**/*.test.tsx'],
      rollupCommonJSResolveHack: true,
      clean: true,
    }),
    postcss({
      extensions: ['.css', '.less'],
      use: {
        less: { javascriptEnabled: true, modifyVars: {} },
      },
    }),
    visualizer({ filename: 'stats-visualizer.html', gzipSize: true }),
    copy({
      targets: [
        {
          src: 'src/styles/themes/dark-variables.less',
          dest: 'dist',
          rename: 'theme/dark.less',
        },
        {
          src: 'src/styles/themes/light-variables.less',
          dest: 'dist',
          rename: 'theme/light.less',
        },
        {
          src: 'src/assets/icons',
          dest: 'dist',
          rename: 'assets/icons',
        },
      ],
    }),
  ],
};

UPDATE 1:

I've tried to use transform rules in jest.config.js as mentioned by Matt Carlota to transpile antdbut this doesn't work:

// jest.config.js
const config = {
  // ... other jest settings
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
    'node_modules/antd/.+\\.(j|t)sx?$': 'ts-jest',
  },
  // I've tried with `antd/es` pattern too and doesn't work
  transformIgnorePatterns: ['node_modules/(?!antd)'],
};

UPDATE 2:

Change manually antd/es by antd/lib in package1 resolve the problem temporarily, but there is one problem and that is that we are a large group of people working and it could be put as a convention to use only antd/lib but I feel it would be error prone.

every time someone forgets to use antd/lib and uses antd/en all tests break with the original error.



from Configuring Jest with Rollup and Typescript

No comments:

Post a Comment