Jest UI React js components - unit tests - reactjs

I am pretty new to React and Jest unit test framework. I have my component and trying to write few unit test cases , tried few ways and unable to proceed further. Here is my code and test case. Can anyone guide /suggest the best approaches please.
Non of the tests work and
Thanks
React UI component Header
import React from 'react';
import { Navbar, NavbarBrand } from 'reactstrap';
import { Link } from 'react-router-dom';
const Header = ({children}) =>
<Navbar light className="sticky-top navbar-expand-lg navbar-toggleable-sm bg-white border-bottom">
<NavbarBrand tag={Link} to="/">Abc: Customer Portal</NavbarBrand>
<div className="d-flex w-100 justify-content-end">
{children}
</div>
</Navbar>
export default Header
Tests - non of them pass, could anyone please guide me in the right direction.
import React from 'react'
import { Navbar, NavbarBrand } from 'reactstrap';
import renderer from 'react-test-renderer';
import { render, unmountComponentAtNode, ReactDOM } from "react-dom";
import { act } from "react-dom/test-utils";
import GlobalSettings from './../features/Header/GlobalSettings';
import UserDisplayName from './../features/Header/UserDisplayName';
import Header from './../features/Header/';
let container = null;
beforeEach(() => {
// setup a DOM element as a render target
container = document.createElement("div");
document.body.appendChild(container);
});
afterEach(() => {
// cleanup on exiting
unmountComponentAtNode(container);
container.remove();
container = null;
});
test('test Header component', () => {
//const nav = document.createElement('Navbar');
ReactDOM.render(<Header>
<Link to="/">Damage Matrix: Customer Portal</Link>
</Header>, Navbar);
ReactDOM.unmountComponentAtNode(nav);
});
test('test Header', () => {
act(() => {
render(<Header />, container);
});
expect(container.appendChild).toBe("Hello");
act(() => {
render(<Header children="GlobalSettings" />, container);
});
expect(container.textContent).toBe("GlobalSettings");
});
test('renders correctly', () => {
const tree = renderer.create(
<Header />
).toJSON();
expect(tree).toMatchSnapshot();
});

Related

React Jest testing : TestingLibraryElementError: Unable to find an element

i can't get the test id within my jest test. I am new to react testing. I want to test this component and get back for example the h3 text what was given before.
Tells me:
"TestingLibraryElementError: Unable to find an element by: [data-testid="testH3"]"
Can you help me?
// Component
import React from 'react';
import './Card.scss';
import Card from '#material-ui/core/Card';
import { Link } from "react-router-dom";
function MovieCard({title, image}) {
return (
<div className="card__container">
<Link to={"/details/" + title}>
<Card className="card">
<img src={image} alt=""/>
<div className="card__info">
<h3
data-testid="testH3"
className="card__title">{ title }
</h3>
</div>
</Card>
</Link>
</div>
)
}
export default MovieCard
// test
import React from 'react';
import { render, screen, cleanup } from '#testing-library/react';
import MovieCard from '../MovieCard';
import { BrowserRouter as Router } from "react-router-dom";
afterEach(cleanup);
describe('Test MovieCard', () => {
const tree = render(
<Router>
<MovieCard title="Batman" image="imagesrc"/>
</Router>
)
it('should match with snapshot', () => {
screen.debug();
expect(tree).toMatchSnapshot();
});
it('test h3', () => {
const {getByTestId} = tree;
const element = screen.getByTestId('testH3')
});
});
UPDATE:
Final code works now pretty well. Thank you guys
import React from 'react';
import { render, screen, cleanup } from '#testing-library/react';
import MovieCard from '../MovieCard';
import { BrowserRouter as Router } from "react-router-dom";
afterEach(cleanup);
describe('Test MovieCard', () => {
function tree() {
return render(
<Router>
<MovieCard title="Batman" image="imagesrc"/>
</Router>
)
}
it('should match with snapshot', () => {
expect(tree()).toMatchSnapshot();
});
it('test h3 text is Batman', () => {
const {getByTestId} = tree();
const element = screen.getByTestId('testH3')
expect(element.textContent).toEqual("Batman")
screen.debug();
});
});
use function instead of const
describe('Test MovieCard', () => {
function tree() {
return render(
<Router>
<MovieCard title="Batman" image="imagesrc"/>
</Router>
)
}
it('should match with snapshot', () => {
screen.debug();
expect(tree()).toMatchSnapshot();
});
it('test h3', () => {
const {getByTestId} = tree();
const element = screen.getByTestId('testH3')
});
});

Is it Possible to use Enzyme testing with Next js (SSR)?

