Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I was bootstrapping my first TypeScript + React project from scratch. I was successful with the TypeScript and component rendering. However, as I try to add a test, it just fails with some type errors.

I've tried to play around with different configurations, even adding a setupTests.ts file.

Here is my configuration: 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',
        }),
    ],
}

Very basic component to start with:

import React, {SFC} from 'react'

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


export default Home

Right when I even try to pass my component as an argument to the render method I get an error

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"
    });
});

When I run my test I get this from the console:

  ● 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 />);
                           ~~~~

UPDATE: currently my file is called App.test.ts

if I change it to App.test.tsx and add import * as React from 'react' to the test the errors go away but the test fails with this error:

  ● 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)
like image 815
aromanarguello Avatar asked Mar 30 '19 19:03

aromanarguello


2 Answers

I ran into the same issue, the problem was the extension of a file, it should be .tsx, for example MyComponent.test.tsx

like image 135
HiImMardzin Avatar answered Nov 17 '22 10:11

HiImMardzin


I would suggest making sure that your modules are being compiled in the test settings of your env preset:

{
    "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"
                }]
            ]
        }
    }
}

and using babel-jest:

transform: { '\\.(ts|tsx)?$': 'babel-jest',`
like image 34
bitten Avatar answered Nov 17 '22 11:11

bitten