jest-styled-components
jest-styled-components copied to clipboard
jest-styled-components is breaking with new 5.0.0 styled-components
We just udpated to styled-components 5.0.0 and our snapshot tests are breaking:
> 3 | import 'jest-styled-components';
Could neither find styled-components secret internals nor styled-components/lib/models/StyleSheet.js
I can see that you had the pre 5.0.0 your package.json.
Is this expected?
That error you see has been resolved when you update jest-styled-components to 7.0.0
However theres a few other errors occurring for me after upgrading, would be nice to see the changelog to 7.0.0
I have upgraded to 7.0.0 and are experiencing the exact samt problem.
toHaveStyleRule expectations are failing after upgrading styled components to 5 and jest-styled-components to 7.
@BatuhanW do the failing expects happen to contain modifiers with single quotes, i.e. is it the same issue as #296 ?
yup, styled-components 5.0 + jest-styled-components 7.0 + Typescript also not happy:
error TS2339: Property 'toHaveStyleRule' does not exist on type 'JestMatchersShape<Matchers<void, HTMLElement>, Matchers<Promise<void>, HTMLElement>>'
Having the same issues, sadly
@BatuhanW do the failing expects happen to contain modifiers with single quotes, i.e. is it the same issue as #296 ?
I don't think. Because we have singleQuote set to false on prettierrc.
I'm also experiencing issues for tests that used to work on v4.4...
places where toHaveStyleRule is used are generating:
Error: No style rules found on passed Component
related to this issue
Can confirm latest is broken with styled-components 4.4.1. Does a version rollback fix?
edit: can confirm version v6.3.4 works with styled-components 4.4.1
@Thomazella yes we dropped support for v4 with the v7 release. The internals changed a lot between v4 and v5 and the library needed incompatible updates.
Thanks. I tried jest-styled-components v6 is working fine with styled-components v4.
Not working with react-native v0.61.5 and styled-components v5 / jest-styled-components v7.
Get TypeError: global.beforeEach is not a function
@lucianomlima are you using global installation approach?
Note the deprecation warning here: https://jestjs.io/docs/en/configuration#setupfilesafterenv-array
When importing from a file referenced via jest.setupFilesAfterEnv its working for me with v5/v7.
@lucianomlima are you using global installation approach?
Note the deprecation warning here: https://jestjs.io/docs/en/configuration#setupfilesafterenv-array
When importing from a file referenced via
jest.setupFilesAfterEnvits working for me with v5/v7.
No, i'm not using global installation and I use jest.setupFilesAfterEnv too. I'm try it again and maybe create a repro repo.
@mirco312312 Thanks! I got working now!
thanks @mirco312312 - since it took me more than a few minutes to solve, here was the diff in my package.json that worked:
replaced: "setupFiles": ["./spec/setupTests.js"],
with: "setupFilesAfterEnv": ["<rootDir>/spec/setupTests.js"],
@raurir thanks! that solved the TypeError: global.beforeEach is not a function for me 👍
after two months, the problem is still existing. I have to use styled-components v4.4.1 and jest-styled-components 6.3.3 due to this problem.
import 'jest-styled-components';
Could neither find styled-components secret internals
styled-components - 4.4.1 and jest-styled-components - 7.0.2
Can anyone help me to solve this error
I can confirm that for me it is working with this config:
- "styled-components": "^4.3.2"
- "jest-styled-components": "^6.3.4",
...🤔 @PravallikaVinod , try these versions or those combinations mentioned at comments above
Its happend to me, when i use import 'jest-styled-components/native';, any update about it ?
Temporary? workaround for "styled-components": "^5.1.0" and "jest-styled-components": "^7.0.2" is to render the component inside the test.
- reference https://styled-components.com/docs/tooling#tohavestylerule
- I used react-test-renderer but I tested it for enzyme
failing test
import React from 'react';
import renderer from 'react-test-renderer'
import 'jest-styled-components';
import styled from 'styled-components'
const Button = styled.button`
color: red;
`
describe('Button', () => {
const app = renderer.create(<Button />).toJSON()
it('Button has red color', () => {
expect(app).toHaveStyleRule('color', 'red');
});
});

workable test
import React from 'react';
import renderer from 'react-test-renderer'
import 'jest-styled-components';
import styled from 'styled-components'
const Button = styled.button`
color: red;
`
describe('Button', () => {
it('Button has red color', () => {
const app = renderer.create(<Button />).toJSON()
expect(app).toHaveStyleRule('color', 'red');
});
});

