Test responsive design using jest and react-testing-library

Testing design breakpoints in React applications is an important aspect of front-end development. It ensures that the components look and behave as expected on different screen sizes. In this article, we will see how to test design breakpoints using Jest, React Testing Library and CSS Media Queries.

Setting up the environment

We will start by setting up a simple React component that changes its text based on the screen size. This React component does use useMediaQuery,useTheme from MUI library in order to handle the breakpoints logic.

Here’s the code for our component:

import * as React from "react";
import { useMediaQuery, useTheme } from "@mui/material";

export default function App() {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.only("xs")); // between 0 and 600px
  const isTablet = useMediaQuery(theme.breakpoints.only("sm")); // between 600px and 900px
  const isDesktop = useMediaQuery(theme.breakpoints.up("md")); // above 900px

  return (
    <React.Fragment>
      {isMobile && <span>Hello Mobile</span>}
      {isTablet && <span>Hello Tablet</span>}
      {isDesktop && <span>Hello Desktop</span>}
    </React.Fragment>
  );
}

So in case the screen size fits the condition on mobile screens (>0px and <= 600px), the text Hello Mobile will be rendered on the screen. and the same will be applied for the rest of the break points.

MUI Breakpoints.


Mobile View:

Test design breakpoints using jest and react-testing-library - Mobile view
Test design breakpoints using jest and react-testing-library – Mobile view

Tablet View:

Test design breakpoints using jest and react-testing-library - Tablet view
Test design breakpoints using jest and react-testing-library – Tablet view

Desktop view:

Test design breakpoints using jest and react-testing-library - Desktop view
Test design breakpoints using jest and react-testing-library – Desktop view

Cool, now let’s dig into testing part.


Testing

First, let’s install the react-testing-library as a dependency in our project sample:

yarn add @testing-library/react

In order to test breakpoints in jest, we need an implementation of matchMedia in our test environment.

So far, jsdom doesn’t support it yet. which means we need to polyfill it. Using css-mediaquery to emulate it. So let’s install css-mediaquery as well:

yarn add css-mediaquery

Now, let’s create a function that returns MediaQueryList object which can then be used to determine if the document matches the media query string.

In your test file, add the following implementation:

import { render, screen } from "@testing-library/react";
import MyApp from "./App";
import mediaQuery from "css-mediaquery";

function createMatchMedia(width) {
  return (query) => {
    return {
      matches: mediaQuery.match(query, { width }),
      media: "",
      addListener: () => {},
      removeListener: () => {},
      onchange: () => {},
      addEventListener: () => {},
      removeEventListener: () => {},
      dispatchEvent: () => true,
    };
  };
}

function resizeScreenSize(width) {
  window.matchMedia = createMatchMedia(width);
}

The function resizeScreenSize will be called in each test suit with the breakpoint width, which is gonna call createMatchMedia function, that will determine if the document matches the query string or not.

Now, let’s add our first test case for mobile screens:

it("renders correctly on mobiles screens", () => {
  // Set the screen size to a smaller value
  resizeScreenSize(400);

  // Render the component
  render(<MyApp />);

  // Verify that the component styles are correct for the default screen size
  const pElement = screen.getByText("Hello Mobile");
  expect(pElement).toBeInTheDocument();
});
  • First, Call resizeScreenSize(400), with any number less than 600px to meet the condition that this view is mobile view.
  • Then, render the component.
  • Lastly, verify that the rendered text in the component is matching what we’re expecting.

Applying the above to the other two cases, we will end up with the following testing implementation:

import { render, screen } from "@testing-library/react";
import MyApp from "./App";
import mediaQuery from "css-mediaquery";

function createMatchMedia(width) {
  return (query) => {
    return {
      matches: mediaQuery.match(query, { width }),
      media: "",
      addListener: () => {},
      removeListener: () => {},
      onchange: () => {},
      addEventListener: () => {},
      removeEventListener: () => {},
      dispatchEvent: () => true,
    };
  };
}

function resizeScreenSize(width) {
  window.matchMedia = createMatchMedia(width);
}

describe("App Component", () => {
it("renders correctly on mobiles screens", () => {
  // Set the screen size to a smaller value
  resizeScreenSize(400);

  // Render the component
  render(<MyApp />);

  // Verify that the component styles are correct for the default screen size
  const pElement = screen.getByText("Hello Mobile");
  expect(pElement).toBeInTheDocument();
});

  it("renders correctly on tablets screens", () => {
    // Set the screen size to a smaller value
    resizeScreenSize(600);

    // Render the component
    render(<MyApp />);

    // Verify that the component styles are correct for the default screen size
    const pElement = screen.getByText("Hello Tablet");
    expect(pElement).toBeInTheDocument();
  });

  it("renders correctly on desktop screens", () => {
    // Set the screen size to a smaller value
    resizeScreenSize(900);

    // Render the component
    render(<MyApp />);

    // Verify that the component styles are correct for the default screen size
    const pElement = screen.getByText("Hello Desktop");
    expect(pElement).toBeInTheDocument();
  });
});

and by running the command `yarn test`, we can see all the tests have passed 👏👏


Source code.

Photo from Unsplash.

Related Posts

How to Capture Screenshots with Puppeteer In NodeJS

How to Capture Screenshots with Puppeteer In NodeJS

To Capture Screenshots with Puppeteer: Launch a Browser Instance Navigate to the Web Page Capture the Screenshot Introduction: Puppeteer is a powerful Node.js library that allows developers…

How to Minimize Puppeteer Browser Window To Tray

How to Minimize Puppeteer Browser Window To Tray

Puppeteer is a powerful tool for automating tasks in headless or non-headless web browsers using JavaScript. While Puppeteer is often used to perform actions within a browser,…

Intercepting Responses in Node.js with Puppeteer

Intercepting Responses in Node.js with Puppeteer

Introduction: Puppeteer is a powerful Node.js library that provides a high-level API for controlling headless Chrome or Chromium browsers. It’s widely used for web scraping, automated testing,…

Mastering React Component Re-rendering in Jest

Mastering React Component Re-rendering in Jest

In this hands-on guide, we’ll explore the art of optimizing React component re-rendering within Jest tests. By combining theory with practical coding examples, you’ll gain a deep…

Eliminating Nesting Loops in React Rendering

Eliminating Nesting Loops in React Rendering

React has ushered in a new era of web application development with its component-based structure, promoting code reusability and maintainability. But as projects evolve, achieving optimal performance…

Exploring Type and Interface Usage in TypeScript

Exploring Type and Interface Usage in TypeScript

TypeScript has gained immense popularity by bridging the gap between dynamic JavaScript and static typing. Two of its fundamental features, “Type” and “Interface,” play pivotal roles in…

Leave a Reply

%d bloggers like this: