testing-library / react-testing-library

🐐 Simple and complete React DOM testing utilities that encourage good testing practices.
https://testing-library.com/react
MIT License
18.96k stars 1.11k forks source link

[NextJS] ReferenceError: expect is not defined [on building] #919

Closed AhmedBHameed closed 3 years ago

AhmedBHameed commented 3 years ago

Describssion:

I have a project here works perfectly in development mode but when I'm trying to build, I'm getting the following error:

yarn run v1.22.5
$ NODE_ENV=production next build
info  - Using webpack 4. Reason: custom webpack configuration in next.config.js https://nextjs.org/docs/messages/webpack5
info  - Checking validity of types  
info  - Using external babel configuration from /home/ahmed/Desktop/WWW/next_ahmedhameed/.babelrc

warn - Tailwind is not purging unused styles because no template paths have been provided.
warn - If you have manually configured PurgeCSS outside of Tailwind or are deliberately not removing unused styles, set `purge: false` in your Tailwind config file to silence this warning.
warn - https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css
info  - Creating an optimized production build  
info  - Compiled successfully

> Build error occurred
ReferenceError: expect is not defined
    at Object.<anonymous> (/home/ahmed/Desktop/WWW/next_ahmedhameed/node_modules/@testing-library/jest-dom/dist/extend-expect.js:7:1)
    at Module._compile (internal/modules/cjs/loader.js:1133:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
    at Module.load (internal/modules/cjs/loader.js:977:32)
    at Function.Module._load (internal/modules/cjs/loader.js:877:14)
    at Module.require (internal/modules/cjs/loader.js:1019:19)
    at require (internal/modules/cjs/helpers.js:77:18)
    at Object.<anonymous> (/home/ahmed/Desktop/WWW/next_ahmedhameed/node_modules/@testing-library/jest-dom/extend-expect.js:2:1)
    at Module._compile (internal/modules/cjs/loader.js:1133:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10) {
  type: 'ReferenceError'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I'm not sure if this error from my configuration of the unit test! but since it was pointing to react-testing-library, I wanted to post the issue here and check for some suggestions.

Background:

I used next.js v9 before and now I wanted to add few features so i ended up with updating next library to v10 with adding unit test configuration.

package.json

{
  "name": "next-kakiee",
  "version": "2.0.0",
  "private": true,
  "scripts": {
    "clean": "rm -fr -R .next",
    "dev": "next",
    "test:debug": "jest --verbose --watchAll",
    "test": "jest --verbose --silent",
    "test:coverage": "jest --coverage  --silent --watchAll",
    "build": "NODE_ENV=production next build",
    "start": "next start",
    "lint:css": "stylelint \"**/*.{ts,tsx}\"",
    "lint": "eslint . --ext ts,tsx",
    "lint:fix": "eslint . --ext ts,tsx --fix",
    "prettify": "prettier --write .",
    "gql:types": "graphql-codegen --config codegen.yml && prettier --write graphql/queries.ts"
  },
  "dependencies": {
    "@apollo/client": "^3.3.19",
    "@emotion/react": "^11.4.0",
    "@emotion/styled": "^11.3.0",
    "@heroicons/react": "^1.0.1",
    "@hookform/resolvers": "^2.5.1",
    "@tailwindcss/forms": "^0.3.2",
    "@tailwindcss/typography": "^0.4.0",
    "@testing-library/jest-dom": "^5.12.0",
    "@testing-library/react": "^11.2.7",
    "@testing-library/react-hooks": "^6.0.0",
    "@testing-library/user-event": "^13.1.9",
    "autoprefixer": "^10.2.5",
    "axios": "^0.21.1",
    "date-fns": "^2.21.3",
    "downshift": "^6.1.3",
    "express": "^4.17.1",
    "graphql": "^15.5.0",
    "gsap": "^3.6.1",
    "joi": "^17.4.0",
    "markdown-to-jsx": "^7.1.3",
    "next": "10.2.2",
    "postcss": "^8.3.0",
    "prism-react-renderer": "^1.2.1",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-dropzone": "^11.3.2",
    "react-hook-form": "^7.6.5",
    "react-map-gl": "^6.1.15",
    "react-markdown": "^6.0.2",
    "react-mde": "^11.5.0",
    "react-syntax-highlighter": "^15.4.3",
    "react-toastify": "^7.0.4",
    "reactjs-popup": "^2.0.4",
    "showdown": "^1.9.1",
    "tailwindcss": "^2.1.2",
    "ulid": "^2.3.0"
  },
  "devDependencies": {
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@graphql-codegen/cli": "1.21.4",
    "@graphql-codegen/introspection": "1.18.2",
    "@graphql-codegen/typescript": "1.22.0",
    "@graphql-codegen/typescript-operations": "1.17.16",
    "@graphql-codegen/typescript-react-apollo": "2.2.4",
    "@svgr/webpack": "^5.5.0",
    "@testing-library/dom": "^7.31.0",
    "@types/faker": "^5.5.5",
    "@types/jest": "^26.0.23",
    "@types/jest-axe": "^3.5.1",
    "@types/node": "^15.6.0",
    "@types/react": "^17.0.6",
    "@types/react-syntax-highlighter": "^13.5.0",
    "@types/showdown": "^1.9.3",
    "@typescript-eslint/eslint-plugin": "^4.24.0",
    "@typescript-eslint/parser": "^4.24.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^26.6.3",
    "babel-plugin-import": "^1.13.3",
    "babel-plugin-inline-react-svg": "^2.0.1",
    "babel-plugin-lodash": "^3.3.4",
    "babel-plugin-styled-components": "^1.12.0",
    "cross-fetch": "^3.1.4",
    "eslint": "^7.27.0",
    "eslint-config-airbnb": "^18.2.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-import-resolver-typescript": "^2.4.0",
    "eslint-plugin-import": "^2.23.3",
    "eslint-plugin-import-helpers": "^1.1.0",
    "eslint-plugin-jsx-a11y": "^6.4.1",
    "eslint-plugin-prettier": "^3.4.0",
    "eslint-plugin-react": "^7.23.2",
    "eslint-plugin-react-hooks": "^4.2.0",
    "faker": "^5.5.3",
    "husky": "^6.0.0",
    "i18n": "^0.13.3",
    "jest": "^26.6.3",
    "jest-axe": "^4.1.0",
    "lint-staged": "^11.0.0",
    "msw": "^0.29.0",
    "next-i18next": "^8.3.0",
    "prettier": "^2.3.0",
    "react-test-renderer": "^17.0.2",
    "stylelint": "^13.13.1",
    "stylelint-config-prettier": "^8.0.2",
    "stylelint-config-recess-order": "^2.4.0",
    "stylelint-config-recommended": "^5.0.0",
    "stylelint-config-styled-components": "^0.1.1",
    "stylelint-processor-styled-components": "^1.10.0",
    "svgo": "^2.3.0",
    "ts-jest": "^26.5.6",
    "typescript": "^4.2.4"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "airbnb"
    ]
  },
  "jest": {
    "setupTestFrameworkScriptFile": "<rootDir>/setupTests.js"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.{js,ts,tsx}": [
      "eslint --fix",
      "stylelint \"**/*.{ts,tsx}\""
    ]
  }
}

