Jest Unit Test - Mocking component with props - reactjs

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>
`;

Related

Material-UI: the value provided `undefined` to the Tabs component is invalid

I am not having this warning probably on the normal functioning of the app but I am having this problem in the unit tests. So I am doing a unit test for a Tabs component and it gives me the following warning:
my jsx file looks like this:
class SimpleTabs extends React.Component {
handleChange = (event, value) => {
const { onChange } = this.props;
onChange(value);
};
render() {
const { classes, selectedChannelIndex } = this.props;
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs
key={selectedChannelIndex}
value={selectedChannelIndex}
onChange={this.handleChange}
classes={{ root: classes.tabsRoot, indicator: classes.tabsIndicator }}
>
{CHANNELS_ARRAY &&
CHANNELS_ARRAY.map((channel, i) => (
<Tab
key={i}
value={i}
label={channel.channel}
classes={{ root: classes.tabRoot, selected: classes.tabSelected }}
/>
))}
</Tabs>
</AppBar>
<TabContainer>{this.props.children}</TabContainer>
</div>
);
}
}
export default withStyles(styles)(SimpleTabs);
and my unit test file looks like this:
import React from 'react';
import Adapter from 'enzyme-adapter-react-16';
import { configure, mount } from 'enzyme';
import { shallowToJson } from 'enzyme-to-json';
import Tabs from '../../../src/components/common/Tabs/Tabs';
configure({ adapter: new Adapter() });
const defaultProps = { selectedChannelIndex: 0, value: 0, selectInput: 0 };
const setup = (props = {}) => {
const setupProps = { ...defaultProps, ...props };
return shallow(<Tabs {...setupProps} />);
};
describe('Tabs', () => {
const wrapper = mount(<Tabs {...defaultProps} />);
it('should be defined', () => {
expect(Tabs).toBeDefined();
});
it('should render correctly', () => {
const tree = mount(<Tabs />);
expect(shallowToJson(tree)).toMatchSnapshot();
});
});
I've seen others asking about this warning as well but many times it's said that to add the value on the tabs element is the solution but is not working for me.

react - writting twice same test passes first but not second time

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

React Jest snapshot tests fail when --coverage flag enabled

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

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