I also have this problem as well using react-test-renderer and the latest versions:
"jest-styled-components": "^7.0.2",
"react-test-renderer": "16.13.1",
"styled-components": "^5.1.1",
I have tried the various suggested solutions above, but nothing have helped so far. Any news on any official solution?
So I had a look under the hood and I found out why the test were breaking.
TL;DR - The solution for now
Configure your babel-plugin-styled-components to use static class names by activating ssr: true, like so:
[
'babel-plugin-styled-components',
{ ssr: true }
]
The analysis
The culprit is that you are directly reliant on having static class names witch are determined by a filtering on the classNames:
const staticClassNames = classNames.filter(x => /^(\w+(-|_))?sc-/.test(x));
So the this filter extracts any static class names (hence the name) like:
something-sc-xxx or something_sc-xxx or sc-xxx
However if you don't use static class names, the whole check fails since the getModifiedClassName will never be called.
return classNames.some(className =>
staticClassNames.some(staticClassName =>
selectors.includes(
getModifiedClassName(
className,
staticClassName,
options.modifier
).replace(/['"]/g, '"')
)
)
);
In my configuration none of my styled-components class names have this prefix, since my ssr: false in my babel-plugin-styled-components options:
[ 'Tab__TabElement-gNeteQ', 'fjgULR', 'Tab', '', 'active' ]
and with ssr: true, we see I now have the correct class name (the first one):
[ 'Tab__TabElement-sc-16mr2vi-1', 'cQclop', 'Tab', '', 'active' ]
I don't think that this direct dependency on the static class names are intentional as that would break the very nature of ssr being optional. And any mention of having to have ssr activated is missing from the documentation.
So... This seems like a bug and the check has to be redone somehow to not be directly reliant on the static class names.
If you want I can try and look into doing a fix. Let me know.
Update
Even with ssr: true I still have some components that does not have the sc- prefix and as such cannot be tested with toHaveStyleRule. A class name list like so:
[ 'Image__Img-k1inrs-0', 'gNQhls', 'Image', '', 'img' ]
this was fixed on https://github.com/styled-components/jest-styled-components/pull/302 (v7.0.2) https://github.com/styled-components/jest-styled-components/pull/313 (master)
#302 does not fix the issue. jest-styled-components looks for the presence of "sc-" anywhere in the component id. babel-plugin-styled-components does not guarantee that the component id will contain the "sc-" substring.
The issue is that babel-plugin-styled-components only applies the "sc-" prefix if it detects the component ID has an invalid css classname, specifically whether it is prefixed by a digit.
Temporarily fixed in my project via patch-package and the following patch for version 1.10.7 which modifies the getComponentId function to ensure it contains "sc-":
diff --git a/node_modules/babel-plugin-styled-components/lib/visitors/displayNameAndId.js b/node_modules/babel-plugin-styled-components/lib/visitors/displayNameAndId.js
index b67a1c8..2b41702 100644
--- a/node_modules/babel-plugin-styled-components/lib/visitors/displayNameAndId.js
+++ b/node_modules/babel-plugin-styled-components/lib/visitors/displayNameAndId.js
@@ -127,7 +127,8 @@ var getNextId = function getNextId(state) {
var getComponentId = function getComponentId(state) {
// Prefix the identifier with a character because CSS classes cannot start with a number
- return `${(0, _prefixDigit.default)(getFileHash(state))}-${getNextId(state)}`;
+ var componentId = `${(0, _prefixDigit.default)(getFileHash(state))}-${getNextId(state)}`;
+ return componentId.indexOf('sc-') >= 0 ? componentId : `sc-${componentId}`;
};
var _default = function _default(t) {
This does seem to stem from an issue in babel-plugin-styled-components for us - removing it does fix the issue. To achieve this while preserving prod behaviour we've split the .babelrc file into envs, not running babel-plugin-styled-components in test mode.
See https://github.com/babel/babel-preset-env/issues/189#issuecomment-284466362 for a reference of how to split babelrc files into envs.
I concur with @noahnu that the problem resides in the fact that not all class names are being prefixed by sc- (I did not make the link with the digit in the class name so thank you for the clarification).
And I also agree that a correction has to be done in babel-plugin-styled-component since it is a bit inconsistent right now.
But the questions is if it is logical that for jest-style-components to find any class names any styled-component class name HAVE to contain sc-? I guess it makes it easier to determine styled-components class names, and as such improve performance, but it makes it less flexible. And (at least what I have seen) the documentation does not clearly state that ssr has to be activated for it to work.
On that note, is it better to just remove the class name filtering entirely?