A set of utilities for testing Styled Components with Jest.
This package improves the snapshot testing experience and provides a brand new matcher to make expectations on the style rules.
Jest snapshot testing is an excellent way to test React components (or any serializable value) and make sure things don't change unexpectedly.
It works with Styled Components but there are a few problems that this package addresses and solves.
For example, suppose we create this styled Button:
When we run our test command, Jest generates a snapshot containing a few class names (which we didn't set) and no information about the style rules:
exports[`it works 1`]=`<button className="sc-bdVaJa rOCEJ"/>`;
Consequently, changing the color to green:
constButton=styled.button` color: green;`
Results in the following diff, where Jest can only tell us that the class names are changed.
Although we can assume that if the class names are changed the style rules are also changed, this is not optimal (and is not always true).
- Snapshot+ Received
<button
- className="sc-bdVaJa rOCEJ"+ className="sc-bdVaJa hUzqNt"
/>
Here's where Jest Styled Components comes to rescue.
We import the package into our test file:
import'jest-styled-components'
When we rerun the test, the output is different: the style rules are included in the snapshot, and the hashed class names are substituted with placeholders that make the diffs less noisy:
The snapshots will contain class instead of className.
Learn more.
Serializer
The serializer can be imported separately from jest-styled-components/serializer.
This makes it possible to use this package with specific-snapshot and other libraries.
The toHaveStyleRule matcher is useful to test if a given rule is applied to a component.
The first argument is the expected property, the second is the expected value which can be a String, RegExp, Jest asymmetric matcher or undefined.
When used with a negated ".not" modifier the second argument is optional and can be omitted.
constButton=styled.button` color: red; border: 0.05em solid ${props=>props.transparent ? 'transparent' : 'black'}; cursor: ${props=>!props.disabled&&'pointer'}; opacity: ${props=>props.disabled&&'.65'};`test('it applies default styles',()=>{consttree=renderer.create(<Button/>).toJSON()expect(tree).toHaveStyleRule('color','red')expect(tree).toHaveStyleRule('border','0.05em solid black')expect(tree).toHaveStyleRule('cursor','pointer')expect(tree).not.toHaveStyleRule('opacity')// equivalent of the following twoexpect(tree).not.toHaveStyleRule('opacity',expect.any(String))expect(tree).toHaveStyleRule('opacity',undefined)})test('it applies styles according to passed props',()=>{consttree=renderer.create(<Buttondisabledtransparent/>).toJSON()expect(tree).toHaveStyleRule('border',expect.stringContaining('transparent'))expect(tree).toHaveStyleRule('cursor',undefined)expect(tree).toHaveStyleRule('opacity','.65')})
The matcher supports an optional third options parameter which makes it possible to search for rules nested within an At-rule (see media and supports) or to add modifiers to the class selector. This feature is supported in React only, and more options are coming soon.
You can take a similar approach when you have classNames that override styles
constButton=styled.button` background-color: red; &.override { background-color: blue; }`constwrapper=mount(<ButtonclassName="override">I am a button!</Button>);expect(wrapper).toHaveStyleRule('background-color','blue',{modifier: '&.override',});
This matcher works with trees serialized with react-test-renderer, react-testing-library, or those shallow rendered or mounted with Enzyme.
It checks the style rules applied to the root component it receives, therefore to make assertions on components further in the tree they must be provided separately (Enzyme's find might help).
Note: for react-testing-library, you'll need to pass the first child to check the top-level component's style. To check the styles of deeper components, you can use one of the getBy* methods to find the element (e.g. expect(getByTestId('styled-button')).toHaveStyleRule('color', 'blue'))
To use the toHaveStyleRule matcher with React Native, change the import statement to:
import'jest-styled-components/native'
Global installation
It is possible to setup this package for all the tests. For Example: import the library once in the src/setupTests.js as follows:
If Jest Styled Components is not working, it is likely caused by loading multiple instances of styled-components. This can happen especially when working with a Lerna monorepo. Starting with styled-compon[email protected], a warning will be logged when multiple instances of it are being included and run as part of the Jest tests. Using [email protected] and lower with multiple instances will cause a silent error with unexpected results.
styled-components/jest-styled-components
Jest Styled Components
A set of utilities for testing Styled Components with Jest. This package improves the snapshot testing experience and provides a brand new matcher to make expectations on the style rules.
Quick Start
Installation
Usage
If you don't want to import the library in every test file, it's recommended to use the global installation method.
Table of Contents
Snapshot Testing
Jest snapshot testing is an excellent way to test React components (or any serializable value) and make sure things don't change unexpectedly. It works with Styled Components but there are a few problems that this package addresses and solves.
For example, suppose we create this styled Button:
Which we cover with the following test:
When we run our test command, Jest generates a snapshot containing a few class names (which we didn't set) and no information about the style rules:
Consequently, changing the color to green:
Results in the following diff, where Jest can only tell us that the class names are changed. Although we can assume that if the class names are changed the style rules are also changed, this is not optimal (and is not always true).
Here's where Jest Styled Components comes to rescue.
We import the package into our test file:
When we rerun the test, the output is different: the style rules are included in the snapshot, and the hashed class names are substituted with placeholders that make the diffs less noisy:
This is the resulting snapshot:
Now, suppose we change the color again to blue:
Thanks to Jest Styled Components, Jest is now able to provide the exact information and make our testing experience even more delightful💖 :
Enzyme
enzyme-to-json is necessary to generate snapshots using Enzyme's shallow or full DOM rendering.
It can be enabled globally in the
package.json
:Or imported in each test:
Jest Styled Components works with shallow rendering:
And full DOM rendering as well:
react-testing-library
To generate snapshots with react-testing-library, you can follow the example below:
Theming
In some scenarios, testing components that depend on a theme can be tricky, especially when using Enzyme's shallow rendering.
For example:
The recommended solution is to pass the theme as a prop:
The following function might also help for shallow rendering:
and for full DOM rendering:
Preact
To generate snapshots of Preact components, add the following configuration:
And render the components with preact-render-to-json:
Serializer
The serializer can be imported separately from
jest-styled-components/serializer
. This makes it possible to use this package with specific-snapshot and other libraries.Serializer Options
The serializer can be configured to control the snapshot output.
toHaveStyleRule
The
toHaveStyleRule
matcher is useful to test if a given rule is applied to a component. The first argument is the expected property, the second is the expected value which can be a String, RegExp, Jest asymmetric matcher orundefined
. When used with a negated ".not" modifier the second argument is optional and can be omitted.The matcher supports an optional third
options
parameter which makes it possible to search for rules nested within an At-rule (see media and supports) or to add modifiers to the class selector. This feature is supported in React only, and more options are coming soon.If a rule is nested within another styled-component, the
modifier
option can be used with thecss
helper to target the nested rule.You can take a similar approach when you have classNames that override styles
This matcher works with trees serialized with
react-test-renderer
,react-testing-library
, or those shallow rendered or mounted with Enzyme. It checks the style rules applied to the root component it receives, therefore to make assertions on components further in the tree they must be provided separately (Enzyme's find might help).To use the
toHaveStyleRule
matcher with React Native, change the import statement to:Global installation
It is possible to setup this package for all the tests. For Example: import the library once in the
src/setupTests.js
as follows:...then add the following to
test.config.js
:Working with multiple packages
If Jest Styled Components is not working, it is likely caused by loading multiple instances of
styled-components
. This can happen especially when working with a Lerna monorepo. Starting withstyled-compon[email protected]
, a warning will be logged when multiple instances of it are being included and run as part of the Jest tests. Using[email protected]
and lower with multiple instances will cause a silent error with unexpected results.To debug and fix multiple instances of
styled-components
see the FAQ on "Why am I getting a warning about several instances of module on the page?".Contributing
Please open an issue and discuss with us before submitting a PR.