Search code examples
javascriptreactjsjestjscreate-react-appemotion

Cannot use import statement outside a module @emotion


I tried to test TextField component using Jest

text-field.test.js

import React from "react";
import { render, screen } from "@testing-library/react";
import TextField from '../text-field'
import "@testing-library/jest-dom";

test('TextField', () => {
  render(<TextField name="Name" />)
  screen.debug()
})

text-field.js

import React from "react";
import {
  FormControl,
  InputLabel,
  Input,
  FormHelperText,
} from "@material-ui/core";
import { css } from "@emotion/core";
import PropTypes from "prop-types";

const TextField = ({ name, helperText, error, value, onChange }) => {
  return (
    <FormControl error={error}>
      <InputLabel
        css={css`
          text-transform: capitalize;
        `}
        htmlFor={name}
      >
        {"Name"}
      </InputLabel>
      <Input id={name} value={value} onChange={onChange} />
      <FormHelperText id={`${name}-helper-text`}>{helperText}</FormHelperText>
    </FormControl>
  );
};

TextField.propTypes = {
  name: PropTypes.string.isRequired,
};

export default TextField;

This is my babel config. I included @emotion/babel-preset-css-prop into babel before running Jest.

babel.config.js

// babel.config.js
module.exports = {
  presets: ["@emotion/babel-preset-css-prop", "@babel/preset-env"],
};

I tried to run yarn test, but it fails with the following error.

    import { jsx as ___EmotionJSX } from "@emotion/core";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)

Any ideas?


Solution

  • I think the problem is from the create-react-app script which somehow puts your @emotion/babel-preset-css-prop on the top of presets list which I didn't look deep into that.

    I would suggest you to take full control of your test by just simply create your own script to run your test which is quite simple like: npx jest which you can take full control on your test.

    Here's the few steps doing that:

    Add your script test package.json

    scripts: {
      test: "jest"
    }
    

    Target your test on node babel.config.js:

    module.exports = {
      presets: [
        ["@babel/preset-env", {
          targets: {
            node: 'current',
          },
        }],
        "@emotion/babel-preset-css-prop",
      ]
    };
    

    Add your custom matchers which offers by create-react-app script offered in your file tests import "@testing-library/jest-dom/extend-expect":

    import React from "react";
    import { render, screen } from "@testing-library/react";
    import "@testing-library/jest-dom";
    import "@testing-library/jest-dom/extend-expect" // Add custom matcher
    import Layout from "../layout";
    
    test("Check if layout display title according to prop", async () => {
      const { getByText } = render(<Layout title={"Abc"} />);
      expect(getByText("Abc")).toBeInTheDocument(); // To have kind of matcher
    });
    
    // ...
    

    That's it! Hopefully you would take more control of your tests instead of having no ideas how to custom jest options with other script.