how to test @mdx-js/mdx with jest (transformIgnorePatterns not working on 'develop' module)

133 views Asked by At

My ultimate goal is to be able to write tests in Jest that can import from @mdx-js/mdx, which is an ESM module, and since the library package under development is configured for commonsjs, I am using the transform and transformIgnorePatterns method in my jest.config.ts.

/* eslint-disable */
import { readFileSync } from 'fs';
import type { Config } from 'jest';

// Reading the SWC compilation config and remove the "exclude"
// for the test files to be compiled by SWC
const { exclude: _, ...swcJestConfig } = JSON.parse(readFileSync(`${__dirname}/.swcrc`, 'utf-8'));

// disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves.
// If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude"
if (swcJestConfig.swcrc === undefined) {
  swcJestConfig.swcrc = false;
}

// Uncomment if using global setup/teardown files being transformed via swc
// https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries
// jest needs EsModule Interop to find the default exported setup/teardown functions
// swcJestConfig.module.noInterop = false;

export default {
  displayName: 'jest-mdx-transformer',
  preset: '../../jest.preset.js',
  transform: {
    '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
  },
  transformIgnorePatterns: [
    '/node_modules/(?!(@mdx-js/mdx|develop|markdown-extensions|unist-util-stringify-position|vfile|vfile-message)/)',
  ],
  moduleFileExtensions: ['ts', 'js', 'json', 'mdx', 'html'],
  testEnvironment: 'node',
  coverageDirectory: '../../coverage/libs/jest-mdx-transformer',
} satisfies Config;

My typical process is to keep expanding this RegExp until Jest no longer complains about transforming ESM in node_modules, which worked well until I added the develop package. Whether it is there or not produces an identical error:

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:

/workspace/perpetual-cabbage/node_modules/devlop/lib/default.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export function deprecate(fn) {
                                                                                  ^^^^^^

SyntaxError: Unexpected token 'export'

  3 | describe('watheia.cabbage/jest-mdx-transformer', () => {
  4 |   it('should render mdx in jest', async () => {
> 5 |     const result = await compile('# Hello, World!');
    |              ^
  6 |     expect(result).toBeDefined();
  7 |   });
  8 | });

  at Runtime.createScriptFromCode (../../node_modules/jest-runtime/build/index.js:1505:14)
  at Object.<anonymous> (../../node_modules/@mdx-js/mdx/lib/core.js:136:17)
  at Object.<anonymous> (../../node_modules/@mdx-js/mdx/lib/compile.js:40:15)
  at Object.<anonymous> (../../node_modules/@mdx-js/mdx/index.js:46:18)
  at Object.<anonymous> (test/jest-mdx-transformer.spec.ts:5:14)

Why did it transform all the other packages I added but not develop? I don't see anything particularly different for this one. I would expect it to be transpiled like all the others in that RegExp.

While I would like to understand what's going on here, I would accept any possible workaround as a solution.

Thanks for your time!

1

There are 1 answers

0
drkstr101 On

I was able to come up with a workaround, but I will wait to accept an answer since it is not portable and doesn't address the underlying issue of Jest failing to transform a package as expected.

Since I am working in an Nx monorepo, I was able to create a simple wrapper library to export the symbols from @mdx-js/mdx and then use rollup to bundle this library as both ESM and CJS. Next, update the consuming library to import from the dist artifacts, and Jest will be able to pick up the fully transformed CJS module from there. No further transformation is needed.

// eslint-disable-next-line @nx/enforce-module-boundaries
import { compile } from '../../../dist/libs/mdx';

describe('compile', () => {
  it('should compile mdx content', async () => {
    const result = await compile('# Hello, World!');
    expect(result).toBeDefined();
  });
});

If possible, update your build system to invoke a build before running tests. For nx, you would set the dependsOn option in your project.json.