【问题标题】:My tests isn't working with react-testing-library with typescript我的测试不适用于带有 typescript 的 react-testing-library
【发布时间】:2020-07-03 09:35:16
【问题描述】:

我在 TypeScript 上的 React 项目遇到了 react-testing-library 问题。

我一直在许多网站上搜索答案,查看教程,但我真的卡住了,找不到答案,更改了 babel.config.js、tsconfig.json 和 jest.config.js 上的一些配置,安装新软件包(例如,不确定我是否必须为 testing-library 安装 @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()
  })
})

总而言之,网站正在运行,构建也在运行,但测试没有:/ 提前感谢您帮助我!

【问题讨论】:

    标签: reactjs typescript jestjs babeljs react-testing-library


    【解决方案1】:

    我在开玩笑的配置中忘记了module.exports 中的“s”。 我已经在我的笑话配置中添加了这个:

      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

    【讨论】:

      【解决方案2】:

      最好如下使用:

      interface IProps {
        children: React.ReactNode | React.ReactNode[];
        tag: 'h1' | 'h2';
      }
      

      因为:

      type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
      

      统一更新: 或者,也许您必须在渲染选项中将子元素作为第一个参数和包装组件传递,如下所示:

      const { getByText } = render(<>Mon titre</>, {
        wrapper: SectionTitle as React.FunctionComponent,
      });
      

      【讨论】:

      • 感谢您的提示!但它不能解决我的错误:/
      • 不得不尝试,因为乍一看这是children属性的类型问题。您是否尝试过 render 而不通过 children (在您的情况下为简单文本)?
      • 我什至尝试过添加&lt;div /&gt;,但它没有用,我试过你的更新,但它也没有用:(
      • 那么为了解决这个问题,我们需要查看您的问题的代码框示例,请制作并在此处发布,以便我们尽快检查并帮助您。
      • 我已经创建了一个沙箱,但是如何使用控制台启动 yarn start 呢? codesandbox.io/s/vigilant-haslett-hl3p2?file=/src/…
      猜你喜欢
      • 2021-02-23
      • 2019-05-21
      • 2019-11-11
      • 1970-01-01
      • 2021-05-27
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多