Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
jest-styled-components
Advanced tools
jest-styled-components is a Jest utility for testing styled-components. It provides custom matchers to test the styles applied to your components, making it easier to ensure that your styled-components are rendered correctly.
toHaveStyleRule
The `toHaveStyleRule` matcher allows you to check if a specific style rule is applied to a component. In this example, it verifies that the `Button` component has a `color` style rule set to `red`.
const styled = require('styled-components').default;
const { toHaveStyleRule } = require('jest-styled-components');
expect.extend({ toHaveStyleRule });
const Button = styled.button`
color: red;
`;
// Test
it('should have red color', () => {
const wrapper = mount(<Button />);
expect(wrapper).toHaveStyleRule('color', 'red');
});
toMatchSnapshot
The `toMatchSnapshot` matcher allows you to take a snapshot of the rendered component and compare it to a previously saved snapshot. This is useful for ensuring that the component's styles have not changed unexpectedly.
const styled = require('styled-components').default;
const { toMatchSnapshot } = require('jest-styled-components');
expect.extend({ toMatchSnapshot });
const Button = styled.button`
color: red;
`;
// Test
it('should match the snapshot', () => {
const wrapper = mount(<Button />);
expect(wrapper).toMatchSnapshot();
});
jest-emotion is a Jest utility for testing Emotion styled components. It provides custom matchers to test the styles applied to your components, similar to jest-styled-components. However, it is specifically designed for Emotion, another popular CSS-in-JS library.
enzyme-to-json is a utility for converting Enzyme wrappers to a format compatible with Jest snapshots. While it does not provide style-specific matchers, it can be used in conjunction with Enzyme to test the rendered output of styled-components.
react-testing-library is a lightweight solution for testing React components. It focuses on testing components from the user's perspective and can be used with jest-styled-components to test styled-components. It does not provide style-specific matchers but can be used to test the overall behavior and appearance of 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.
yarn add --dev jest-styled-components
import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'
const Button = styled.button`
color: red;
`
test('it works', () => {
const tree = renderer.create(<Button />).toJSON()
expect(tree).toMatchSnapshot()
expect(tree).toHaveStyleRule('color', 'red')
})
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:
import styled from 'styled-components'
const Button = styled.button`
color: red;
`
Which we cover with the following test:
import React from 'react'
import renderer from 'react-test-renderer'
test('it works', () => {
const tree = renderer.create(<Button />).toJSON()
expect(tree).toMatchSnapshot()
})
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:
const Button = 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 just 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:
- Snapshot
+ Received
+.c0 {
+ color: green;
+}
+
<button
- className="sc-bdVaJa rOCEJ"
+ className="c0"
/>
This is the resulting snapshot:
exports[`it works 1`] = `
.c0 {
color: green;
}
<button
className="c0"
/>
`;
Now, suppose we change the color again to blue:
const Button = styled.button`
color: blue;
`
Thanks to Jest Styled Components, Jest is now able to provide the exact information and make our testing experience even more delightful 💖:
- Snapshot
+ Received
.c0 {
- color: green;
+ color: blue;
}
<button
className="c0"
/>
enzyme-to-json is necessary to generate snapshots using Enzyme's shallow or full DOM rendering.
yarn add --dev enzyme-to-json
It can be enabled globally in the package.json
:
"jest": {
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}
Or imported in each test:
import toJson from 'enzyme-to-json'
// ...
expect(toJson(wrapper)).toMatchSnapshot()
Jest Styled Components works with shallow rendering:
import { shallow } from 'enzyme'
test('it works', () => {
const wrapper = shallow(<Button />)
expect(wrapper).toMatchSnapshot()
})
And full DOM rendering as well:
import { mount } from 'enzyme'
test('it works', () => {
const wrapper = mount(<Button />)
expect(wrapper).toMatchSnapshot()
})
In some scenarios, testing components that depend on a theme can be tricky, especially when using Enzyme's shallow rendering.
For example:
const Button = styled.button`
color: ${props => props.theme.main};
`
const theme = {
main: 'mediumseagreen',
}
The recommended solution is to pass the theme as a prop:
const wrapper = shallow(<Button theme={theme} />)
The following function might also help for shallow rendering:
const shallowWithTheme = (tree, theme) => {
const context = shallow(<ThemeProvider theme={theme} />)
.instance()
.getChildContext()
return shallow(tree, { context })
}
const wrapper = shallowWithTheme(<Button />, theme)
and for full DOM rendering:
const mountWithTheme = (tree, theme) => {
const context = shallow(<ThemeProvider theme={theme} />)
.instance()
.getChildContext()
return mount(tree, {
context,
childContextTypes: ThemeProvider.childContextTypes // Needed so child components receive the theme prop
})
}
To generate snapshots of Preact components, add the following configuration:
"jest": {
"moduleNameMapper": {
"^react$": "preact-compat"
}
}
And render the components with preact-render-to-json:
import React from 'react'
import styled from 'styled-components'
import render from 'preact-render-to-json'
import 'jest-styled-components'
const Button = styled.button`
color: red;
`
test('it works', () => {
const tree = render(<Button />)
expect(tree).toMatchSnapshot()
})
The snapshots will contain
class
instead ofclassName
. Learn more.
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
.
const Button = 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', () => {
const tree = renderer.create(<Button />).toJSON()
expect(tree).toHaveStyleRule('color', 'red')
expect(tree).toHaveStyleRule('border', '0.05em solid black')
expect(tree).toHaveStyleRule('cursor', 'pointer')
expect(tree).toHaveStyleRule('opacity', undefined) // equivalent of the following
expect(tree).not.toHaveStyleRule('opacity', expect.any(String))
})
test('it applies styles according to passed props', () => {
const tree = renderer.create(<Button disabled transparent />).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 (media) or to add modifiers to the class selector. This feature is supported in React only, and more options are coming soon.
const Button = styled.button`
@media (max-width: 640px) {
&:hover {
color: red;
}
}
`
test('it works', () => {
const tree = renderer.create(<Button />).toJSON()
expect(tree).toHaveStyleRule('color', 'red', {
media: '(max-width:640px)',
modifier: ':hover',
})
})
If a rule is nested within another styled-component, the modifier
option can be used with the css
helper to target the nested rule.
const Button = styled.button`
color: red;
`
const ButtonList = styled.div`
display: flex;
${Button} {
flex: 1 0 auto;
}
`
import { css } from 'styled-components';
test('nested buttons are flexed', () => {
const tree = renderer.create(<ButtonList><Button /></ButtonList>).toJSON()
expect(tree).toHaveStyleRule('flex', '1 0 auto', {
modifier: css`${Button}`,
})
})
This matcher works with trees serialized with react-test-renderer
and shallow renderered 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:
import 'jest-styled-components/native'
It is possibile to setup this package for all the tests using the setupTestFrameworkScriptFile option:
"jest": {
"setupTestFrameworkScriptFile": "./setupTest.js"
}
And import the library once in the setupTest.js
as follows:
import 'jest-styled-components'
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-components@3.2.0
, a warning will be logged when multiple instances of it are being included and run as part of the Jest tests. Using styled-components@3.1.6
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?".
Please open an issue and discuss with us before submitting a PR.
FAQs
Jest utilities for Styled Components
The npm package jest-styled-components receives a total of 619,663 weekly downloads. As such, jest-styled-components popularity was classified as popular.
We found that jest-styled-components demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.