reactjs - 我的测试无法与带有 typescript 的 react 测试库一起使用

标签 reactjs typescript jestjs babeljs react-testing-library

我在 TypeScript 上的 React 项目遇到了一个有关 React-testing-library 的问题。

我一直在很多网站上搜索答案,检查教程,但我真的陷入困境,找不到答案,更改了 babel.config.js、tsconfig.json 和 jest.config.js 上的一些配置,安装新的软件包(例如,不确定我是否必须为测试库安装@types),但我对所有这些都不是专家,我迷失了。

我尝试过一个简单的测试,结果显示:

Unexpected token, expected "," (11:47)

       9 | describe('Test SectionTitle', () => {
      10 |   test('renders message', () => {
    > 11 |     const { getByText } = render(<SectionTitle tag="h1">Mon titre</SectionTitle>)
         |                                                ^
      12 | 
      13 |     expect(getByText('Mon titre')).toBeInTheDocument()
      14 |   })

我的项目结构如下:

    .
    ├── public                      # Where build files are (shoudn't be this way)
    ├── src                         # Source files (alternatively `lib` or `app`)
    │   ├── assets                  # All images
    │   ├── components              # All the components
    │   │   ├── component.spec.ts   # Test files 
    │   │   ├── component.styled.ts # Style of the component with styled-components 
    │   │   ├── component.tsx       # Component file
    │   │   └── index.ts            # Choose what to export
    │   ├── routes                  # All routes with react-router-dom
    │   ├── screens                 # All screens
    │   │   ├── screen.spec.ts      # Test files 
    │   │   ├── screen.styled.ts    # Style of the screen with styled-components 
    │   │   ├── screen.meta.tsx     # Meta tag of the screen with react-helmet 
    │   │   ├── screen.tsx          # Screen file
    │   │   └── index.ts            # Choose what to export
    │   ├── sitemap                 # Sitemap generator (issue about missing some parameters, changefreq, priority, lastmod etc.)[https://github.com/kuflash/react-router-sitemap/issues/39]
    │   ├── style                   # Helpers, utils, variables CSS, global style etc
    │   ├── index.tsx               # Index file
    │   ├── setupTests.ts           # Packages to be imported for tests
    └── README.md
    └── webpack.config.js           # Config of webpack
    └── babel.config.js             # Config of babel
    └── jest.config.js              # Config of jest
    └── tsconfig.json               # Config for TypeScript like imported paths with '@'
    └── custom.d.ts                 # Adding Custom Type Definitions
    └── .prettierrc                 # Rules for prettier
    └── .prettierignore             # Files to be ignored for prettier
    └── .gitignore                  # Files to be ignored for git
    └── package.json                # List of packages and commands to run with yarn
    └── yarn.lock                   # Packages in the node_modules folder

这是我的 package.json 依赖项和脚本:

{
  "dependencies": {
    "framer-motion": "^1.11.0",
    "react": "^16.13.1",
    "react-cookie-consent": "^5.0.1",
    "react-dom": "^16.13.1",
    "react-ga": "^3.0.0",
    "react-helmet": "^6.0.0",
    "react-router-dom": "^5.1.2",
    "styled-components": "^5.1.0"
  },
  "scripts": {
    "prebuild": "yarn run sitemap",
    "build": "webpack --mode production",
    "start": "webpack-dev-server --mode development",
    "sitemap": "babel-node src/sitemap/sitemap-builder.js",
    "test": "jest -c jest.config.js --watch"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "./src/**/*.{ts,tsx}": [
      "prettier --write ."
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@babel/cli": "^7.8.4",
    "@babel/core": "^7.9.6",
    "@babel/node": "^7.10.1",
    "@babel/plugin-transform-typescript": "^7.10.1",
    "@babel/preset-env": "^7.9.6",
    "@babel/preset-react": "^7.10.1",
    "@testing-library/jest-dom": "^5.11.0",
    "@testing-library/react": "^10.4.3",
    "@types/jest": "^26.0.3",
    "@types/node": "^14.0.14",
    "@types/react": "^16.9.0",
    "@types/react-dom": "^16.9.0",
    "@types/react-helmet": "^6.0.0",
    "@types/react-router-dom": "^5.1.5",
    "@types/styled-components": "^5.1.0",
    "@types/testing-library__jest-dom": "^5.9.1",
    "@types/testing-library__react": "^10.2.0",
    "babel-loader": "^8.1.0",
    "css-loader": "^3.5.3",
    "file-loader": "^6.0.0",
    "husky": "^4.2.5",
    "jest": "^26.1.0",
    "lint-staged": "^10.2.2",
    "prettier": "^2.0.5",
    "react-router-sitemap": "^1.2.0",
    "source-map-loader": "^0.2.4",
    "style-loader": "^1.2.1",
    "ts-jest": "^26.1.1",
    "ts-loader": "^7.0.3",
    "tsconfig-paths-webpack-plugin": "^3.2.0",
    "typescript": "~3.7.2",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.11.0"
  }
}

这是我的 jest.config.js :

module.export = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  transform: {
    "^.+\\.tsx?$": "ts-jest"
  },
  roots: ['<rootDir>/src'],
  testMatch: ['<rootDir>/src/**/>(*.)spec.{ts, tsx}'], // finds test
  moduleFileExtensions: ['ts', 'tsx', 'json', 'node'],
  testPathIgnorePatterns: ['/node_modules/', '/public/'],
  setupFilesAfterEnv: '<rootDir>/src/setupTests.ts'
};

这是我的 setupTests.ts :

import '@testing-library/jest-dom/extend-expect'
import '@testing-library/react/cleanup-after-each'

这是我的 tsconfig.json :

{
  "compilerOptions": {
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "target": "es5",
    "module": "commonjs",
    "rootDir": "src",
    "outDir": "public",
    "jsx": "react",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "baseUrl": "src",
    "paths": {
      "@assets/*": [
        "assets/*"
      ],
      "@components/*": [
        "components/*"
      ],
      "@routes/*": [
        "routes/*"
      ],
      "@screens/*": [
        "screens/*"
      ],
      "@style/*": [
        "style/*"
      ]
    }
  },
  "include": [
    "src",
    "custom.d.ts"
  ]
}

这是我的 babel.config.js :

module.exports = {
  presets: ["@babel/preset-env", "@babel/preset-react"],
  plugins: ["@babel/plugin-transform-typescript"]
};

这是我的 webpack.config.js :

const path = require("path");
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = {
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
    plugins: [new TsconfigPathsPlugin({ configFile: "./tsconfig.json" })]
  },
  devServer: {
    contentBase: path.join(__dirname, "public"),
    compress: true,
    port: 3000,
    historyApiFallback: true,
    publicPath: '/'
  },
  entry: path.resolve(__dirname, "src", "index.tsx"),
  output: {
    path: path.resolve(__dirname, "public"),
    filename: "bundle.js",
    publicPath: '/'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: ["babel-loader"]
      },
      {
        test: /\.ts(x?)$/,
        exclude: /node_modules/,
        use: [{ loader: "ts-loader" }]
      },
      {
        test: /\.css$/,
        use: [{ loader: "style-loader" }, { loader: "css-loader" }]
      },
      {
        test: /\.(png|svg|jpg|gif)$/i,
        use: ["file-loader"]
      },
      {
        enforce: "pre",
        test: /\.js$/,
        loader: "source-map-loader"
      }
    ]
  }
};

