Home > Software design >  How to write unit test cases for different screen sizes using react-testing-library
How to write unit test cases for different screen sizes using react-testing-library

Time:06-26

I have two buttons to display based on the screen size(for medium screen one button and another button for other screens). I'm using Material UI's MediaQuery and theme.breakpoints to define the screen size.

This is my UI code and I'm using Typescript in React.

import React from "react";
import Button from "@material-ui/core/Button";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { useTheme } from "@material-ui/core/styles";

export default function SimpleCard() {
  const theme = useTheme();
  const isMd = useMediaQuery(theme.breakpoints.only("md"));

  return (
   <div>
    {isMd ? (
      <Button
       data-testid="mediumScreenButton"
       onClick={() => console.log("medium")}
      >
       medium screen
      </Button>
     ) : (
      <Button
       data-testid="otherScreenButton"
       onClick={() => console.log("other")}
      >
       Other screen
      </Button>
     )}
   </div>
 );
}

This is my test code

import React from 'react';
import { render, fireEvent, screen, waitFor, cleanup } from '@testing-library/react';
import Demo from './Demo'

beforeEach(() =>
{
 window.scrollTo = jest.fn();
 window.HTMLDivElement.prototype.scrollIntoView = jest.fn();

 // window.matchMedia('(max-width: 999px)');

});

describe('To test cond. for screen sizes', () =>
 {
  afterEach(cleanup);

  it('Medium screen', async () =>
   {
    const { container } = render(<Demo />)

    const mediumScreenButton = screen.getByTestId('mediumScreenButton');
    fireEvent.click(mediumScreenButton);

    expect(container).toMatchSnapshot();

   });

});

I don't understand how to set the screen size to medium in my test file so that my test case will pass. But right now, the test case is failing as "unable to find element with data testid mediumScreenButton ". Can someone help me in solving this.

Thank you.

CodePudding user response:

Mui docs have some example on how do to it.

You need an implementation of matchMedia in your test environment.

For instance, jsdom doesn't support it yet. You should polyfill it. Using css-mediaquery to emulate it is recommended.

So first you need to install css-mediaquery:

npm install css-mediaquery
// OR
yarn add css-mediaquery

And your test could be:

import mediaQuery from "css-mediaquery";
import Demo from './Demo'

const createMatchMedia = (width) => (query) => ({
  matches: mediaQuery.match(query, { width }),
  addListener: () => {},
  removeListener: () => {}
});

describe("Media Test", () => {
  it("Desktop Test", async () => {
    window.matchMedia = createMatchMedia(1000);

    render(<Demo />);

    const buttonEl = screen.getByRole("button");

    expect(buttonEl).toHaveTextContent("medium screen");
  });

  it("Mobile Test", async () => {
    window.matchMedia = createMatchMedia(200);

    render(<Demo />);

    const buttonEl = screen.getByRole("button");

    expect(buttonEl).toHaveTextContent("Other screen");
  });
});

* A tip about your code:

Avoid use getByTestId to find elements with testing-library. In their documents has a query priority recommendation, as you can check here. So, in your case you can use getByRole('button')

CodePudding user response:

I'm using Typescript in my project. The below code is worked for me. Thanks to @Luis for the hint.

install css-mediaquery

npm install css-mediaquery

add this function in your test file

function createMatchMedia(width) {
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
    matches: mediaQuery.match(query, { width }),
    media: query,
    onchange: null,
    addListener: jest.fn(), // deprecated
    removeListener: jest.fn(), // deprecated
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
})),
});
};

Finally place this in your test case (it)

createMatchMedia('999px');

Overall test code would be

import React from 'react';
import { render, fireEvent, screen, cleanup } from '@testing-library/react';
import Demo from './Demo'
import mediaQuery from 'css-mediaquery'; // install this package

function createMatchMedia(width) {
  Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: jest.fn().mockImplementation(query => ({
    matches: mediaQuery.match(query, { width }),
    media: query,
    onchange: null,
    addListener: jest.fn(), // deprecated
    removeListener: jest.fn(), // deprecated
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })),
  });
};

beforeEach(() =>
 {
  window.scrollTo = jest.fn();
  window.HTMLDivElement.prototype.scrollIntoView = jest.fn();

 });

describe('To test cond. for screen sizes', () =>
 {
  afterEach(cleanup);

  it('Medium screen', async () =>
   {
    createMatchMedia('999px');
    const { container } = render(<Demo />)

    const mediumScreenButton = screen.getByTestId('mediumScreenButton');
    fireEvent.click(mediumScreenButton);

    expect(container).toMatchSnapshot();

   });

});
  • Related