When using the latest version alongside babel-plugin-styled-components, the toHaveStyleRule matcher always fails ("No style rules found on passed Component").
This issue seems to have been caused by this commit: https://github.com/styled-components/jest-styled-components/commit/8c2ea4a0a8789e11707e7f18e76b811e0d70c4c0#diff-4eed74593d3d8efde6a0959c9c35119bR71
Specifically, this line assumes classnames will have a sc- prefix which is not present:
const staticClassNames = classNames.filter(x => x.startsWith("sc-"));
(similar issue to #285)
I have the same issue using @testing-library/react with babel-plugin-styled-components.
โฏ npm ls babel-plugin-styled-components jest jest-styled-components @testing-library/react @testing-library/react-dom
[email protected]
โโโ @testing-library/[email protected]
โโโ [email protected]
โโโฌ [email protected]
โ โโโ [email protected]
โโโฌ [email protected]
โโโ [email protected]
import styled from 'styled-components/macro';
const MyComponent = styled.div`
-webkit-text-stroke: 1px white;
cursor: pointer;
`;
test('it works', () => {
const { container } = render(<MyComponent />);
const component = container.firstChild;
expect(component).toHaveStyleRule('-webkit-text-stroke', '1px white');
expect(component).toHaveStyleRule('cursor', 'pointer');
});
Result:
โ it works
No style rules found on passed Component
99 | const component = container.firstChild;
100 |
> 101 | expect(component).toHaveStyleRule('-webkit-text-stroke', '1px white');
| ^
102 | expect(component).toHaveStyleRule('cursor', 'pointer');
103 | });
104 |
I don't think that sc- filter is at fault here, as removing it does not change things. Going deeper, it seems that in certain situations, the stylesheet is empty (i.e. if you dig into __PRIVATE__.masterSheet.tag.tag.element.sheet).
Not yet sure where the culprit lies, but I do know that in my case, simply changing where the component is rendered (i.e. moving it into the test itself, instead of at the top level ... yeah ๐คทโโ ) makes it work well again.
Update: I now think my comment above is probably not relevant for this issue, as I've tracked down the source of my errors. Specifically, this is new: https://github.com/styled-components/jest-styled-components/blob/master/src/index.js#L5. We used to reuse rendered components in multiple tests (I guess that's a bit of an anti-pattern anyway), but now there's beforeEach resetStyleSheet.
I can confirm that this issue is present, after updating styled-components to v5 and jest-styled-components to v7 (with babel-plugin-styled-components v1.10.6). Worked fine before!
As far as I understand this line, that was introduced with the following commit.
It filters classes to those starting with sc-:
const staticClassNames = classNames.filter(x => x.startsWith("sc-"));
Unfortunately if your project is bootstrapped with Create React App, and you cannot simply add babel-plugin-styled-components you have to use Babel Macro instead eg:
import styled from 'styled-components/macro'
that change class names from sc-<hash> to styled__<ComponentName>-sc-<hash>
A quickfix for that I suggest here, is to change this line in toHaveStyleRule.js:71:
const staticClassNames = classNames.filter(x => x.startsWith("sc-"));
to filter not only starting with sc- but generally including that substring:
const staticClassNames = classNames.filter(x => x.includes("sc-"));
It works properly for both new setup (styled-components to v5 and jest-styled-components to v7) as well as older one.
Setting the ssr and displayName plugin parameters to false helped me during testing.
["babel-plugin-styled-components", { ssr: false, displayName: false }]
@weyheyhey is there a way to apply this setting just to my test folder? I've tried all the tricks I know with .babelrc but can't get my tests to not apply the root .babelrc config. Basically, I want displayName to be enabled during development, but disabled for tests.
@visoft you can try something like that in babel.config.js
```
module.exports = (api) => {
const isTest = api.env("test");
// You can use isTest to determine what presets and plugins to use.
const plugins = [
["babel-plugin-styled-components", { ssr: !isTest, displayName: !isTest }]
];
return {
// ...
};
};
Above fix seems to work, but now .find('DisplayName') does not work, so importing and doing .find(DisplayName) is now needed instead. ๐
@stefee Is the plan to get this working without such fixes or should I proceed with my project to try these workarounds? Would hope there'd be no breaking changes ๐ค
@mulholio
Iโm not the maintainer of this project, sorry.
As a alternative fix, I submitted https://github.com/styled-components/babel-plugin-styled-components/issues/268 to babel-plugin-styled-components that makes sure all component IDs are prefixed sc-
The correct solution depends on the how styled-components should work.
My team is experiencing this issue as well for the tests on our design system as we upgrade to Styled Components V5. Tests were working fine just before the upgrade.
I am also experiencing this issue and found that coping the change @robilars-amazon suggests in styled-components/babel-plugin-styled-components#268 didn't actually fix the issue for me.
I have used the workaround suggested by @weyheyhey to disable "displayName" when running tests and found it works in my case.
Thanks for taking care of this @probablyup ! Excited to see next release ship.
It's still not working for me with [email protected], [email protected], and [email protected] :(
Same here have also tried upgrading to v5 again today (with jest-styled-components v7) but also still run into this problem.
Me too, upgraded to v5 and had this issue pop up.
@visoft you can try something like that in
babel.config.jsmodule.exports = (api) => { const isTest = api.env("test"); // You can use isTest to determine what presets and plugins to use. const plugins = [ ["babel-plugin-styled-components", { ssr: !isTest, displayName: !isTest }] ]; return { // ... }; };
If you're using create-react-app and the babel macro (import styled from "styled-components/macro";), you can create a .babel-plugin-macrosrc.js (https://styled-components.com/docs/tooling#experimental-config) in your project root with:
const isTest = process.env.TEST === "true";
module.exports = {
styledComponents: {
ssr: !isTest,
displayName: !isTest,
},
};
and run your test script with TEST=true in front of it. eg. TEST=true react-scripts test.
Most helpful comment
It's still not working for me with
[email protected],[email protected], and[email protected]:(