I have built a React app (v16.13.1) and am testing it with Jest (v25.1.0). When I run npm test the tests all pass fine, but when I run npm test -- --coverage all of the components return undefined and all of the snapshot tests fail.
It's happening with every component in the app. A typical example of a component exhibiting this behaviour is:
src/components/Card.js
import React from 'react';
import PropTypes from 'prop-types';
const Card = ({ title, subtitle, children }) => (
<div className="card">
{title && <div className="card-header">{title}</div>}
<div className="card-body">
{subtitle && <div className="small mb-3">{subtitle}</div>}
<div className="mt-3">{children}</div>
</div>
</div>
);
Card.propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string,
children: PropTypes.node.isRequired
};
Card.defaultProps = {
title: null,
subtitle: null
};
export default Card;
src/components/Card.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import Card from './Card';
let tree;
describe('without title or subtitle', () => {
beforeAll(() => {
tree = renderer.create(
<Card>
<p>Hello there</p>
</Card>
);
});
it('renders correctly', () => {
expect(tree).toMatchSnapshot();
});
});
describe('with title and subtitle', () => {
beforeAll(() => {
tree = renderer.create(
<Card title="Test" subtitle="This is a test">
<p>Hello there</p>
</Card>
);
});
it('renders correctly', () => {
expect(tree).toMatchSnapshot();
});
});
These tests all used to pass just fine but now they are failing but only when the coverage flag is enabled.
What am I doing wrong?
I think I've seen this before: For stateless components, you may need to define displayName prop.
https://github.com/facebook/jest/issues/1824#issuecomment-250478026
Related
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
Im a bit new to the react ecosytem. Im having a weird behaviour with passing tests.
Im using CRA, prop-types and react-test-library.
Here is my component:
import React from 'react';
import PropTypes from 'prop-types';
export default function Navbar({
Logo, MenuItems, className,
}) {
return (
<nav aria-label="navigation bar" className={className}>
{Logo}
<div>
{ MenuItems.map((MenuItem) => MenuItem) }
</div>
</nav>
);
}
Navbar.defaultProps = {
className: '',
};
Navbar.propTypes = {
className: PropTypes.string,
Logo: PropTypes.node.isRequired,
MenuItems: PropTypes.arrayOf(PropTypes.node).isRequired,
};
I want to test that prop-types complains when params are not receiving the right type.
import React from 'react';
import { render } from '#testing-library/react';
import Navbar from './Navbar';
describe('<Navbar />', () => {
beforeAll(() => {
jest.spyOn(console, 'error').mockImplementation(() => {});
});
beforeEach(() => {
console.error.mockClear();
});
afterAll(() => {
console.error.mockRestore();
});
it('renders', () => {
render(<Navbar
Logo={<p data-test="logo">My logo</p>}
MenuItems={[
<p key="spanish">Spanish</p>,
<p key="english">english</p>,
]}
/>);
expect(console.error).not.toHaveBeenCalled();
});
it('errors to console when Logo is missing', () => {
render(<Navbar MenuItems={[
<p key="spanish">Spanish</p>,
<p key="english">English</p>,
]}
/>);
expect(console.error).toHaveBeenCalled();
});
it('does not error to console when Logo is missing', () => {
render(<Navbar MenuItems={[
<p key="spanish">Spanish</p>,
<p key="english">English</p>,
]}
/>);
expect(console.error).toHaveBeenCalled();
});
});
My thinking is that Im not resetting properly the mocks, they have some state that it is not clear or something similar.
What am i missing?
PropTypes.checkPropTypes(...) only console.errors a given message once. To reset the error warning cache in tests, call PropTypes.resetWarningCache()
Source
Try invoke resetWarningCache in your beforeEach hooks
import PropTypes from 'prop-types';
beforeEach(() => {
PropTypes.resetWarningCache()
});
I am trying to make a Jest Mock for NextSeo where I can run assertions on the props passed to Meta.
I have a basic working example below but I am unsure of how to include props in my Mock to run assertions on.
Meta Component
const Meta = (props: Props) => {
return (
<NextSeo
title={props.title == 'Homepage' ? appMeta.title : props.title}
description={
props.title == 'Homepage' ? appMeta.description : props.description
}
/>
);
};
export default Meta;
Meta Unit Test
jest.mock('next-seo', () => ({
NextSeo: '<div></div>', // I am trying to add props here
}));
describe('<ContactUs/>', () => {
it('can render with default props', () => {
const ContactUsWrapper = shallow(
<Meta title="title" description="description" />
);
expect(NextSeo).toEqual('<div></div>');
});
});
What I am trying to achieve:
Mock:
jest.mock('next-seo', () => ({
NextSeo: '<div>{props.title} {props.desctription}</div>',
}));
Spec:
expect(NextSeo).toEqual('<div>title description</div>');
You can mock NextSeo component a functional component. E.g.
index.tsx:
import React from 'react';
import { NextSeo } from './next-seo';
type Props = any;
const Meta = (props: Props) => {
const appMeta = { title: '', description: '' };
return (
<NextSeo
title={props.title === 'Homepage' ? appMeta.title : props.title}
description={props.title === 'Homepage' ? appMeta.description : props.description}
/>
);
};
export default Meta;
next-seo.tsx:
import React from 'react';
export const NextSeo = ({ title, description }) => <span></span>;
index.test.tsx:
import Meta from './';
import React from 'react';
import { mount } from 'enzyme';
jest.mock('./next-seo', () => ({
NextSeo: (props) => (
<div>
{props.title} {props.description}
</div>
),
}));
describe('<ContactUs/>', () => {
it('can render with default props', () => {
const ContactUsWrapper = mount(<Meta title="title" description="description" />);
expect(ContactUsWrapper).toMatchSnapshot();
});
});
test results:
PASS stackoverflow/60759940/index.test.tsx (7.958s)
<ContactUs/>
✓ can render with default props (37ms)
› 1 snapshot updated.
Snapshot Summary
› 1 snapshot updated from 1 test suite.
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 1 updated, 1 total
Time: 9.08s
index.test.tsx.snap:
// Jest Snapshot v1
exports[`<ContactUs/> can render with default props 1`] = `
<Meta
description="description"
title="title"
>
<NextSeo
description="description"
title="title"
>
<div>
title
description
</div>
</NextSeo>
</Meta>
`;
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
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.