How to write a unit test for a React.js project? - reactjs

I am doing a web-based e-commerce site. Now I need to perform unit testing. Are there any tools required for unit testing?

There are a couple of testing frameworks and libraries for this.
The ones I use are Jest and React Testing Library
There is a curve for the setup but if you are using create-react-app it's already done.
As for the question 'how'. It's dependent of the code because some components just render props and the testing itself is just checking that the props are rendered a certain way.
Some other components have data fetching, hooks and dependencies that need mocking. Until you learn the quirks of both libraries I would advise testing simpler components first. I leave one example
========== index.js ============
import React from 'react'
export default function MyComponent(){
return <div>test</div>
}
=========== index.test.js =============
import React from 'react'
import { render, screen } from '#testing-library/react'
import '#testing-library/jest-dom'
import MyComponent from '.'
test("should render 'test'", () => {
render(<MyComponent />)
expect(screen.queryByText("test")).toBeInTheDocument()
})

Related

How to test a component which is built with styled component

I'm new to React testing and with Jest and Enzyme.
I'm trying to learn how to use a TDD approach first and due to that, I'm building my tests before starting coding.
What I did was to create a sample app in React and I installed Enzyme dependencies and then I wrote the test:
import { shallow } from "enzyme";
import React from "react";
import AppLayout from "./AppLayout";
import { ContentLayout } from "./styles";
it("renders <AppLayout /> component", () => {
const wrapper = shallow(<AppLayout />);
expect(wrapper.find(ContentLayout)).to.have.lengthOf(1);
});
Then I built the component which contains a styled component called ContentLayout
import React from "react";
import { ContentLayout } from "./styles";
const AppLayout = () => {
return (
<>
<ContentLayout>
<h1>HELLO</h1>
</ContentLayout>
</>
);
};
export default AppLayout;
I'm unable yo make the test pass as what I got was the next error:
TypeError: Cannot read property 'have' of undefined
I would like to learn how shoulæd be the practice to test this kind of component and what rules to follow in general when I start a project from scratch with TDD in mind.
The AppLayout is called then in App.js
import React from "react";
import AppLayout from "./Components/AppLayout";
function App() {
return <AppLayout />;
}
export default App;
You should use .toHaveLength(number) matchers of expect in jestjs.
expect(wrapper.find(ContentLayout)).toHaveLength(1);
For nested components, there are two strategies generally:
Shallow Rendering API
Shallow rendering is useful to constrain yourself to test a component as a unit, and to ensure that your tests aren't indirectly asserting the behavior of child components.
This means we don't want to render the nested component(ContentLayout), we only test the behavior(lifecycle methods, event handlers, data fetching, condition render, etc.) of the parent component(AppLayout).
Full Rendering API (mount(...))
Full DOM rendering is ideal for use cases where you have components that may interact with DOM APIs or need to test components that are wrapped in higher order components.

Enzyme / Jest Error testing component render in React (TS)

I've been having an odd issue with Jest/Enzyme testing on my react typescript app. For some reason it gives a syntax error even though this is following the official documentation, as well as input from several articles.
The Code:
import React from 'react';
import NavbarTop from "../components/navbar";
import { shallow } from 'enzyme';
describe('NavbarTop', () => {
it('renders correctly', () => {
const wrapper = shallow(<NavbarTop />);
expect(wrapper).toMatchSnapshot();
// On the first run of this test, Jest will generate a snapshot file automatically.
});
});
The folder structure. I have a named class and then an index with a default export.
The error log.
Do you have JSX configured for Jest? Looks like you don't have support for JSX in Jest, which probably means this is a configuration issue. Have a look at configuring babel to support JSX in Jest.
Make sure you read this tutorial

ReactWrapper::state() can only be called on class components Unit Testing Jest and Enzyme

