How to test styling using Jest
Asked Answered
P

3

21

I'm working on a React project that uses SASS (SCSS syntax) for styling, along with Jest for unit tests. I'm having trouble testing styling in my project. Here's a simple example:

In component.js (which imports a separate stylesheet)...

const Component = () => {
     return (
        <div className="greeting">Hello</div>
     )
}

In my .scss file...

.greeting {
    background-color: red;
}

In my test file...

test('background color should be red', () => {
    render(<Component />);
    expect(screen.getByText('Hello')).toHaveStyle('background-color: red');
})

The test fails with:

expect(element).toHaveStyle()

    - Expected

    - background-color: red;

However, if I use inline styling (<div style={{backgroundColor: red}}>Hello</div>), the test passes.

Has anyone encountered this issue? I'm also wondering other people's approaches to testing styling in Jest (particularly when your styles are kept in a separate .scss file)

I am utilizing screen from @testing-library/dom and render from @testing-library/react for my tests.

Peavy answered 2/11, 2020 at 0:50 Comment(1)
Jest is not the right too to test CSS that is not CSS-in-JS. I would look into visual diffing maybe?!Acuminate
A
20

I agree with Dominik. Jest is good for testing properties of your rendered HTML. Unless the styling is within the HTML (inline styling), Jest will not see it (as you have pointed out). The deepest you could test without in-lining the styles is to verify that it has a proper class name.

Maybe a test framework that runs in a browser like Cypress? Have a read of visual testing with Cypress.

Archy answered 2/11, 2020 at 2:53 Comment(1)
Yeah, cypress component testing seems the way to go. My answere on this question... kinda makes sense, but correct me if I am wrong but it seems you can't really simulate media queries in a jest approachSatisfy
O
20

You can use window.getComputedStyle() to access the final result of all your styling, even those in classes.

In your case, in order to test what the background color the div element ends up being you would write:

test('background color should be red', () => {
    render(<Component />);

    const element = screen.getByText('Hello');
    const styles = getComputedStyle(element);

    expect(styles.backgroundColor).toBe('red');
})
Oxa answered 2/6, 2021 at 12:27 Comment(3)
This does not work if the style is not inlined.Gittle
Works for me, although the style is not inlined (using vitest with 'happy-dom')Westering
I've got it working by adding "import '../src/index.css'" in the test file, as the tested component didn't import the global style itself (also using vitest with 'happy-dom').Drandell
S
4

I was struggling with the same thing with testing non-inlined CSS styles

I'm using Gatsby to clone a web page for fun and I wanted to test styles in jest without the overhead of a browser like playwright

Pretty soon I stumbled on jest-transform-css and just now I was able to get a proof of concept style unit test working

Granted I am using CSS Modules, not SASS or SCSS

Basically after following their setup in their README docs, I got a test like this working

import '@testing-library/jest-dom'

import * as React from 'react'
import {render, fireEvent, screen} from '@testing-library/react'
import * as styles from "../../styles/navbar.module.css"
import { HomeNavButton } from "../buttons"

test('test HomeNavButton', () => {
    const testMessage = 'Test Message'
    render(<HomeNavButton href={"/test"} text={testMessage} className={styles.homeItem}/>)

    const div = screen.getByText(testMessage).parentElement
    const computedStyle = window.getComputedStyle(div)
    expect(computedStyle.margin).toBe('auto auto auto 0px')
}

Here the margin style of auto auto auto 0px comes from the styles.homeItem

Satisfy answered 15/12, 2022 at 2:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.