Search code examples
jestjsbabeljsmonorepobabel-jestyarn-workspaces

Support for the experimental syntax 'jsx' isn't currently enabled in monorepo


I currently have 2 packages in my monorepo

web-ui & testing-utils

testing-utils

package.json

{
  "name": "@testing-utils",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "lint": "eslint",
    "postinstall": "cd ../../ && patch-package",
    "test": "jest --passWithNoTests",
    "prettier": "prettier ../../.prettierrc.js -c \"./**/*.{ts,tsx,js,jsx}\"",
    "prettier:write": "prettier ../../.prettierrc.js --write \"./**/*.{ts,tsx,js,jsx}\""
  },
  "dependencies": {
    "react": "16.14.0",
    "react-redux": "7.2.2",
    "redux": "4.0.5"
  },
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.12.10",
    "@babel/plugin-proposal-class-properties": "^7.12.1",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@babel/plugin-syntax-jsx": "^7.18.6",
    "@babel/plugin-transform-react-jsx": "^7.19.0",
    "@babel/plugin-transform-runtime": "^7.12.10",
    "@babel/preset-env": "^7.19.4",
    "@babel/preset-react": "^7.18.6",
    "@babel/preset-typescript": "^7.18.6",
    "@testing-library/react": "12.0.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^26.6.3",
    "babel-loader": "^8.0.5",
    "babel-plugin-react-require": "^3.1.3",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-preset-minify": "^0.6.0-alpha.9",
    "eslint": "7.21.0",
    "eslint-config-airbnb": "18.2.1",
    "eslint-config-airbnb-typescript": "12.3.1",
    "eslint-config-prettier": "8.1.0",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsx-a11y": "6.4.1",
    "eslint-plugin-prettier": "3.4.0",
    "eslint-plugin-react": "7.22.0",
    "eslint-plugin-react-hooks": "4.2.0",
    "prettier": "2.3.0",
    "react-test-renderer": "16.14.0"
  }
}

.babelrc

{
  "presets": [["@babel/preset-env"], "@babel/preset-react"],
  "ignore": ["node_modules/**"],
  "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-syntax-jsx"]
}

renderWithTheme.js

import { render } from '@testing-library/react';
import { THEME } from '@web-ui/src/theme';
import React from 'react';
import { ThemeProvider } from 'styled-components';

const renderWithTheme = (ui) => {
  function Wrapper({ children }) {
    return <ThemeProvider theme={THEME}>{children}</ThemeProvider>;
  }

  return render(ui, { wrapper: Wrapper });
};

export default renderWithTheme;

web-ui

package.json

{
  "name": "@web-ui",
  "version": "0.0.1",
  "license": "MIT",
  "scripts": {
    "lint": "eslint src --ext .js,.jsx,.ts,.tsx",
    "jest": "jest",
    "test": "jest --coverage --runInBand",
    "typecheck": "npx tsc --noemit",
    "prettier": "prettier ../../.prettierrc.js -c \"./src/**/*.{ts,tsx,js,jsx}\"",
    "prettier:write": "prettier ../../.prettierrc.js --write \"./src/**/*.{ts,tsx,js,jsx}\""
  },
  "devDependencies": {
    "@babel/plugin-syntax-jsx": "^7.18.6",
    "@babel/plugin-transform-react-jsx": "^7.19.0",
    "@babel/preset-env": "^7.19.4",
    "@babel/preset-react": "^7.18.6",
    "@testing-library/jest-dom": "^5.11.6",
    "@testing-library/react": "12.0.0",
    "@types/react": "16.14.0",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "es-check": "^5.1.2",
    "eslint": "7.21.0",
    "eslint-config-airbnb": "18.2.1",
    "eslint-config-airbnb-typescript": "12.3.1",
    "eslint-config-prettier": "8.1.0",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsx-a11y": "6.4.1",
    "eslint-plugin-prettier": "3.4.0",
    "eslint-plugin-react": "7.22.0",
    "eslint-plugin-react-hooks": "4.2.0",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^26.0.1",
    "prettier": "2.3.0",
    "react-test-renderer": "^16.13.1",
    "typescript": "4.3.5"
  },
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.32",
    "@fortawesome/free-brands-svg-icons": "^5.15.1",
    "@fortawesome/free-regular-svg-icons": "^5.15.2",
    "@fortawesome/pro-light-svg-icons": "^5.15.2",
    "@fortawesome/pro-regular-svg-icons": "^5.15.1",
    "@fortawesome/pro-solid-svg-icons": "^5.15.1",
    "@fortawesome/react-fontawesome": "^0.1.13",
    "@googlemaps/markerclustererplus": "^1.2.0",
    "@juggle/resize-observer": "^3.3.1",
    "@uiw/react-textarea-code-editor": "^2.0.3",
    "axios": "^0.21.0",
    "date-fns": "^1.9.0",
    "dinero.js": "^1.6.0",
    "formik": "^2.1.4",
    "google-libphonenumber": "^3.2.15",
    "libphonenumber": "0.0.10",
    "lodash": "^4.17.20",
    "moment": "^2.29.1",
    "rc-slider": "^8.6.7",
    "react-dates": "^21.8.0",
    "react-number-format": "^4.4.1",
    "react-router-dom": "^5.2.0",
    "react-select": "^3.0.8",
    "react-spinkit": "^3.0.0",
    "react-spinners": "^0.10.6",
    "react-spring": "^8.0.27",
    "react-table": "^7.6.3",
    "react-tag-autocomplete": "^6.1.0",
    "react-transition-group": "^4.4.1",
    "styled-components": "^4.4.1",
    "use-resize-observer": "^7.0.0",
    "yup": "^0.29.3"
  },
  "resolutions": {
    "@types/react": "16.14.0"
  }
}

