Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

toHaveStyleRule does not work with babel-plugin-styled-components #290

Closed
joshjg opened this issue Dec 10, 2019 · 20 comments · Fixed by #302
Closed

toHaveStyleRule does not work with babel-plugin-styled-components #290

joshjg opened this issue Dec 10, 2019 · 20 comments · Fixed by #302

Comments

@joshjg
Copy link

joshjg commented Dec 10, 2019

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: 8c2ea4a#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)

@esetnik
Copy link

esetnik commented Dec 10, 2019

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
frontend@1.1.13
├── @testing-library/react@9.3.2
├── jest-styled-components@7.0.0-beta.2
├─┬ react-scripts@3.2.0
│ └── jest@24.9.0
└─┬ styled-components@5.0.0-rc.2
  └── babel-plugin-styled-components@1.10.6
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 |

@joshjg joshjg changed the title Does not work with babel-plugin-styled-components toHaveStyleRule does not work with babel-plugin-styled-components Dec 10, 2019
@jure
Copy link

jure commented Jan 14, 2020

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.

@almightybruce
Copy link

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!

@maciejtatol
Copy link

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.

@afflicted-cat
Copy link

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

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

@visoft
Copy link

visoft commented Jan 16, 2020

@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.

@afflicted-cat
Copy link

afflicted-cat commented Jan 17, 2020

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

@stefee
Copy link
Member

stefee commented Jan 26, 2020

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

@mulholo
Copy link

mulholo commented Jan 29, 2020

@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 🤞

@stefee
Copy link
Member

stefee commented Jan 29, 2020

@mulholio
I’m not the maintainer of this project, sorry.

@robilars-amazon
Copy link

As a alternative fix, I submitted styled-components/babel-plugin-styled-components#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.

@marcod1419
Copy link

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.

@georgewilde
Copy link

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.

quantizor pushed a commit that referenced this issue Apr 9, 2020
* Fix support classes with displayName prefix

Closes #290 #294

* simplify regexp on get classname

* add unit test for custom prefix/display name
@robilars-amazon
Copy link

robilars-amazon commented Apr 9, 2020

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

@stonebk
Copy link

stonebk commented Apr 20, 2020

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 :(

@joaogarin
Copy link

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

@VarunBalakrishna
Copy link

Me too, upgraded to v5 and had this issue pop up.

@VarunBalakrishna
Copy link

VarunBalakrishna commented Jun 24, 2020

@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.

@andreiciceu
Copy link

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

@daltonwignall
Copy link

For anyone else still struggling with this issue. The commonly recommended solution below "worked"..

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

Though we use the displayName property semi-frequently within our tests so this caused breaking issues elsewhere. Given we wanted to persist the ability to find elements based on the displayName we instead opted to downgrade to v7.0.0-beta.1 (prior to the version introducing the issue) of this library which led to green across the board again. Downgrading isn't necessarily my favorite thing to do, but it persisted the same functionality we were using prior and didn't require broader code changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.