jest-styled-components icon indicating copy to clipboard operation
jest-styled-components copied to clipboard

Test if nth-child is receiving styles

Open jdwillemse opened this issue 7 years ago • 2 comments

I don't know if this is a bug, or if I just can't find the answer on google.

I'm trying to see if a style rule is applied to the nth-child() of an element. I'm always getting the base style rather than the modified style which is based on the element's location in the tree.

This is my test:

  it('should render correctly', () => {
    const wrapper = render(<Rating rating={3} />);
    expect(toJson(wrapper.find('button:nth-child(1) svg'))).toHaveStyleRule('fill', '#91c11e');
    expect(toJson(wrapper.find('button:nth-child(1) svg'))).toMatchSnapshot();
  });

The test fails with:

    "Value mismatch for property 'fill'"

    Expected
      "fill: #91c11e"
    Received:
      "fill: #eceae6"

The snapshot is:

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Rating should render correctly 1`] = `
.c0 {
  width: 16px;
  height: 16px;
  fill: #eceae6;
  pointer-events: none;
}

.c1:nth-child(-n + 3) .c0 {
  fill: #91c11e;
}

<svg
  class="c0"
  xmlns="http://www.w3.org/2000/svg"
>
  <use
    href="#star"
  />
</svg>
`;

Any help would be appreciated

jdwillemse avatar Mar 16 '19 17:03 jdwillemse

Hey @jdwillemse! You need to assert the style rule on the styled component that has these styles instead of finding the element that should be styled(In your case it should be just wrapper). You can achieve this by passing a modifier into the .toHaveStyleRule call. I haven't tested the code below, but something like this should work:

expect(toJson(wrapper)).toHaveStyleRule('fill', '#91c11e', {
 modifier: 'button:nth-child(1) svg',
});

Just be sure that your selector in styled-component code is exactly the same as in the modifier option.

KITSMarkShulhin avatar May 24 '19 11:05 KITSMarkShulhin

For anyone else looking for an equivalent without Enzyme, I've used, @emotion/styled with jest, react-test-renderer (instead of Enzyme, as used here):

Here's how you'd do it there.

import renderer from 'react-test-renderer';
import Rating from './path/to/rating';
import { matchers } from '@emotion/jest';   // I've used @emotion/styled (https://emotion.sh/docs/@emotion/jest)

expect.extend(matchers); // This is necessary

it('should render correctly', () => {
    const wrapper = renderer.create(<Rating rating={3} />).toJSON();
    expect(wrapper).toHaveStyleRule('fill', '#91c11e', {
         target: 'button:nth-child(1) svg'
    });
});

Very similar to the enzyme one, slightly different syntax.

jayantasamaddar avatar Oct 16 '22 19:10 jayantasamaddar