Search code examples
cssreactjstestingresponsive-designreact-testing-library

How to test a responsive design?


I'm trying to test a responsive design where I hide some text (in spans) when the screen size is too narrow.

import React from 'react'
import './index.css'

function Welcome(props) {
  return (
    <div className="container" data-testid="welcome-component">
      <span
        className="search-detective-emoji"
        role="img"
        aria-label="search emoji"
      >
        🕵️‍♀️
      </span>
      <span className="title">
        <span className="verb">Search</span>{' '}
        <span className="adjectives">Good Old</span> Flickr
      </span>
      <span
        className="search-detective-emoji"
        role="img"
        aria-label="search emoji"
      >
        🕵️‍♂️
      </span>
    </div>
  )
}

export default Welcome
.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.search-detective-emoji {
  font-size: 10vw;
}

.title {
  text-align: center;
  font-size: calc(1rem + 3vw);
  font-family: Abril Fatface, Cambria, Cochin, Georgia, Times, 'Times New Roman',
    serif;
  margin: 0 10px;
}

@media screen and (max-width: 500px) {
  .title .adjectives {
    display: none;
  }
}

@media screen and (max-width: 200px) {
  .title .verb {
    display: none;
  }
}
import React from 'react'
import { render, screen, act, fireEvent } from '@testing-library/react'

import Welcome from '.'
test('renders a title', () => {
  const { getByText } = render(<Welcome />)
  const title = /flickr/i

  expect(getByText(title)).toBeInTheDocument()
})

test('renders a responsive title', () => {
  const { rerender, container } = render(<Welcome />)
  let title = /search good old flickr/i

  expect(container).toHaveTextContent(title)

  act(() => {
    window.innerWidth = 199
    fireEvent(window, new Event('resize'))
  })
  rerender(<Welcome />)

  expect(screen.getByText('Good Old')).not.toBeVisible()
})
src/components/Welcome/index.test.js
  ● renders a responsive title

    expect(element).not.toBeVisible()

    Received element is visible:
      <span class="adjectives" />

      22 |   rerender(<Welcome />)
      23 | 
    > 24 |   expect(screen.getByText('Good Old')).not.toBeVisible()
         |                                            ^
      25 | })
      26 | 

      at Object.<anonymous> (src/components/Welcome/index.test.js:24:44)

 PASS  src/App.test.js

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 failed, 2 passed, 3 total
Snapshots:   0 total
Time:        2.717s, estimated 3s

if it's easier then I got this github branch https://github.com/Norfeldt/flickr-code-challenge/blob/implement-css/src/components/Welcome/index.test.js be aware that I have commented out my attempt and that it's not possible to see if the results is a false positive (since removing the .not will also make the test pass)


Solution

  • TLDR; You will not be able to test media-queries with current setup (jest-dom).

    After debugging and going through github repository of jest-dom, it seems it will be pretty hard to test what responsive design.

    There are couple of issue with the way, jest-dom (which uses jsdom) library renders component and calculates style.

    To begin with, it doesn't attach/compute styles from attached stylesheet. This came with surprise to me as I am used to test UI with Angular setup. As mentioned in the attached link, you can try to overcome this issue by manually creating style element

    const style = document.createElement('style')
    style.innerHTML = `
      @media screen and (min-width: 500px) {
        .title .adjectives {
          display: none;
          color: red;
        }
      }
    `;
    document.body.appendChild(style)
    

    or use helper function to do that as suggested in this bug.

    After this change, I assumed it would work but to my surprise, it FAILED!, I checked with non-media query style and it was attaching style perfectly and that's when I discovered this TODO comment in jsdom, which makes sense as media-query styles are not working.

    To conclude, it will not be possible to test media-query at the moment with react-testing-library. I haven't checked if it is working with enzyme setup, but it might who knows!

    on you can use end to end testing framework such as Cypress.