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. Usingcss-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();
});
});