It's My first Nextjs project with SSR.
When Integrating Enzyme For Reactjs UI Testing. it could not run due to "React' refers to a UMD global, but the current file is a module. Consider adding an import instead."
but it's works when i am using normal Reactjs Component(Functional or Class). Anyone Please give suggestions.
SandBox Link - https://codesandbox.io/s/currying-moon-gdk09
Full code From GitHub - https://github.com/Rizz13/nextJs-with-Enzyme
to run testing Use "npm test"
pages/Index.tsx
import Head from 'next/head'
import Link from 'next/link'
import { GetStaticProps } from 'next'
export default function Home({
allPostsData
}: {
allPostsData: {
title: string
id: string
}[]
}) {
return (
<>
<Head>
<title>Sample Page</title>
</Head>
<section className="icon-stars">
<p>[Your Self Introduction]</p>
<p>
(This is a sample website - you’ll be building a site like...)
</p>
</section>
<section>
<h2>Blog</h2>
<ul>
{allPostsData.map(({ id, title }) => (
<li key={id}>
<Link href="#">
<a>{title}</a>
</Link>
<br />
</li>
))}
</ul>
</section>
</>
)
}
export const getStaticProps: GetStaticProps = async () => {
const allPostsData = [{id: 0, title:"Sample1"}, {id: 1, title:"Sample2"}]
return {
props: {
allPostsData
}
}
}
_tests_/Index.tsx
import * as React from 'react'
import { expect as expect1 } from 'chai';
import IndexPage from '../pages/index'
import {/*mount,*/ shallow} from 'enzyme'
const setUp1 = (data) => {
return shallow(<IndexPage {...data} />);
}
let wrapper;
describe('props Check', () => {
beforeEach(() => {
wrapper = setUp1({});
});
it('should render an `.icon-stars`', () => {
expect1(wrapper.find('.icon-stars')).to.have.length(1);
});
});
When I using the Above Code Testing could not run due to below Error.
tests/Index.tsx
import * as React from 'react'
import { expect as expect1 } from 'chai';
import IndexPage from '../pages/index'
import {/*mount,*/ shallow} from 'enzyme'
const setUp1 = (data) => {
return shallow(<IndexPage {...data} />);
}
let wrapper;
describe('props Check', () => {
beforeEach(() => {
wrapper = setUp1(allPostsData={[]});
});
it('should render an `.icon-stars`', () => {
expect1(wrapper.find('.icon-stars')).to.have.length(1);
});
});
You have to pass props inside the testing component & use
import * as React from 'react'
In pages/Index.tsx for rendering react components

Jest Manual Mock for ThemeProvider

