我有两个按钮根据屏幕尺寸显示(对于中屏幕,一个按钮,对于其他屏幕,另一个按钮)。我使用 Material UI 的 MediaQuery 和 theme.breakpoints 来定义屏幕尺寸。
这是我的 UI 代码,我正在 React 中使用 Typescript。
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>
);
}
这是我的测试代码
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();
});
});
我不明白如何在我的测试文件中将屏幕尺寸设置为中等以便我的测试用例能够通过。但现在,测试用例失败,因为“无法找到带有数据 testidmediumScreenButton 的元素”。 有人可以帮我解决这个问题吗?
谢谢你。
docs 有一些关于如何操作的示例。
您需要在测试环境中实现 matchMedia。所以首先你需要安装
例如,jsdom还不支持它。你应该填充它。建议使用css-mediaquery
进行模拟。
css-mediaquery
:
npm install css-mediaquery
// OR
yarn add css-mediaquery
你的测试可能是:
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");
});
});
* 关于您的代码的提示:避免使用
getByTestId
来查找带有
testing-library
的元素。在他们的文档中有一个查询优先级建议,您可以查看here。因此,根据您的情况,您可以使用
getByRole('button')
安装
css-mediaquery
npm install css-mediaquery
将此函数添加到您的测试文件中
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(),
})),
});
};
最后将其放入您的测试用例中(it)
createMatchMedia('999px');
总体测试代码是
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();
});
});