组件SectionTitle.tsx:

import React from 'react'
import SectionTitleWrapper from './SectionTitle.styled'

interface IProps {
  children: JSX.Element[] | JSX.Element | string
  tag: 'h1' | 'h2'
}

const SectionTitle = (props: IProps) => <SectionTitleWrapper as={props.tag}>{props.children}</SectionTitleWrapper>

export default SectionTitle

以及测试SectionTitle.spec.tsx:

import React from 'react'
import { render, cleanup } from '@testing-library/react'
import SectionTitle from './SectionTitle'

afterEach(cleanup)

describe('Test SectionTitle', () => {
  test('renders message', () => {
    const { getByText } = render(<SectionTitle tag="h1">Mon titre</SectionTitle>)

    expect(getByText('Mon titre')).toBeInTheDocument()
  })
})

总而言之,网站正在运行,构建也正在运行,但测试不起作用:/ 预先感谢您对我的帮助!

最佳答案

我忘记了我的 Jest 配置中 module.exports 中的“s”。 我已将其添加到我的 Jest 配置中:

  moduleNameMapper: {
    '^@assets/(.*)$': '<rootDir>/src/assets/$1',
    '^@components/(.*)$': '<rootDir>/src/components/$1',
    '^@routes/(.*)$': '<rootDir>/src/routes/$1',
    '^@screens/(.*)$': '<rootDir>/src/screens/$1',
    '^@style/(.*)$': '<rootDir>/src/style/$1'
  }

我已将 TypeScript 升级到此版本:~3.8.0

关于reactjs - 我的测试无法与带有 typescript 的 react 测试库一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62712613/

相关文章:

typescript - 使用 Pulumi : Missing credentials in config 部署 Localstack

javascript - Firestore 文档 typescript doc.data() 未定义?

javascript - 如何正确测试 React Dropzone onDrop 方法

javascript - 跳过测试文件 Jest 中的一项测试

javascript - 无法在 React 服务器端渲染中处理 UnhandledPromiseRejectionWarning

javascript - React js Firebase 身份验证无法正常工作

node.js - npm 错误!名称无效 : "@types/handlebars"

node.js - 测试时如何修复这个 "Cannot read property of undefined"?

javascript - 如何将从 API 接收到的 HTML 类注入(inject)到 React 中?

javascript - React 中具有固定记录数的多行