Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test with jest and typescript with types a basic react function component

This is a bit shocking, but I've been long long time trying to find a simple example on how to test a silly react component using jest and typescript, and I am unable to succeed. I've had a look at: https://basarat.gitbooks.io/typescript/content/docs/testing/jest.html How to use react-test-renderer/shallow with typescript? How to see what the rendered React component looks like in the Jest unit test?

Nothing works. Most of the times I get

Test suite failed to run
'App' refers to a value, but is being used as a type here.

I'm new to react and jest. I've tried react-test-renderer and enzyme. At this stage I don't mind either, the most agnostic possible would be great.

What I have: This is my package.json

{
    "name": "web",
    "version": "1.0.0",
    "description": "mySample",
    "main": "index.js",
    "scripts": {
        "build-dev": "webpack --watch",
        "build": "webpack",
        "start-dev": "nodemon build/server.js",
        "start": "node build/server.js",
        "test": "jest"
    },
    "dependencies": {
        "express": "^4.17.1",
        "react": "^16.8.6",
        "react-dom": "^16.8.6"
    },
    "devDependencies": {
        "@types/enzyme": "^3.10.3",
        "@types/express": "^4.17.0",
        "@types/jest": "^24.0.16",
        "@types/node": "^12.6.9",
        "@types/react": "^16.8.24",
        "@types/react-dom": "^16.8.5",
        "enzyme": "^3.10.0",
        "jest": "^24.8.0",
        "nodemon": "^1.19.1",
        "ts-jest": "^24.0.2",
        "ts-loader": "^6.0.4",
        "typescript": "^3.5.3",
        "webpack": "^4.39.1",
        "webpack-cli": "^3.3.6",
        "webpack-node-externals": "^1.7.2"
    }
}

as you can see, I'd like to have strongly typed tests with typescript, and that's why I need enzyme types.

I have a silly react component App.tsx

import * as React from "react";

interface WelcomeProps {
    name: string;
}

const App: React.FC<WelcomeProps> = ({ name }) => {
    return <h1>Hello, {name}</h1>;
};

export default App;

And I want to have a test file App.test.ts where I simply test that given the <App name="whatever" /> renders, the DOM should have <h1>Hello, whatever</h1>

My attempt was:

import * as React from "react";
import App from "./App";
import { shallow } from "enzyme";

describe("App component", () => {
    it("returns the name passed as props", () => {
        const app = shallow(<App name="test" />);
        expect(app).toMatchSnapshot();
    });
});

and it fails with the above error, plus the VS Code displays error on the shallow argument as if it didn't understand JSX.

In case it's needed my jest.config.js is:

module.exports = {
    roots: ["<rootDir>/src"],
    transform: {
        "^.+\\.tsx?$": "ts-jest"
    }
};

It can't get simpler than this, yet I'm failing!

PS: The vast majority of the articles I find don't use typescript and type definitions, but this is something I want.

like image 841
diegosasw Avatar asked Jan 27 '23 00:01

diegosasw


2 Answers

I know it's a old question, but I bumped into the same problem and it has a simple solution: your file name must have the .tsx extension for using jsx tag.

like image 126
alphamz Avatar answered Jan 29 '23 10:01

alphamz


Update: While this was accepted, the much better answer was provided by @alphamz below (.tsx vs .ts). That said I would still suggest create-react-app or create-next-app (much better in 2021) for React newbies who want to get up and running quickly, then you're starting with good time-tested settings.

Original answer: For someone new to React and Jest like yourself, I would strongly suggest starting with Create-React-App with the Typescript extension

https://facebook.github.io/create-react-app/docs/adding-typescript

This gives a good baseline for TS usage with jest support (has pretty strong app defaults as well)

yarn create react-app my-app --typescript

From there, use React-Testing-Library here: https://testing-library.com/docs/react-testing-library/intro

And you can write tests like this

import { render } from 'react-testing-library';

test('init GameTotaler', () => {
  const myName: string = 'foo';
  const { getByText } = render(
    <App name={foo} />
  );
  expect(getByText(`Hello, ${foo}`)).toBeTruthy();
});

@testing-library (that react-testing-library is part of) is extremely well written and supported by Kent C. Dodds, who is a remarkably strong author of React articles and on testing in general.

He has recently written why shallow rendering (which is what is done in Enzyme) can be an anti-pattern (at least for him) - https://kentcdodds.com/blog/why-i-never-use-shallow-rendering

Note that create-react-app does hide things inside its generated framework, but is well supported.

One strong plus - If you want to completely pull out of create-react-app once it's generated your codebase, you can run react-scripts eject and then you can see the secret sauce while still having a fully buildable codebase.

Hope this helps - Good luck!

like image 30
BarryM Avatar answered Jan 29 '23 11:01

BarryM