jest.config.js

module.exports = {
  roots: ['<rootDir>/'],
  // transform: {
  //   '^.+\\.tsx?$': 'ts-jest',
  // },
  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  transformIgnorePatterns: ['/node_modules/(?!(jest-styled-components)/).*/'],
  testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
  setupFilesAfterEnv: ['<rootDir>/setupTests.ts'],
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': '<rootDir>/node_modules/babel-jest',
  },
};

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    "@babel/syntax-dynamic-import",
    [
      "lodash",
      {
        "id": ["lodash"]
      }
    ]
  ],
  "ignore": ["node_modules", ".next"]
}

next.config.js

module.exports = {
  publicRuntimeConfig: {
    mapboxApiAccessToken:
      'pk.eyJ1IjoiYWhtZWRiaGFtZWVkIiwiYSI6ImNrNmNpd3M3ZzExZXMza21neGoxNHJoeDcifQ.07EbC691qPVJ86uLhJyfWA',
    domain: `${
      process.env.NODE_ENV === 'production'
        ? 'https://www.ahmedhameed.dev'
        : 'http://localhost:5000'
    }`,
    graphqlApi: '/nodeys/v1/graphql',
    uploadApi: '/nodeys/api/upload',
    localeSubpaths:
      typeof process.env.LOCALE_SUBPATHS === 'string'
        ? process.env.LOCALE_SUBPATHS
        : 'none',
  },
  i18n: {
    locales: ['en', 'ar'],
    defaultLocale: 'en',
    localeDetection: false,
  },
  images: {
    domains: ['assets.vercel.com'],
  },
  webpackDevMiddleware: (config) => {
    config.watchOptions = {
      poll: 1000,
      aggregateTimeout: 300,
    };

    return config;
  },
  webpack: (config, {webpack}) => {
    config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//));

    config.node = {
      fs: 'empty',
    };
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });

    return config;
  },
};
AhmedBHameed commented 3 years ago

I guess I found a workaround solution.

I moved setupTests.ts to test folder and use next.config.js to ignore test folder completely.

That will prevent cheking test folder while building the app which make sense as long it is related to testing only

module.exports = {
  publicRuntimeConfig: {
    mapboxApiAccessToken:
      'pk.eyJ1IjoiYWhtZWRiaGFtZWVkIiwiYSI6ImNrNmNpd3M3ZzExZXMza21neGoxNHJoeDcifQ.07EbC691qPVJ86uLhJyfWA',
    domain: `${
      process.env.NODE_ENV === 'production'
        ? 'https://www.ahmedhameed.dev'
        : 'http://localhost:5000'
    }`,
    graphqlApi: '/nodeys/v1/graphql',
    uploadApi: '/nodeys/api/upload',
    localeSubpaths:
      typeof process.env.LOCALE_SUBPATHS === 'string'
        ? process.env.LOCALE_SUBPATHS
        : 'none',
  },
  i18n: {
    locales: ['en', 'ar'],
    defaultLocale: 'en',
    localeDetection: false,
  },
  images: {
    domains: ['assets.vercel.com'],
  },
  webpackDevMiddleware: (config) => {
    config.watchOptions = {
      poll: 1000,
      aggregateTimeout: 300,
    };

    return config;
  },
  webpack: (config, {webpack}) => {
    config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//));
    config.plugins.push(new webpack.IgnorePlugin(/\/test\//));    // <<<<<====== This line solved my issue

    config.node = {
      fs: 'empty',
    };
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });

    return config;
  },
};

Closing my issue.