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

jest-styled-components is breaking with new 5.0.0 styled-components #297

Open
santaclauze opened this issue Jan 17, 2020 · 36 comments
Open

Comments

@santaclauze
Copy link

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?

@ARXChrono
Copy link

That error you see has been resolved when you update jest-styled-components to 7.0.0

@ARXChrono
Copy link

However theres a few other errors occurring for me after upgrading, would be nice to see the changelog to 7.0.0

@pgsandstrom
Copy link

I have upgraded to 7.0.0 and are experiencing the exact samt problem.

@BatuhanW
Copy link

toHaveStyleRule expectations are failing after upgrading styled components to 5 and jest-styled-components to 7.

@SoontirFell
Copy link

@BatuhanW do the failing expects happen to contain modifiers with single quotes, i.e. is it the same issue as #296 ?

@moarwick
Copy link

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>>'

@hutber
Copy link

hutber commented Jan 21, 2020

Having the same issues, sadly

@BatuhanW
Copy link

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

@hamatoyogi
Copy link

hamatoyogi commented Jan 22, 2020

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

@tcodes0
Copy link

tcodes0 commented Jan 25, 2020

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

@quantizor
Copy link
Contributor

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

@Duncan00
Copy link

Thanks. I tried jest-styled-components v6 is working fine with styled-components v4.

@lucianomlima
Copy link

Not working with react-native v0.61.5 and styled-components v5 / jest-styled-components v7.
Get TypeError: global.beforeEach is not a function

@mircoba
Copy link

mircoba commented Feb 6, 2020

@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
Copy link

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

No, i'm not using global installation and I use jest.setupFilesAfterEnv too. I'm try it again and maybe create a repro repo.

@lucianomlima
Copy link

@mirco312312 Thanks! I got working now!

@raurir
Copy link

raurir commented Feb 20, 2020

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"],

@stazrad
Copy link

stazrad commented Mar 18, 2020

@raurir thanks! that solved the TypeError: global.beforeEach is not a function for me 👍

zdmitchell added a commit to iFixit/product-page-components that referenced this issue Mar 30, 2020
This is makes reading the diffs of snapshots easier to read if the diff
is regarding a changed style in a styled component.

Note: a previous version was installed to match our core components
package.json. Installing the newest version leads to a problem described
here: styled-components/jest-styled-components#297
@Soul244
Copy link

Soul244 commented Mar 31, 2020

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.

@PravallikaVinod
Copy link

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

@wdonet
Copy link

wdonet commented Apr 22, 2020

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

@sebas-bytelion
Copy link

Its happend to me, when i use import 'jest-styled-components/native';, any update about it ?

@kdalkafoukis
Copy link

kdalkafoukis commented May 21, 2020

Temporary? workaround for "styled-components": "^5.1.0" and "jest-styled-components": "^7.0.2" is to render the component inside the test.

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');
    });

});

image

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');
    });
});

image

@Tokimon
Copy link

Tokimon commented Jun 5, 2020

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?

@Tokimon
Copy link

Tokimon commented Jun 5, 2020

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' ]

@ghost
Copy link

ghost commented Jun 24, 2020

this was fixed on #302 (v7.0.2) #313 (master)

@noahnu
Copy link
Contributor

noahnu commented Jun 27, 2020

#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) {

@markwoodward23
Copy link

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 babel/babel-preset-env#189 (comment) for a reference of how to split babelrc files into envs.

@Tokimon
Copy link

Tokimon commented Jul 2, 2020

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.

@noahnu
Copy link
Contributor

noahnu commented Jul 2, 2020

On that note, is it better to just remove the class name filtering entirely?

@stephen-boynton
Copy link

stephen-boynton commented Jul 20, 2020

We are having the exact same problem. @noahnu 's fix does not fix the issue for us. We still receive the original error Could neither find styled-components secret internals nor styled-components/lib/models/StyleSheet.js. It is only during testing that this is an issue.

@ghost
Copy link

ghost commented Jul 22, 2020

well this require also a fix from babel plugin side styled-components/babel-plugin-styled-components#276, you can use https://www.npmjs.com/package/@univision/babel-plugin-styled-components that have that fix

@stephen-boynton
Copy link

The fix I was referring to was a fix for the babel plugin.

@BonnieMilian
Copy link

for me worked with this versions:
"styled-components": "^5.2.3"
"jest-styled-components": "^7.0.3"

import '@testing-library/jest-dom/extend-expect'
import 'jest-styled-components'
import { screen } from '@testing-library/react'

// ...

expect(screen.getByTitle('some-title')).toHaveStyleRule('color', 'white')

@phaux
Copy link

phaux commented Sep 5, 2021

I'm not using babel plugin, only jest with ts-jest preset. v4/v6 works. v5/v7 doesn't, I get empty className and no css in snapshot.

@vdsabev
Copy link

vdsabev commented Oct 18, 2021

I had this issue with styled-components@5.3.1 and jest-styled-components@7.0.5. Turns out that in addition to importing jest-styled-components in setupTests.js (which is run once before all tests) I was also importing it in one other test which was breaking all tests.

Removing the second import resolved my issue.

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

No branches or pull requests