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

Styles not found on a component (toHaveStyleRule) #170

Closed
msbober opened this issue Aug 16, 2018 · 32 comments
Closed

Styles not found on a component (toHaveStyleRule) #170

msbober opened this issue Aug 16, 2018 · 32 comments
Labels

Comments

@msbober
Copy link

msbober commented Aug 16, 2018

With the latest enzyme (3.4.1) and jest-styled-components (6.0.0), the toHaveStyleRule assertion is not finding the styles on a component.

Symptoms:

    No style rules found on passed Component

      28 |         .dive()
      29 |         .dive()
    > 30 |     ).toHaveStyleRule('text-align', 'center')
      31 |   })
      32 |

Also visible in snapshots. Before, the snapshot included the style classes definition, e.g.:

.c0 {
  padding-left: 0;
 ...
  display: table-cell;
}

With the latest enzyme, in the snapshot, the className is still there on a component (twice?), but the class definition is missing:

<MyComponent
  centre={false}
  className="c0"
  className="... obnHq"
@MicheleBertoli
Copy link
Member

Hello @msbober, thanks for opening this issue.
The tests are currently passing with enzyme 3.1.4, would you mind providing more information (e.g. the component and the test implementation)?

@wesrice
Copy link

wesrice commented Aug 16, 2018

Fwiw, I'm experiencing the same issue, but cannot provide much debugging information at this time.

jest-styled-components@6.0.1
enzyme@3.4.2

@oreqizer
Copy link

Same here, snapshot's okay, but no styles found using toHaveStyleRule, happening since v6.

jest-styled-components@6.1.0
enzyme@3.4.4

@MicheleBertoli
Copy link
Member

Thank you very much, @wesrice @oreqizer.

Unfortunately, without a non-working example and the tests that are passing is super hard for me to investigate this issue.
Would you be able to provide some code?

@thmsobrmlr
Copy link

I'm running into the issue as well and have been trying to setup a codesandbox with a repro. Can't get the sandbox running with jest + enzyme though. Do you have a codesandbox that I could use as a starter somewhere?

@MicheleBertoli
Copy link
Member

Hey @Thomas88, thanks for your comment.

Codesandbox helps but it's not require, if you could paste the code (of the component and the failing test) here, I will be happy to run it locally.

@msbober
Copy link
Author

msbober commented Aug 21, 2018

At some point the problem just stopped happening for us (enzyme (3.4.1) and jest-styled-components (4.9.0)) without any apparent reason.

Currently we think that in our case it was some weird yarn caching problem. We'll keep an eye for it.

I'd close the issue but it looks like there are others observing the same behaviour.

@thmsobrmlr
Copy link

thmsobrmlr commented Aug 21, 2018

I think I found the pattern that breaks after updating to version 6. It occurs when the styled component is (shallow) rendered by another component (which is the one being tested). Here's an example:

MyComponent.js

import React from 'react';
import styled from 'styled-components';

const Card = styled.div`
  opacity: 1;
`;

const MyComponent = () => (
  <Card></Card>
);

export default MyComponent;

MyComponent.test.js

import React from 'react';
import { shallow } from 'enzyme';

import MyComponent from '../MyComponent';

describe('<MyComponent />', () => {
  it('renders with style rule', () => {
    const wrapper = shallow(<MyComponent />);
    console.log(wrapper.debug());
    expect(wrapper.find('MyComponent__Card')).toHaveStyleRule('opacity', '1');
  });
});

Output

  No style rules found on passed Component

       8 |     const wrapper = shallow(<MyComponent />);
       9 |     console.log(wrapper.debug());
    > 10 |     expect(wrapper.find('MyComponent__Card')).toHaveStyleRule('opacity', '1');
         |                                               ^
      11 |   });
      12 | });
      13 | 

@wesrice
Copy link

wesrice commented Aug 21, 2018

I am experiencing this issue with the same scenario that @Thomas88 is describing.

@MicheleBertoli
Copy link
Member

This is awesome, thanks @Thomas88 @wesrice.
I found the regression, and fixed it in v6.1.1.

@Thomas88 you should run the expectation on wrapper, as opposed to wrapper.find('MyComponent__Card'), because the latter doesn't exist:

describe('<MyComponent />', () => {
  it('renders with style rule', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper).toHaveStyleRule('opacity', '1');
  });
});

@thmsobrmlr
Copy link

How awesome is that. Thanks for the fast fix @MicheleBertoli! All tests are working again.

@jsjoeio
Copy link

jsjoeio commented Sep 19, 2018

@MicheleBertoli

I wasn't sure if I should open another issue or comment here. I'm experiencing the same issue as described previously - No style rules found on passed Component.

Button.styles.js

Here is the styled-component I would like to test.

import styled from 'styled-components'
import { hover } from '../../../styles/_utility/'

