jest-mock-external-components
Version:
Mock external React components with jest
129 lines (94 loc) • 3.94 kB
Markdown
## Easy automock your external react components
Do you like write component tests? Do you like react-test-renderer more than shallow renderer? Do you feel sometimes that it would be great to combine both shallow renderer and react-test-renderer to prevent rendering inner components? Do you feel headcache when writing tests for something like [styled-components](https://www.styled-components.com/) ? Are you bored to write numerous ```jest.mock()``` calls to mock your component?
If the answer for any of these questions is "Yes" then you come to the right place.
Much often, you want to mock/don't render external components. Almost always these external components are being imported through import statement ```import A from "./a"```. And very often you want to full render the inner (helpers or styled) components:
```jsx
import Button from "./Button";
import AnotherComp from "./AnotherComp";
const SomeText = () => <h1>SomeText</h1>
const SomeLabel = styled.label`
font-size: 0.8em;
`;
const MyButton = styled(Button)`
font-size: 2em;
`
const Component = () =>
<div>
<SomeText />
<AnotherComp />
<SomeLabel>Label</SomeLabel>
<MyButton>Button</MyButton>
</div>
```
Here you probably want to fully render ```SomeText``` , ```SomeLabel``` and partially ```MyButton``` (render styles but don't render ```Button``` itself). ```AnotherComp``` should remain non-rendered (so it's internals won't affect the component test).
This is not achievable by standard react-test-renderer, it will give you snapshot similar to this:
```html
.SomeLabelCss {}
.MyButtonCss {}
// Shouldn't be here
.ButtonCss {}
// Shouldn't be here
.AnotherCompCss {}
<div>
<h1>SomeText</h1>
// Shouldn't be here
<div className="AnotherCompCss">AnotherComp internals</div>
<label className="SomeLabelCss">Label</label>
// Shouldn't be here
<button className="MyButtonCss ButtonCss">Button</button>
</div>
```
Shallow renderer also won't give you desired result:
```html
// No styles since it doesn't unwrap styled-component HOC
<div>
// Didn't unwrap the internal component
<SomeText />
<AnotherComp />
// Didn't unwrap the internal component
<SomeLabel>Label</SomeLabel>
// Didn't unwrap the internal component
<MyButton>Button</MyButton>
</div>
```
Ideally, you want this snapshot:
```html
.SomeLabelCss {}
.MyButtonCss {}
<div>
<h1>SomeText></h1>
// External component shouldn't be rendered
<AnotherComp />
<label className="SomeLabelCss">Label</label>
// Unwrap styled HOC but don't render further. Button already has dedicated test
<Button className="MyButtonCss">Button</Button>
</div>
```
This is achievable by mocking components using ```jest.mock()``` but this is boring and repetetive task, especially when you have to mock many components:
```jsx
jest.mock("../AnotherComp", () => "AnotherComp");
jest.mock("../Button", () => "Button");
jest.mock("../SomeComp", () => ({ SomeComp: "SomeComp" })); // very ugly for named exports
// etc...
```
Finally, now you can just use ```jest-mock-external-components```:
```jsx
import Component from "../mycomponent";
import { mockExternalComponents } from "jest-mock-external-components";
mockExteralComponents(Component);
// will automatically mock <Button /> and <AnotherComp />
// Use react-test-renderer
const t = create(<Component />);
expect(t.toJSON()).toMatchSnapshot();
```
and it will you give the snapshot which you want with mocked external dependencies and fully-rendered internal components! and it's not shallow, so the lifecycle, refs etc will continue to work.
## Installation and setup
```yarn add jest-mock-external-components --dev```
or
```npm install jest-mock-external-components --save-dev```
Add to your ```.babelrc``` / ```.babelrc.js``` / ```babel.config.js```
```
plugins: [
"jest-mock-external-components/babel",
]
```