.babelrc

{
  "presets": [["@babel/preset-env"], "@babel/preset-react"],
  "ignore": ["node_modules/**"],
  "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-syntax-jsx"]
}

tests/form/form.test.js

import renderWithTheme from '@testing-utils/renderWithTheme';
import React, { useRef, useEffect } from 'react';
import { waitFor } from '@testing-library/react';
import Form from '../../src/form/Form/Form';

const FormDummy = (props) => {
  const formRef = useRef();
  const initialValues = {
    terms: '',
  };

  useEffect(() => {
    if (formRef && formRef.current) formRef.current.submitForm();
  }, [formRef]);

  return (
    <div>
      <Form onSubmit={props.onSub} formRef={formRef} initialValues={initialValues} />
    </div>
  );
};

describe('form', () => {
  test('it should render without error', () => {
    const initialValues = {
      terms: '',
    };

    const { container } = renderWithTheme(<Form initialValues={initialValues} />);

    expect(container).toBeDefined();
  });

  test('it should render without error when custom handle submit', async () => {
    const onSub = jest.fn();

    renderWithTheme(<FormDummy onSub={onSub} />);

    await waitFor(() => expect(onSub).toBeCalled());
  });
});

On the root of the monorepo I also have the following;

babel.config.js

module.exports = {
  "presets": [["@babel/preset-env"], "@babel/preset-react"],
  "ignore": ["node_modules/**"],
  "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-syntax-jsx"]
}

package.json

{
  "private": true,
  "name": "monorepo",
  "version": "0.1.0",
  "license": "MIT",
  "scripts": {
    "re-install": "rm -rf node_modules packages/node_modules packages/web-ui/node_modules packages/testing-utils/node_modules && yarn",
    "lint": "yarn workspaces run lint",
    "test": "yarn workspaces run test",
    "typecheck": "yarn workspaces run tsc --noemit",
    "prettier": "yarn workspaces run prettier",
    "prettier:write": "yarn workspaces run prettier:write",
    "postinstall": "patch-package",
    "prepare": "husky install",
  },
  "devDependencies": {
    "husky": "^6.0.0",
    "minimist": "^1.2.5",
    "patch-package": "^6.4.4",
    "plist": "^3.0.1",
    "postinstall-postinstall": "^2.1.0"
  },
  "workspaces": {
    "packages": [
      "packages/*"
    ]
  },
  "dependencies": {},
  "resolutions": {
    "@types/react": "16.14.0"
  }
}

when trying to run npx jest form I get the following error;

FAIL  __tests__/form/form.test.js
  ● Test suite failed to run

    SyntaxError: ~~~/packages/testing-utils/renderWithTheme.js: Support for the experimental syntax 'jsx' isn't currently enabled (8:12):

       6 | const renderWithTheme = (ui) => {
       7 |   function Wrapper({ children }) {
    >  8 |     return <ThemeProvider theme={THEME}>{children}</ThemeProvider>;
         |            ^
       9 |   }
      10 |
      11 |   return render(ui, { wrapper: Wrapper });

    Add @babel/preset-react (https://github.com/babel/babel/tree/main/packages/babel-preset-react) to the 'presets' section of your Babel config to enable transformation.
    If you want to leave it as-is, add @babel/plugin-syntax-jsx (https://github.com/babel/babel/tree/main/packages/babel-plugin-syntax-jsx) to the 'plugins' section to enable parsing.

As you can see from my files above, I have done the suggestion of adding @babel/preset-react to the presets section and added @babel/plugin-syntax-jsx to the plugins section to all my babel configs.

Where am I going wrong here?

Any help would be greatly appreciated.


Solution

  • What ended up actually working for me in the end was changing all the .babelrc files to be babel.config.js instead.

    Not fully sure why that worked, but it did.