10

in our project we use react-intl for internationalisation. We are using jest as the testing framework and we decided to move our unit test utility library from enzyme to react-testing-library. But now, since there is no shallow rendering, I have to provide <IntlProvider ... /> in the test myself, no problem. But even if I do that, when testing terminal says Invalid hook call. Hooks can only be called inside of the body of a function component but when I run the project locally, no errors just runs normally as expected. P.S in the tests, Apollo provider works normally.

FirstNameFor.test.tsx

import { IntlProvider } from 'react-intl';
import { createMockClient } from 'mock-apollo-client';
import { ApolloProvider as ApolloProviderHooks } from '@apollo/react-hooks';
import { ApolloProvider } from 'react-apollo';

const wrapper = (mockProps, mockClient) => {
  return (
    <ApolloProvider client={mockClient}>
      <ApolloProviderHooks client={mockClient}>
        <IntlProvider locale="en">
          <FirstNameForm
            handleNext={mockProps.handleNext}
            onboardingState={mockProps.onboardingState}
            setHelpContent={mockProps.setHelpContent}
            updateOnboardingState={mockProps.updateOnboardingState}
          />
        </IntlProvider>
      </ApolloProviderHooks>
    </ApolloProvider>
  );
};

describe('FirstNameForm Container', () => {
  afterEach(() => {
    jest.clearAllMocks();
    cleanup();
  });

  it('should match snapshot', () => {
    // Arrange
    const mockProps = {
      handleNext: jest.fn(),
      onboardingState: {},
      setHelpContent: jest.fn(),
      updateOnboardingState: jest.fn(),
    };
    const mockClient = createMockClient();

    // Act
    const component = render(wrapper(mockProps, mockClient));

    // Assert
    expect(component).toMatchSnapshot();
  });
});

FirstNameForm.tsx

export const FirstNameForm: React.FC<StepContentProps> = props => {
  const [showMessageMutation] = useShowMessageMutation();
  const intl = useIntl();

  const formik = useFormik<FirstNameFormValues>({
   ...,
  });

  return <FirstNameFormComponent formik={formik} intl={intl} />;
};

Terminal Screenshot enter image description here

package.json

