A shallow renderer for React components
This is a fork of @jakesidsmith/react-shallow-renderer.
This is an alternative renderer to react-test-renderer/shallow
with full support for:
- React.memo
- React.forwardRef
- React.Fragment
- React.createContext (Provider and Consumer)
- ReactDOM.createPortal
- Functional components
- Component classes
The output of this renderer is far more informative than other existing renderers, providing context of memo wrapped components, fragments, etc.
npm i @dabapps/react-shallow-renderer -S
Example with jest:
import React from 'react';
import { ReactShallowRenderer } from '@dabapps/react-shallow-renderer';
import MyComponent from './path';
describe('MyComponent', () => {
it('renders some stuff', () => {
const renderer = new ReactShallowRenderer(<MyComponent />);
expect(renderer).toMatchSnapshot();
});
});
Newer versions of jest will automatically call the toJSON
method of the renderer. If the version you are using doesn't you can try:
expect(renderer.toJSON()).toMatchSnapshot();
A form component using memo
, Fragment
, a SubmitButton
component that uses memo
, and an external form library that uses forwardRef
import React from 'react';
import { Field } from 'form-library';
import SubmitButton from './path';
const MyComponent = (props) => (
<>
<h1>
Log in
</h1>
<form onSubmit={props.handleSubmit}>
<Field component="input" type="email" name="email" />
<Field component="input" type="password" name="password" />
<SubmitButton>
Log in
</SubmitButton>
</form>
<a href="/forgot-password">
Forgot password?
</a>
</>
);
export default React.memo(MyComponent);
<React.Fragment>
<h1>
Log in
</h1>
<form
onSubmit={[Function]}
>
<React.forwardRef(Field)
component="input"
type="email"
name="email"
/>
<React.forwardRef(Field)
component="input"
type="password"
name="password"
/>
<React.memo(SubmitButton)>
Log in
</React.memo(SubmitButton)>
</form>
<a
href="/forgot-password"
>
Forgot password?
</a>
</React.Fragment>
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import Popover from './path';
import { MyContext } from './another-path';
export default class MyComponent extends PureComponent {
render() {
return ReactDOM.createPortal(
(
<Popover>
<MyContext.Consumer>
{(value) => (
<p>
Some content: {value}
</p>
)}
</MyContext.Consumer>
</Popover>
),
document.getElementById('my-id')
);
}
}
<ReactDOM.Portal>
<Popover>
<React.Consumer>
[Function: Unknown]
</React.Consumer>
</Popover>
</ReactDOM.Portal>
You can avoid the Unknown
function here by defining a named function, or const
outside of the render method, which should give you a nicer output, such as:
<React.Consumer>
[Function: myFunction]
</React.Consumer>
In order to get better snapshots (and avoid unknown component names in dev tools), you should not define anonymous / arrow functions in your render method, or immediately inside wrappers like React.memo and React.forwardRef. Instead I recommend the following:
const MyComponent = () => <div />;
export default React.memo(MyComponent);
Or with react-redux:
const MyComponent = () => <div />;
export default connect(mapStateToProps)(React.memo(MyComponent));
Ensure you have added a remote upstream in git e.g.
git remote add upstream [email protected]:JakeSidSmith/react-shallow-renderer.git
Create a new branch (from master) and run the following to pull changes from upstream:
git fetch upstream
git pull upstream master