Jest-dom: Media queries

Created on 29 May 2019  路  6Comments  路  Source: testing-library/jest-dom

First thank you for this awesome library!

I would like to use toHaveStyle to test a media query. I am migrating xstyled tests from jest-styled-components to jest-dom since the approach is better for me.

My question is simple. How to do the equivalent with toHaveStyle?

expect(container.firstChild).toHaveStyleRule('color', 'red', {
   media: '(min-width: 768px)',
})

Most helpful comment

I would suggest consider testing media queries through Cypress or similar framework were stylesheet actually get rendered and/or interpreted.

All 6 comments

My question is simple.

It may look simple, but it is far from it, I think 馃槃

I'm unfamiliar with both jest-styled-components and xstyled, and only somewhat familiar with styled-components, but on a quick glance to jest-styled-components, it seems to me what you want to transfer from the usage of it to this library is not easily achievable.

About jest-styled-components

That library (jest-styled-components) seems to be pretty tied up to how styled-components are implemented internally. For example, what it seems to be testing internally is related to the structure of React elements as returned by React.createElement (see this). It does not seem to actually run the components it is "rendering" through the full react stack to end up with the finished result of the DOM structure created by rendering those components. Therefore this jest-styled-components library seems to be having access to the raw props of elements and the raw styled-component-specific style objects given to those elements, in order to check for the style conditions.

The difference compared to jest-dom

This library jest-dom however, is React-agnostic, and tests an actual DOM structure that can be rendered with anything (React, Vue, Angular, etc.). When you render something for jest-dom to consume (for example by using react-testing-library) you no longer have the raw props and style objects that went through styled-components. You end up instead with what a browser would end up when rendering all that.

Stylesheets in jest-dom

Stylesheets in this context are also a bit of a complex thing to test in this detail that you intend to test them. For starters, our style checking matchers will not work properly unless you manually setup attaching a css stylesheet to the document, as done here for instance.

What you'd need to do, hypothetically

I'm not sure therefore if you can:

  1. Get the stylesheet content that styled-components generated under the hood, and...
  2. Attach it to the document manually during tests as shown in the linked lines above, and...
  3. I'm, not sure how jsdom (the headless browser context where usually jest-dom runs) would allow you then to check for specific media queries.

On setting the browser width in tests

On that last point, what our toHaveStyle matcher does is inspect the actual computed styles of the element being tested (think of the "computed styles" panel you see in a browser dev tools). So I guess that for styles applied only under a certain media query, you'd need to somehow tell the browser where the tests are being run to set a specific window size first, then test the styles of the element that you want to test to see if they change in response to changes in window size. Ideally something like this:

const { container } = render(<ComponentBeingTestedHere />)

// TODO: Attach at this point the stylesheet source code to the document...
// as shown here https://github.com/testing-library/jest-dom/blob/09f7f041805b2a4bcf5ac5c1e8201ee10a69ab9b/src/__tests__/to-have-style.js#L12-L18

browser.setWindowWidth(1280) // Note: This is not a real API!!!
expect(container.firstChild).toHaveStyle("color: blue")
browser.setWindowWidth(768) // Note: This is not a real API!!!
expect(container.firstChild).toHaveStyle("color: red")

The above hypothetical test would "prove" there's a media query somehow, without actually testing it in terms of the css source code that sets it up. However, it's up to you to see if there's a way to tell the browser in the tests to set a specific window size. I'm not sure jsdom supports that, unfortunately.

Bottomline

But this all boils down to the intent of this library (and the entire set of testing libraries it is part of): tests should be testing the end result, and not the implementation details.

That's not to say your approach is wrong. If you still prefer to test things in this level of details, and your project is nevertheless intrinsically tied to styled-components, it may not be a bad thing that you keep testing the internals of the styles set in this way. And in that case jest-dom may not be the best fit for your purpose.

Hope all this helps, and please, if you do pursue checking out the pointers I give here to try make this work, please share your findings here, wether positive or not.

Hello @gnapse,

I agree, jest-styled-components tests the underlying implementation, and I want to switch to jest-dom to test the end result (the CSS applied on the element).

I suspected that I had to change the size of the browser in order to test media queries. But I was not sure it will work that way.

I hoped that someone had already the problem and was able to give me a real working example in order to gain time.

I will work on it, as soon as I have something that work I will post it here.

Thank you!

I'm going to be closing this for the time being. Feel free to open if there's something actionable stemming from this proposal.

I would suggest consider testing media queries through Cypress or similar framework were stylesheet actually get rendered and/or interpreted.

Interestingly, even @media all seems to be excluded from window.getComputedStyle(el) in JSDOM

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hiwelo picture hiwelo  路  7Comments

benmonro picture benmonro  路  3Comments

tom-sherman picture tom-sherman  路  5Comments

BurntCaramel picture BurntCaramel  路  5Comments

Rowin206 picture Rowin206  路  3Comments