I want to test a React Component that uses Material-UI`s makeStyles.
My Component:
import React from 'react';
import { useTranslation } from 'react-i18next';
import { DefaultButton } from '../../../../components';
import { makeStyles } from '#material-ui/styles';
const useStyles = makeStyles((theme: any) => ({
root: {},
row: {
marginTop: theme.spacing()
},
spacer: {
flexGrow: 1
},
}));
const UsersToolbar: React.FC<any> = (props) => {
const classes = useStyles();
const { t } = useTranslation();
return (
<div className={classes.root}>
<div className={classes.row}>
<span className={classes.spacer} />
<DefaultButton id="createUserBtn">{t('Create User')}</DefaultButton>
</div>
</div>
);
};
export default UsersToolbar;
My test:
import React from 'react';
import ReactDOM from 'react-dom';
import { createMuiTheme } from '#material-ui/core';
import { ThemeProvider } from '#material-ui/styles';
import UsersToolbar from '.';
describe('<UsersToolbar />', () => {
it('passes smoke test', () => {
const div = document.createElement('div');
ReactDOM.render(
<UsersToolbar />,
div
);
});
});
I was thinking about using jest.mock() and place a manual mock in __mocks__/
How can I do that? I tried to provide a ThemeProvider as proposed on the official Material-UI homepage (https://material-ui.com/guides/testing/) but it did not work out.
I solved this by creating a component named MockTheme which wraps the component that needs to be tested. The result looks like the following:
import React from 'react';
import { createMuiTheme } from '#material-ui/core';
import { ThemeProvider } from '#material-ui/core/styles';
function MockTheme({ children }: any) {
const theme = createMuiTheme({});
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}
export default MockTheme;
The modified test now works:
import React from 'react';
import ReactDOM from 'react-dom';
import MockTheme from '../../../../theme/MockTheme';
import UsersToolbar from '.';
describe('<UsersToolbar />', () => {
it('passes smoke test', () => {
const div = document.createElement('div');
ReactDOM.render(
<MockTheme>
<UsersToolbar />
</MockTheme>,
div
);
});
});

Enzyme unit test is passing test when it should fail

I'm trying to test a component it has two props title, and url.
I'm unsure how to pass mock data, i made an attempt but it passes but im pretty sure its not reading whats in the data object
Both tests are passing.
Card.js
import React, {Component} from 'react';
const Styles = {
width: '300px',
height: '300px'
}
class Card extends React.Component {
render() {
return (
<div>
{/* Renders title of the GIY */}
<h1>{this.props.title}</h1>
<div >
<img alt="" src={this.props.url}/>
</div>
</div>
);
}
}
export default Card;
Card.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import {shallow} from 'enzyme';
import Card from './Card';
describe('Should render Card Component', ()=> {
it('should render card component', ()=> {
const component = shallow(<Card />);
})
});
describe('Should render title/ url prop', ()=>{
it('should render title /url prop', ()=>{
// trying to mock data for the Card component
const data = {
title: "owl",
url:"https://giphy.com/gifs/bird-owl-qISaMW1xwmvNS"
}
const component = shallow(<Card title={data.title} url={data.url}/>)
})
})
You're not making any assertions. You need to expect some result to happen.
Card.js (this can be a pure function if it doesn't require state)
import React from "react";
import PropTypes from "prop-types";
const styles = {
width: "300px",
height: "300px"
};
const Card = ({ title, url }) =>
title && url ? ( // if a title and url are passed in, return <div>...</div>, else return "null"
<div className="card">
<h1>{title}</h1>
<div>
<img alt="" src={url} styles={styles} />
</div>
</div>
) : null;
// PropTypes will throw a warning if either of them is missing
PropTypes.propTypes = {
title: PropTypes.string.isRequired,
url: PropTypes.string.isRequired
};
export default Card;
Card.test.js
import React from "react";
import { shallow } from "enzyme";
import Card from "../index";
// we define initial props (empty strings)
const initialProps = {
title: "",
url: ""
};
// we shallow wrap the Card while passing in the "initialProps"
const wrapper = shallow(<Card {...initialProps} />);
// we define some props that will be passed in during our second test
const nextProps = {
title: "owl",
url: "https://media.giphy.com/media/qISaMW1xwmvNS/giphy.gif"
};
describe("Card Component", () => {
afterAll(() => wrapper.unmount());
it("shouldn't render a card without the required props", () => {
expect(wrapper.type()).toBeNull();
});
it("should render a card if the required props are present", () => {
wrapper.setProps({ ...nextProps }); // we update the component with "nextProps"
expect(wrapper.find("div.card")).toHaveLength(1); // expect "div.card" to be present
expect(wrapper.find("h1").text()).toContain(nextProps.title); // expect the "h1" element to contain "owl"
expect(wrapper.find("img").prop("src")).toBe(nextProps.url); // expect the "img"'s src to be "https://media.giphy.com/media/qISaMW1xwmvNS/giphy.gif"
});
});
Working example: https://codesandbox.io/s/k35zpqwk97

React component test with enzyme

I have a component like this:
component.js
import React from "react";
import PropTypes from "prop-types";
const Test = ({ text }) => (
<div>
{text.split("\n").map((item, key) => {
return (
<span key={key}>
{item}
<br />
</span>
);
})}
</div>
);
Test.propTypes = {
text: PropTypes.string.isRequired
};
export default Test;
How do i write component test for this react component using enzyme? I am new to react and enzyme. Any help will really appreciable.
This could be a test using mocha:
import {shallow} from 'enzyme'
import assert from 'assert'
import Test from './Test'
describe('component Test', () => {
it('should show a span for each line of "text" prop', () => {
const text = `foo
bar
`
const wrapper = shallow(<Test text={text} />)
const spans = wrapper.find('span')
assert.equal(spans.length, 2)
assert.equal(spans.at(0).text(), 'foo')
assert.equal(spans.at(1).text(). 'bar')
})
it('should throw if "text" prop is not provided', () => {
assert.throws(() => {
shallow(<Text />)
})
})
})
Here is shamelessly taken example of testing dom using enzyme + jest (from jest web site):
// __tests__/CheckboxWithLabel-test.js
import React from 'react';
import {shallow} from 'enzyme';
import CheckboxWithLabel from '../CheckboxWithLabel';
test('CheckboxWithLabel changes the text after click', () => {
// Render a checkbox with label in the document
const checkbox = shallow(
<CheckboxWithLabel labelOn="On" labelOff="Off" />
);
expect(checkbox.text()).toEqual('Off');
checkbox.find('input').simulate('change');
expect(checkbox.text()).toEqual('On');
});
I recommend you to go though the link I gave - it contains nice examples of testing react components using Jest + Enzyme.

Resources