我正在其中一个组件中使用Material-UI的useMediaQuery()
函数来确定要在组件中的size
中使用的<Button>
道具。
我正在尝试在玩笑测试中测试它是否按预期工作,但是我当前的实现无法正常工作:
describe("Unit: <Navbar> On xs screens", () => {
// Incorrectly returns `matches` as `false` ****************************
window.matchMedia = jest.fn().mockImplementation(
query => {
return {
matches: true,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn()
};
}
);
it("renders as snapshot", async () => {
const width = theme.breakpoints.values.sm - 1;
const height = Math.round((width * 9) / 16);
Object.defineProperty(window, "innerWidth", {
writable: true,
configurable: true,
value: width
});
const { asFragment } = render(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
expect(asFragment()).toMatchSnapshot();
const screenshot = await generateImage({
viewport: { width, height }
});
expect(screenshot).toMatchImageSnapshot();
});
});
describe("Unit: <Navbar> On md and up screens", () => {
// Correctly returns `matches` as `false` ****************************
window.matchMedia = jest.fn().mockImplementation(
query => {
return {
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn()
};
}
);
it("renders as snapshot", async () => {
const width = theme.breakpoints.values.md;
const height = Math.round((width * 9) / 16);
Object.defineProperty(window, "innerWidth", {
writable: true,
configurable: true,
value: width
});
const { asFragment } = render(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
expect(asFragment()).toMatchSnapshot();
const screenshot = await generateImage({
viewport: { width, height }
});
expect(screenshot).toMatchImageSnapshot();
});
});
我正在测试的组件(删除了不相关的部分):
const Navbar = () => {
const theme = useTheme();
const matchXs = useMediaQuery(theme.breakpoints.down("xs"));
return (
<Button size={matchXs ? "medium" : "large"}>
Login
</Button>
);
};
export default Navbar;
尽管我已将其设置为返回true,但它在第一个测试中仍以matches
的形式返回false
。我知道这是因为它正在生成屏幕截图,并且可以看到在第一次测试中将按钮大小设置为large
时,按钮大小设置为medium
。
它在生产中按预期工作。
如何在玩笑测试中正确获得模拟useMediaQuery()
?
答案 0 :(得分:0)
我知道了...
useMediaQuery()
需要重新渲染组件才能正常工作,因为第一个渲染将返回您在options.defaultMatches
(默认为false
)中定义的内容。
此外,该模拟还需要在每个测试(it
)范围内,而不是在describe
中。
当我使用react-testing-library时,我要做的就是再次重新渲染该组件并更改模拟的范围,并且可以正常工作。
这是工作示例:
const initTest = width => {
Object.defineProperty(window, "innerWidth", {
writable: true,
configurable: true,
value: width
});
window.matchMedia = jest.fn().mockImplementation(
query => {
return {
matches: width >= theme.breakpoints.values.sm ? true : false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn()
};
}
);
const height = Math.round((width * 9) / 16);
return { width, height };
};
describe("Unit: <Navbar> On xs screens", () => {
it("renders as snapshot", async () => {
const { width, height } = initTest(theme.breakpoints.values.sm - 1);
const { asFragment, rerender} = render(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
rerender(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
expect(asFragment()).toMatchSnapshot();
const screenshot = await generateImage({
viewport: { width, height }
});
expect(screenshot).toMatchImageSnapshot();
});
});
describe("Unit: <Navbar> On md and up screens", () => {
it("renders as snapshot", async () => {
const { width, height } = initTest(theme.breakpoints.values.md);
const { asFragment } = render(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
rerender(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
expect(asFragment()).toMatchSnapshot();
const screenshot = await generateImage({
viewport: { width, height }
});
expect(screenshot).toMatchImageSnapshot();
});
});
答案 1 :(得分:0)
一种推荐的方式是使用css-mediaquery
,现在以the MUI docs编写:
import mediaQuery from 'css-mediaquery';
function createMatchMedia(width) {
return query => ({
matches: mediaQuery.match(query, { width }),
addListener: () => {},
removeListener: () => {},
});
}
describe('MyTests', () => {
beforeAll(() => {
window.matchMedia = createMatchMedia(window.innerWidth);
});
});