export default styled.button`
  cursor: pointer;
  outline: none;
  border: none;
  border-radius: 3px;
  font-size: 14px;
  margin: 0 10px;
  padding: 8px 18px;
  color: ${props => {
    if (props.variant === 'main' && props.color !== 'white') {
      return props.theme.white.main
    } else if (props.color !== 'white') {
      return props.theme[props.color].main
    } else {
      return props.theme.dark.main
    }
  }};
  background-color: ${props => props.theme[props.color][props.variant]};
  ${props => props.hover ? hover(props.selected) : ''}
`

Button.test.js

Here is the test I've written:

/* eslint-env jest */
import React from 'react'
import { shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
import ButtonContainer from './Button.styles'
import theme from '../../../styles/theme'
import 'jest-styled-components'

describe('Button styled-components', () => {
  it('should render a ButtonContainer', () => {
    const wrapper = shallow(<ButtonContainer color='primary' variant='lighter' theme={theme} />)
    expect(wrapper).toHaveStyleRule('color', '#FFD5B7')
  })
})

I've tried it with the wrapper and also the wrapper as JSON with

const tree = toJson(wrapper)
expect(tree).toHaveStyleRule('border', 'none')

Versions

"react": "latest"
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "^3.3.4",
"jest-styled-components": "^6.2.0"

If I can get this to work, I will happily make a video on egghead to share with the community ❤️

Thank you in advance for your time and help!

@MicheleBertoli
Copy link
Member

Hello @jsjoeio, thanks for your comment.
I tried to run your code and it worked.

screen shot 2018-09-22 at 8 06 33 am

Would you be able to provide a non-working repo or sandbox?
Cheers!

@jsjoeio
Copy link

jsjoeio commented Sep 22, 2018

@MicheleBertoli Strange...

Here's a non-working repo: https://github.com/jsjoeio/styles-not-found/tree/master

@MicheleBertoli
Copy link
Member

Thanks for setting up a repo, @jsjoeio.
So the problem is that you are using Styled Components v4.0.0-beta.4-hmr, which is not supported yet by this library.

@jsjoeio
Copy link

jsjoeio commented Sep 23, 2018

Ahhh - that makes sense now. My apologies @MicheleBertoli - I should have checked if v4 was supported before commenting on this issue. Thanks for helping figure out the problem! Really appreciate your help!

@lexanth
Copy link

lexanth commented Sep 28, 2018

In case anyone comes here because they have the same issue, I hit this from having two versions of styled-components in my node_modules (Lerna multimodule with a yarn workspace - there was a hoisted version and a version local to one module).

@lauriejones
Copy link

Thank you @lexanth! I was having the same issue.

@jmacioszek
Copy link

jmacioszek commented Oct 30, 2018

Having this issue as well, this is my component:

interface StyledProps {
  fluid: boolean;
}

const Button = styled(TouchableOpacity)<StyledProps>`
  align-items: center;
  justify-content: center;
  ${({ fluid }: StyledProps) => fluid && { width: '100%' }};
`;

const ButtonText = (styled as any).Text({
  color: #fff,
  fontSize: 16,
});

const GradientButton = ({ testID, onPress, title, fluid = false }: GradientButtonProps) => {
  return (
    <Button fluid={fluid} {...testLabel(testID)} onPress={onPress}>
      <ButtonText>{title}</ButtonText>
    </Button>
  );
};

export default GradientButton;

And here is the test:

let wrapper: ShallowWrapper;
const component = <GradientButton testID={TEST_ID} title={TITLE} onPress={onPressSpy} />;
beforeEach(() => {
  wrapper = shallow(component);
});

describe('<GradientButton />', () => {
  it('renders fluid', () => {
    expect(wrapper).toHaveStyleRule('width', '100%');
  });
});

Which gives me: No style rules found on passed Component

package.json:

    "react": "16.5.1",
    "styled-components": "^3.4.10",
    "react-native": "0.57.1",
    "jest-styled-components": "^6.2.2",

@MicheleBertoli
Copy link
Member

Thanks for your comment, @jmacioszek.

The test says "No style rules found on passed Component" because you are shallow rendering and the children components don't get resolved. If you use mount, the tests will work.
However, they would still fail because you need to see fluid={true}.

I hope this helps.

@greypants
Copy link

greypants commented Dec 11, 2018

For anyone else running into this, my issue was styled-components not being hoisted in my monorepo.

I had dev and peer dependencies misconfigured in a couple packages, so there were two versions being referenced depending what package I was importing from. Check your node_modules folders in each package.

You should only see one copy of styled components hoisted to the root node_modules of of your monorepo.

@Soul244
Copy link

Soul244 commented Mar 6, 2019

Thanks for your comment, @jmacioszek.

The test says "No style rules found on passed Component" because you are shallow rendering and the children components don't get resolved. If you use mount, the tests will work.
However, they would still fail because you need to see fluid={true}.

I hope this helps.

I changed rendering method shallow to mount and it worked. Thanks.

@goodbomb
Copy link

I'm running into the same issue. Not exactly sure what I'm doing wrong here, but here are my files:

import React from 'react';
import styled from 'styled-components';

const Home = styled.div`
    .desktop {
        color: red;
        display: block;
    }
`;

const HomeView = function() {
    return (
        <Home className="home">
            <div className="desktop">The desktop home page!</div>
        </Home>
    );
};

export default HomeView;

Spec File:

import React from 'react';
import { mount } from 'enzyme';
import { HomeView } from './';
import 'jest-styled-components';

describe('Examples', () => {
    it('should check the styles', () => {
        const wrapper = mount(<HomeView />);
        const element = wrapper.find('.desktop');

        expect(element).toHaveStyleRule('color', 'red');
    });
});

In the end I'm getting the error No style rules found on passed Component. Any help would be appreciated.

"enzyme": "3.8.0",
"jest": "24.5.0",
"jest-styled-components": "6.3.1",
"react": "16.7.0",
"react-dom": "16.7.0",
"styled-components": "4.1.3"

@Soul244
Copy link

Soul244 commented Mar 29, 2019

@goodbomb

const Home = styled.div.desktop { color: red; display: block; };

There's no styling for Home component. Error is normal. I think, if you have another styled component, just write like this and write a test for that component:

const Home =  styled.div`
    Home Sytling...
 `;

const Desktop = styled.div`
       color: red;
       display: block;
`;


<Home className="home">
    <Desktop>The desktop home page!</div>
 </Home>

@goodbomb
Copy link

@Soul244 how does one access the styles for nested elements though?

@Soul244
Copy link

Soul244 commented Mar 29, 2019

@goodbomb i updated my answer.

@goodbomb
Copy link

goodbomb commented Mar 29, 2019

Damn, so you can't use the cascading styles aspect of Styled-Components? That's one of the big benefits I see for using it. You only need to style the top-level component, and then use normal cascading CSS selectors for the child elements. Having to create new components for every styled element adds a lot of verbosity to the styles and the file itself.

@Soul244
Copy link

Soul244 commented Mar 29, 2019

If you need a general component which created with styled component, just write that in a file and export it. I am not sure, what you need exactly?

A hover example:

const Home =  styled.div`
    Home Sytling...
 `;

const Desktop = styled.div`
 ${Home}:hover &(
       color: red;
       display: block;
)
`;
<Home className="home">
    <Desktop>The desktop home page!</div>
 </Home>

I am sure, Styled Components is ten times more better than css. You can use all css selectors and other things in Styled Components. Docs: https://www.styled-components.com/docs

this is my mail address: hasancangedik@hotmail.com. I can help you, if you have a problem about styled-components.

@goodbomb
Copy link

We're using the Cascade approach to styling. So instead of creating a new component for each element we want to style (like you're doing in your examples), we're using cascade selectors (like you do in normal CSS files).

