jest-styled-components: toHaveStyleRule does not work with babel-plugin-styled-components

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)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 19
  • Comments: 20 (2 by maintainers)

Commits related to this issue

Most upvoted comments

It’s still not working for me with styled-components@5.1.0, jest-styled-components@7.0.2, and babel-plugin-styled-components@1.10.7 😦

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!

Same here have also tried upgrading to v5 again today (with jest-styled-components v7) but also still run into this problem.

@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 {
    // ...
  };
};

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.

Setting the ssr and displayName plugin parameters to false helped me during testing.

["babel-plugin-styled-components", { ssr: false, displayName: false }]

This is still an issue on:

"jest-styled-components": "7.0.8",
"styled-components": "5.3.1",
"babel-plugin-styled-components": "2.0.7",
"@babel/core": "7.17.9"

And I cannot disable displayName for the babel plugin as we use it in testing

@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 {
    // ...
  };
};

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.

Thanks for taking care of this @probablyup ! Excited to see next release ship.

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.

Above fix seems to work, but now .find('DisplayName') does not work, so importing and doing .find(DisplayName) is now needed instead. 😕

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.