Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Testing Library (RTL): 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)

like image 788
Norfeldt Avatar asked Oct 09 '20 13:10

Norfeldt


People also ask

What is RTL testing?

React Testing Library (RTL) is a library for testing React applications. React Testing Library focuses on testing components from the end-user's experience rather than testing the implementation and logic of the underlying React components.

What type of testing is React testing library?

React Testing Library is a testing utility tool that's built to test the actual DOM tree rendered by React on the browser. The goal of the library is to help you write tests that resemble how a user would use your application.

Which testing library is best for React?

By default, Jest and React come with a react-test-renderer package which can transform components into JSON objects. This mechanism is used for snapshot testing. Jest is a perfect choice for standard unit tests of pure functions.


1 Answers

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.

like image 173
Dipen Shah Avatar answered Sep 24 '22 16:09

Dipen Shah