How to test a Component’s CSS styles with React-Testing-Library (RTL) and Styled Components.

Ilya Zykin
3 min readApr 17, 2019

--

In my current project I use

If you check RTL documentation and examples you see very simple getBy* selectors for testing a code.

https://testing-library.com/docs/dom-testing-library/api-queries

The most ugly thing here is ByTestId

The author suppose that you could add some specific IDs in your code specially for tests. What is just unacceptable. Your code has to know just nothing about your tests and you MUST avoid pollution of your code with any tests-specific identifiers.

<input data-testid=”username-input” />

Time to time you have to select and check components which do not have any specific identifiers. For example, it may be a wrapper for a main part of a content. However, usually these wrappers have a class name and you can use it to select an element from DOM tree. Like that:

<ContentWrapper className="wrapperClass">
<ContentComponent />
</ContentWrapper>

But what if you use Styled Components? In this case you will not know a name of the wrapper component, it will be a hashed class name.

Otherwise it’s possible to find this element and check its styles. There is the solution.

import React from 'react'import 'jest-dom/extend-expect'
import { render, cleanup } from 'react-testing-library'
import MyHeader from './MyHeader'afterEach(cleanup)test('It has to contain My Header', () => {
render(
<div>
<MyHeader />
</div>
)
const headerClass = MyHeader().type.styledComponentId
const MyHeaderRoots = document.getElementsByClassName(headerClass)
const style = window.getComputedStyle(MyHeaderRoots[0])
expect(style.position).toBe('fixed')
expect(style.top).toBe('0px')
})

Here we see how to get a className of a Styled Component.

MyHeader().type.styledComponentId
=> "MyHeader__MyHeaderRoot-a8c9o2-0"

After that we just use a typical DOM selector method

document.getElementsByClassName(headerClass)

and finally we define the style object for the rendered element

const style = window.getComputedStyle(MyHeaderRoots[0])

Actually that is it. Now you can check CSS styles like that:

expect(style.position).toBe('fixed')
expect(style.top).toBe('0px')

Enjoy with testing!

UPD 1:
Why didn’t I use a way like that?

expect(container).toHaveStyle(‘padding-top: 10px;’)

This way was described in the Article https://hackernoon.com/testing-react-with-jest-axe-and-react-testing-library-accessibility-34b952240f53

In my case I have a div wrapper for my component in the test

render(
<ExternalWrapper>
<MyHeader />
</ExternalWrapper>
)

In my case I could not remove the wrapper, because sometimes you have to use a specific wrappers with some properties from external packages. It makes impossible to use toHaveStyle directly in the code.

UPD 2:

The code

const headerClass = MyHeader().type.styledComponentId
const MyHeaderRoots = document.getElementsByClassName(headerClass)
const style = window.getComputedStyle(MyHeaderRoots[0])

May be moved to a helper-function

const getStyledComponentStyles = (StyledComponent, index = 0) => {
const componentClass = StyledComponent().type.styledComponentId
const components = document.getElementsByClassName(componentClass)
const style = window.getComputedStyle(components[index])
}

UPD 3:

Testing of CSS is not a best practice. Usually you have to avoid it, because it gives not too much. But sometimes you should test something specific what is simpler to test via this approach. For example, sometimes you want to be sure that an element has a required position value. That is exactly I showed to you in my case.

For better testing you should try to use testing via snapshots and visual testing. Maybe once I’ll write an article about these approaches also.

--

--

Ilya Zykin
Ilya Zykin

Written by Ilya Zykin

IT coach. React and Rails enthusiast. Passionate programmer, caring husband and pancake baker on Sundays. School teacher of computer studies in the past.

Responses (8)