React-Testing-Library:使用打字稿无法将组件传递给渲染函数

React-Testing-Library: using typescript can't pass component to render function

我正在从头开始引导我的第一个 TypeScript + React 项目。我在 TypeScript 和组件渲染方面取得了成功。但是,当我尝试添加测试时,它只是失败并出现一些类型错误。

我试过不同的配置,甚至添加了一个 setupTests.ts 文件。

这是我的配置: package.json

{
  ....
      "dependencies": {
        "@babel/plugin-proposal-object-rest-spread": "^7.4.0",
        "@babel/plugin-syntax-dynamic-import": "^7.2.0",
        "@babel/polyfill": "^7.4.0",
        "@babel/preset-env": "^7.4.2",
        "@babel/preset-react": "^7.0.0",
        "@babel/preset-typescript": "^7.3.3",
        "@types/html-webpack-plugin": "^3.2.0",
        "@types/jest": "^24.0.11",
        "@types/react": "^16.8.10",
        "@types/react-dom": "^16.8.3",
        "@types/react-redux": "^7.0.6",
        "@types/react-router-dom": "^4.3.1",
        "@types/redux": "^3.6.0",
        "@types/redux-logger": "^3.0.7",
        "@types/redux-promise": "^0.5.28",
        "@types/webpack": "^4.4.26",
        "@typescript-eslint/eslint-plugin": "^1.5.0",
        "@typescript-eslint/parser": "^1.5.0",
        "babel-jest": "^24.5.0",
        "babel-loader": "^8.0.5",
        "babel-plugin-transform-class-properties": "^6.24.1",
        "babel-preset-es2015": "^6.24.1",
        "babel-preset-react": "^6.24.1",
        "eslint": "^5.16.0",
        "eslint-config-prettier": "^4.1.0",
        "eslint-plugin-prettier": "^3.0.1",
        "eslint-plugin-react-hooks": "^1.6.0",
        "html-webpack-plugin": "^3.2.0",
        "jest": "^24.5.0",
        "jest-dom": "^3.1.3",
        "prettier": "^1.16.4",
        "react": "^16.8.6",
        "react-dom": "^16.8.6",
        "react-redux": "^6.0.1",
        "react-router": "^5.0.0",
        "react-router-dom": "^5.0.0",
        "react-testing-library": "^6.0.3",
        "redux": "^4.0.1",
        "redux-logger": "^3.0.6",
        "redux-promise": "^0.6.0",
        "redux-thunk": "^2.3.0",
        "styled-components": "^4.2.0",
        "ts-loader": "^5.3.3",
        "ts-node": "^8.0.3",
        "webpack": "^4.29.6",
        "webpack-dev-middleware": "^3.6.1",
        "webpack-dev-server": "^3.2.1",
        "webpack-hot-middleware": "^2.24.3"
    },
    "devDependencies": {
        "@babel/core": "^7.4.0",
        "awesome-typescript-loader": "^5.2.1",
        "jest-environment-jsdom": "^24.5.0",
        "source-map-loader": "^0.2.4",
        "ts-jest": "^24.0.1",
        "typescript": "^3.4.1",
        "webpack-cli": "^3.3.0"
    }

.babelrc

{
    "presets": [
        "@babel/react",
        "@babel/typescript",
        [
            "@babel/preset-env",
            {
                "targets": {
                    "browsers": [">0.25%"]
                },
                "modules": false,
                "useBuiltIns": "usage"
            }
        ]
    ],
    "plugins": ["@babel/proposal-class-properties", "@babel/proposal-object-rest-spread"]
}

jest.config.js

module.exports = {
    roots: ['<rootDir>/src'],
    transform: {
      '.*.tsx?$': 'ts-jest',
    },
    testMatch: ['<rootDir>/src/**/?(*.)test.{ts,tsx}'],
    moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
    setupFilesAfterEnv: [
        'react-testing-library/cleanup-after-each', 'jest-dom/extend-expect']
  };

webpack.config.js:

const path = require('path');

// Plugins
const path = require('path')

// Plugins
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: {
        dev: './src/index.tsx',
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/[name].bundle.js',
    },
    devServer: {
        compress: true,
        port: 3000,
        hot: true,
    },
    devtool: 'source-map',
    resolve: {
        extensions: ['.ts', '.tsx', '.js', '.jsx'],
    },
    module: {
        rules: [
            /**
             * Gets all .ts, .tsx, or .js files and runs them through eslint
             * and then transpiles them via babel.
             */
            {
                test: /(\.js$|\.tsx?$)/,
                exclude: /(node_modules|bower_components)/,
                use: ['babel-loader'],
            },

            /**
             * All output '.js' files will have any sourcemaps re-processed by
             * source-map-loader.
             */
            { test: /\.js$/, enforce: 'pre', loader: 'source-map-loader' },
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
        }),
    ],
}

开始的非常基本的组件:

import React, {SFC} from 'react'

export const Home: SFC<any> = () => <div>HomePage</div>


export default Home

就在我什至尝试将我的组件作为参数传递给 render 方法时,我收到了一个错误

import { Home } from '../pages'; // this import works
import { render } from 'react-testing-library';

describe('', () => {
    test('should render app', () => {
        render(<Home />) // says it cant find "Home"
    });
});

当我 运行 我的测试时,我从控制台得到这个:

  ● Test suite failed to run

    TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    src/__tests__/App.test.ts:6:27 - error TS1005: '>' expected.

    6         console.log(<Home />);
                                ~
    src/__tests__/App.test.ts:6:28 - error TS1161: Unterminated regular expression literal.

    6         console.log(<Home />);

    src/__tests__/App.test.ts:7:5 - error TS1005: ',' expected.

    7     });
          ~
    src/__tests__/App.test.ts:6:22 - error TS2749: 'Home' refers to a value, but is being used as a type here.

    6         console.log(<Home />);
                           ~~~~

更新: 目前我的文件名为 App.test.ts

如果我把它改成App.test.tsx 并将 import * as React from 'react' 添加到测试中 错误消失但测试失败并出现此错误:

  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /<user>/code/react-leader-board/src/__tests__/App.test.tsx:15
            react_testing_library_1.render(<pages_1.Home />);
                                           ^

    SyntaxError: Unexpected token <

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:451:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:493:19)

我建议确保您的模块是在您的环境预设的测试设置中编译的:

{
    "presets": [
        "@babel/react",
        "@babel/typescript",
        [
            "@babel/preset-env",
            {
                "targets": {
                    "browsers": [">0.25%"]
                },
                "modules": false,
                "useBuiltIns": "usage"
            }
        ]
    ],
    "plugins": ["@babel/proposal-class-properties", "@babel/proposal-object-rest-spread"],
    "env": {
        "test": {
            "presets": [
                ["@babel/preset-env", {
                    "modules": "commonjs"
                }]
            ]
        }
    }
}

并使用 babel-jest:

transform: { '\.(ts|tsx)?$': 'babel-jest',`

我运行进入同样的问题,问题是文件的扩展名,应该是.tsx,例如MyComponent.test.tsx