styled-components / jest-styled-components

🔧 💅 Jest utilities for Styled Components
MIT License
1.58k stars 145 forks source link

How to test styled components with `<GlobalStyle />`? #292

Open yuuta1999 opened 4 years ago

yuuta1999 commented 4 years ago

I created my blog with styled-components and everything worked perfectly. I think testing will help me cover all the errors and bugs that I didn't see, so I decided to test the whole website. But I had troubles from the beginning. Every code examples demonstrated testing on pass-props components, like this:

const Button = styled.button`
  background: ${props => props.primary ? '#fff' : '#000'};
  color: ${props => props.primary ? '#000' : '#fff'}; 
`

and its test will look like this:

test('it applies default styles', () => {
  const tree = renderer.create(<Button />).toJSON()
  expect(tree).toHaveStyleRule('color', 'red')
  expect(tree).toHaveStyleRule('border', '0.05em solid black')
  expect(tree).toHaveStyleRule('cursor', 'pointer')
  expect(tree).not.toHaveStyleRule('opacity') // equivalent of the following two
  expect(tree).not.toHaveStyleRule('opacity', expect.any(String))
  expect(tree).toHaveStyleRule('opacity', undefined)
})

test('it applies styles according to passed props', () => {
  const tree = renderer.create(<Button disabled transparent />).toJSON()
  expect(tree).toHaveStyleRule('border', expect.stringContaining('transparent'))
  expect(tree).toHaveStyleRule('cursor', undefined)
  expect(tree).toHaveStyleRule('opacity', '.65')
})

My whole codebase is too different from these examples. For instance:

// Button.jsx
const Button = styled.button`
  color: var(--Button--Color);
  background: var(--Button--Background);
`
// GlobalStyle.jsx
const GlobalStyle = createGlobalStyle`
  --Button--Color: ${props => props.mode === 'light' ? '#fff' : '#000};
  --Buton--Background: ${props => props.mode === 'light' ? "#000" : "#fff"};
`

How can I test styled-components in this situation? Every comments are appreciated to me.

Steveeeie commented 4 years ago

I would just assert that Button has the correct variable name applied:

expect(tree).toHaveStyleRule('color', 'var(--Button--Color)')

And test GlobalStyle separately for the actual colour value. It is probably easiest to use snapshot testing for createGlobalStyle as it creates multiple styling rules. Somebody may be able to offer an alternative solution.

It is also best practice to wrap global CSS variables in :root:

// GlobalStyle.jsx
const GlobalStyle = createGlobalStyle`
  :root{
    --Button--Color: ${props => props.mode === 'light' ? '#fff' : '#000};
    --Buton--Background: ${props => props.mode === 'light' ? "#000" : "#fff"};
  }
`