Need help understanding this odd Jest behavior

Viewed 105

I built a button for a React component library. To test the component, I used jest@26, ts-jest@26, @types/jest@26, @testing-library/react@12.1.2, and @testing-library/jest-dom@5.14.1.

While running the test, it threw an error of TypeError: Cannot read property 'forwardRef' of undefined. This error pointed to the following line in my button component code:

export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(...)

I ended up resolving this error by explicitly importing forwardRef in my import statement and replacing React.forwardRef with it:

// this works for some reason in jest
import { forwardRef } from 'react';

export const Button = forwardRef(...)

This issue also applied to other aspects of my component code where I'm referencing attributes from PropTypes and resolving the error required me to explicitly import and reference those attributes.

// before (throws error in jest)
import PropTypes from 'prop-types';

Button.propTypes = {
  variant: PropTypes.oneOf([...]),
  size: PropTypes.oneOf([...]),
  isFullWidth: PropTypes.bool,
}

// after (passes in jest)
import { oneOf, bool } from 'prop-types';

Button.propTypes = {
  variant: oneOf([...]),
  size: oneOf([...]),
  isFullWidth: bool,
}

Despite the changes making my tests pass, I find it odd that I have to make these changes for Jest, because my former code works in the browser. I'm wondering if anyone else has encountered this issue and can explain this odd behavior.

1 Answers

In you tsconfig.json (or the tsconfig file you are using for Jest), turn on esModuleInterop flag

{
   compilerOptions: {
...
      esModuleInterop: true,
...
   }
}

This help do what allowSyntheticDefaultImports is supposed to do in normal Typescript app.

What allowSyntheticDefaultImports does is to allow default import to be equivalent to namespace import of a module.

The deprecate of allowSyntheticDefaultImports is mentioned here: https://github.com/kulshekhar/ts-jest/issues/632

Related