Instead of this:

const Home =  styled.div`
    ...Home styles...
`;

const Desktop = styled.div`
    ...Desktop styles...
`;

<Home className="home">
    <Desktop>The desktop home page!</div>
 </Home>

We're doing this:

const Home =  styled.div`
    ...Home styles...
    
    .desktop {
        ...desktop styles...
    }
`;

<Home className="home">
    <div className="desktop">The desktop home page!</div>
 </Home>

Our approach makes for less verbosity and is much closer to normal CSS. I take it this library doesn't support that approach, @Soul244 ?

@Soul244
Copy link

Soul244 commented Mar 29, 2019

No, you can use your approach. I tried and couldn't find a problem. Could you write result of this code?

const element = wrapper.find('.desktop');
console.log(element)

Probably, toHaveStyleRule function is just working for styled components. You need to test it with another function. Maybe this: "toHaveProperty".

@goodbomb
Copy link

I did this:

const element = wrapper.find('.desktop');
console.log(element)

Output only gives me this: ReactWrapper {}

Changing to console.log(element.debug()); gives this:

console.log src/app/home/HomeView.spec.js:14
    <div className="desktop">
      The desktop home page!
    </div>

@Soul244
Copy link

Soul244 commented Mar 29, 2019

I can't help you about this problem, sorry.

But i found what is your problem with your approach. Styled Components creates a unique class name for every component to prevent css problems with other html elements. But when you create a component like you do, it's creating a normal css class name. For example:

const Home =  styled.div`
    ...Home styles...
    
    .desktop {
        ...desktop styles...
    }
`;

<Home className="home">
    <div className="desktop">The desktop home page!</div>
 </Home>

in this code, Home has a unique class name. You can see the name on inspect. But child component class name is not unique. That is the problem. So you need to create new styled component for every element.

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

No branches or pull requests