Writing unit testing in react using jest and enzyme. While checking with a component state , it throws an error "ReactWrapper::state() can only be called on class components ".
import React from 'react';
import { mount } from 'enzyme';
import expect from 'expect';
import CustomerAdd from '../CustomerAdd'
import MUITheme from '../../../../Utilities/MUITheme';
import { ThemeProvider } from '#material-ui/styles';
describe('<CustomerAdd />', () => {
const wrapper = mount(
<ThemeProvider theme={MUITheme}>
<CustomerAdd {...mockProps}></CustomerAdd>
</ThemeProvider>
);
test('something', () => {
expect(wrapper.find(CustomerAdd).state('addNewOnSubmit')).toEqual(true);
});
});
In the above code CustomerAdd Component is class component.I don't what wrong with my code. Can any one help me out of this problem. Thanks in advance.
So your default export
export default withStyles(styles)(CustomerAdd);
exports functional(HOC) wrapper about your class-based component. And it does not matter if name of class and import in
import CustomerAdd from '../CustomerAdd'
are equal. Your test imports wrapped version and after calling .find(CustomerAdd) returns that HOC not your class. And you're unable to work with instance.
Short time solution: export class directly as named export.
export class CustomerAdd extends React.Component{
...
}
export default withStyles(styles)(CustomerAdd);
Use named import in your tests:
import { CustomerAdd } from '../CusomerAdd';
Quick'n'dirty solution: use .dive to access your underlying class-based component:
expect(wrapper.find(CustomerAdd).dive().state('addNewOnSubmit')).toEqual(true);
It's rather antipattern since if you add any additional HOC in your default export you will need to monkey-patch all related tests with adding appropriate amount of .dive().dive()....dive() calls.
Long-term solution: avoid testing state, it's implementation details.
Instead focus on validating what's been rendered. Then you are safe in case of lot of different refactoring technics like replacing class with functional component, renaming state/instance members, lifting state up, connecting component to Redux etc.

How can i make unit test for react component with typescript?

i made a small react project with typescript
and i made it to print numbers of li tag to browser.
so i tried to implement unit test that test component create HTMLElement
but I really confused. I'm a newbie with typescript
import * as React from "react";
import { render } from "#testing-library/react";
import List from "../component/List";
describe("<List />", () => {
it("check li tags were made perfectly", async () => {
const component = render(<List />);
component.getByText("li");
});
this code's output is error at render(<List />);
my component doesn't require any props
how can i make this code is able to run properly?
Thanks to, #Edward Choupuryan
it was just simple problem.
i wanted to test react component with typescript, and that file need to has extension tsx . mine was just *.test.ts
i changed my testfile testfile.test.ts to testfile.test.tsx, and problem solved

Mock import/module with Jest in React application

I am working on a React application and I want to test one module, let's call it B, that depends on another module, let's call it A.
The scenario could be something like this:
moduleA.js
export function helperFn() {
return { prop1: 10, prop2: 20 };
}
moduleB.js
import React from 'react';
import { helperFn } from '../moduleA';
export class CustomComp extends React.Component {
render() {
const helperObj = helperFn();
return (
<div>{helperObj.prop1}</div>
);
}
}
The core libraries to test my components are Jest and Enzyme. My goal here is to test module B, but I want to test it in isolation and so I want to mock the dependency on moduleA.js.
I know one way would be to inject the helperFn as a prop instead of importing it so during the test I can inject a mock function, but there are modules quite big on this app that have a few dependencies each of them.
Researching a bit I found it is posible to mock a dependecy using Jest, but I tried many things with no success. I tried approaches from this question, also from this post and I have no luck. I also read the Manual Mocks and Mock Functions guides from Jest docs, but I think they are pretty confusing.
I could make it work (i.e. I could mock moduleA.js dependency) using the approach on this post, but I had another problem then. It worked just fine to test moduleB.js, but when I went ahead and test moduleA.js, I had to import moduleA.js in moduleA.test.js and I got the mock while I wanted the real module.
So, I need help to understand how I can mock dependency A in moduleB test file.
I hope I was clear if not let me know and I will add the clarifications you might need.
Thanks in advance !
Indeed you can use jest to mock your dependency. There is some configuration you need to set in order to make it work with import. E.g. configuring babel-jest.
If you already have that configuration then you can mock it like so.
import React from 'react';
import { shallow } from 'enzyme';
import { helperFn } from '../moduleA';
jest.mock('../moduleA');
describe("CustomComp", () => {
it("should render component", () => {
helperFn.mockReturnValueOnce({
prop1: "dummy"
});
const component = shallow(<CustomComp />);
});
You can see a working example here.
I'm using Vue2 and trying to write tests for a Vue component. The Vue component uses a lot of other components that aren't really needed to test.
So for that reason, I created a mock for importing other components like below
jest.mock('#/core/components/UserInput.vue', () => ({
exec: jest.fn(),
}));

Resources