{
  "private": true,
  "proxy": "http://localhost:5000",
  "version": "0.1.57",
  "scripts": {
    "dev": "yarn graphql:generate && SKIP_PREFLIGHT_CHECK=true react-app-rewired start",
    "build": "SKIP_PREFLIGHT_CHECK=true react-app-rewired build",
    "testonly": "SKIP_PREFLIGHT_CHECK=true react-app-rewired test --env=jsdom",
    "coverage": "SKIP_PREFLIGHT_CHECK=true react-app-rewired test --env=jsdom --coverage",
  },
  "jest": {
    "coveragePathIgnorePatterns": [
      "/node_modules/",
      "src/types/",
      "src/config/analytics/mp.d.ts",
      "src/config/analytics/ua.d.ts"
    ],
    "snapshotSerializers": [
      "enzyme-to-json/serializer"
    ]
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
  "resolutions": {
    "@types/react": "16.8.17"
  },
  "dependencies": {
    "@apollo/react-hooks": "3.1.3",
    "animated-scroll-to": "1.2.2",
    "apollo-cache": "1.3.2",
    "apollo-cache-inmemory": "1.6.3",
    "apollo-client": "2.6.3",
    "apollo-link": "1.2.12",
    "apollo-link-context": "1.0.18",
    "apollo-link-error": "1.1.11",
    "apollo-link-http": "1.5.15",
    "apollo-link-ws": "1.0.18",
    "apollo-utilities": "1.3.2",
    "big.js": "5.2.2",
    "copy-to-clipboard": "3.2.0",
    "core-js": "3.0.1",
    "date-fns": "1.30.1",
    "downloadjs": "1.4.7",
    "formik": "2.1.1",
    "graphql": "14.3.0",
    "graphql-subscriptions": "1.1.0",
    "graphql-tag": "2.10.1",
    "graphql-tools": "4.0.4",
    "history": "4.9.0",
    "intl": "1.2.5",
    "js-cookie": "2.2.0",
    "lodash": "4.17.11",
    "owasp-password-strength-test": "1.3.0",
    "qrcode.react": "0.9.3",
    "query-string": "6.5.0",
    "react": "16.8.6",
    "react-apollo": "3.1.3",
    "react-dom": "16.8.6",
    "react-google-recaptcha": "1.1.0",
    "react-intl": "3.1.8",
    "react-router-dom": "5.1.0",
    "recompose": "0.30.0",
    "regenerator-runtime": "0.13.2",
    "subscriptions-transport-ws": "0.9.16",
    "validator": "10.11.0",
    "victory": "34.0.0",
    "yup": "0.27.0"
  },
  "devDependencies": {
    "@apollo/react-testing": "3.1.3",
    "@babel/cli": "7.4.4",
    "@babel/core": "7.4.4",
    "@babel/preset-env": "7.4.4",
    "@graphql-codegen/add": "1.8.1",
    "@graphql-codegen/cli": "1.8.1",
    "@graphql-codegen/fragment-matcher": "1.8.1",
    "@graphql-codegen/typescript": "1.8.1",
    "@graphql-codegen/typescript-operations": "1.8.1",
    "@graphql-codegen/typescript-react-apollo": "1.8.1",
    "@testing-library/react": "10.0.4",
    "@testing-library/jest-dom": "5.8.0",
    "@types/testing-library__react": "10.0.1",
    "@types/big.js": "4.0.5",
    "@types/downloadjs": "1.4.1",
    "@types/enzyme": "3.10.5",
    "@types/graphql": "14.2.0",
    "@types/js-cookie": "2.2.2",
    "@types/node": "12.0.0",
    "@types/owasp-password-strength-test": "1.3.0",
    "@types/prop-types": "15.7.1",
    "@types/qrcode.react": "0.8.2",
    "@types/query-string": "6.3.0",
    "@types/react": "16.8.17",
    "@types/react-dom": "16.8.4",
    "@types/react-google-recaptcha": "1.0.0",
    "@types/react-router-dom": "5.1.0",
    "@types/react-test-renderer": "16.9.0",
    "@types/recompose": "0.30.6",
    "@types/validator": "10.11.0",
    "@types/victory": "33.1.0",
    "@types/ws": "6.0.1",
    "@types/yup": "0.26.13",
    "babel-loader": "8.0.6",
    "enzyme": "3.11.0",
    "enzyme-adapter-react-16": "1.15.2",
    "enzyme-to-json": "3.4.4",
    "jest-canvas-mock": "2.2.0",
    "jest-localstorage-mock": "2.4.0",
    "merge-graphql-schemas": "1.5.8",
    "npm-run-all": "4.1.5",
    "patch-package": "6.1.2",
    "postinstall-postinstall": "2.0.0",
    "react-app-rewired": "2.1.3",
    "react-scripts": "3.3.0",
    "react-test-renderer": "16.8.6",
    "source-map-explorer": "1.8.0",
    "ts-jest": "25.3.1",
    "ts-node": "8.1.0",
    "typescript": "3.5.3"
  }
}
Ari Seyhun
  • 11,506
  • 16
  • 62
  • 109
onuriltan
  • 3,730
  • 4
  • 25
  • 37

1 Answers1

2

The error comes from React itself, and most likely has nothing to do with react-intl.

There's a good chance you have multiple instances of React in conflict, for some reason only occurring in the test environment. I suspect it might have to do with react-app-rewired, not sure though.

The steps from the official help doc should help reveal whether duplicate Reacts is the source of the problem.

If that is the reason, here's some of the top solutions from the community:

  • Modify your webpack config to resolve the react alias (discussion)
  resolve: {
    alias: {
        react: path.resolve('./node_modules/react'),
      }
  },
  • Modify your webpack config to set react as an external (PR example)
  externals: {
    react: 'react'
  }
mrc114
  • 21
  • 3