Search code examples
reactjsjestjsemotion

toHaveStyleRule cant find style defined by parent


I'm writing some tests for my component and have this test that works fine:

  test('should add padding', () => {
    const element = renderWithTheme(
      <List p={2}>
        <ListItem>1</ListItem>
        <ListItem>2</ListItem>
      </List>
    )
    expect(element).toHaveStyleRule('padding', theme.spacing(2))
  })

In my next testcase, I want to check styling on the children so I made this test:

  test('should add spacing to children', () => {
    const element = renderWithTheme(
      <List spacing={2}>
        <ListItem>1</ListItem>
        <ListItem>2</ListItem>
      </List>
    )
    element.childNodes.forEach((child) => {
      expect(child).toHaveStyleRule('padding', theme.spacing(2))
    })
  })

This test gives me the error Property not found: padding

If I edit the code to check for styling with getComputedStyle it works fine

const computedStyles = window.getComputedStyle(child)
expect(computedStyles.padding).toEqual(theme.spacing(2))

But I want all of the functionality that toHaveStyleRule offers, is there a way to make this work?

I think my main issue is that the parent component sets style, since it works when i apply style to the ListItem directly

const ListRoot = styled.ul<{ ownerState: Partial<ListProps> }>(
  ({ theme, ownerState: { columnSpacing, rowSpacing, spacing } }) => ({
    padding: 0,
    listStyle: 'none',
    '& li': {
       padding: theme.spacing(spacing),
       Some more style for the nested li
    },
  })
)

Solution

  • I ended up using target specified in the DOCS. I tested it before but didn't seem too work back then. So I select the parent that has the style specified and add a target: "selector" to point to the specific style. It also works with media queries now

      test('should add spacing to children', () => {
        const element = renderWithTheme(
          <List spacing={2}>
            <ListItem>1</ListItem>
            <ListItem>2</ListItem>
          </List>
        )
    
        expect(element).toHaveStyleRule('padding', theme.spacing(2), {
          target: 'li',
          media: theme.breakpoint.up('md'),
        })
      })