React测试库在呈现过程中不应用材料UI组件的sx支持。
例如,我指定属性来隐藏某个断点上的元素。
<>
<AppBar
data-testid="mobile"
...
sx={{
display: { xs: "block", sm: "none" }
}}
>
MOBILE
</AppBar>
<AppBar
data-testid="desktop"
...
sx={{
display: { xs: "none", sm: "block" }
}}
>
DESKTOP
</AppBar>
</>在浏览器中,一切都按预期工作。当呈现在React测试库中时,我得到了两个元素的结果。从样式中可以清楚地看出,它们是基础知识,而sx属性没有应用。链接到码箱
import { ThemeProvider } from "@mui/material/styles";
import { screen, render } from "@testing-library/react";
import darkTheme from "./darkTheme";
import App from "./App";
describe("Demo", () => {
it("should have display props", () => {
render(
<ThemeProvider theme={darkTheme}>
<App />
</ThemeProvider>
);
expect(screen.getByTestId("mobile")).toHaveStyle({ display: "none" });
expect(screen.getByTestId("desktop")).toHaveStyle({ display: "block" });
});
});在中测试这种材料UI道具的正确方法是什么?
发布于 2022-06-02 12:46:40
在遇到同样的问题后,我决定编写一个临时帮助程序,用于对计算样式执行断言。
我发现正在将计算出来的sx样式应用于head。如果你运行screen.debug(),你将无法看到它.然而,运行document.head.innerHTML就能做到这一点。
请注意,这一用途远远不是完美的。这只是继续测试的一种快速方法。
export const getElementStyleFromHead = (element: HTMLElement) => {
const sourceElementClassNames = [...element.classList.values()]; // get all the classNames for source element
const styleTags = new DOMParser().parseFromString(document.head.innerHTML, 'text/html').querySelectorAll('style'); // parse all style tags in head
const styleTagsArray = [...styleTags.values()]; // convert NodeList to array
const elementStyles = styleTagsArray.filter((style) => sourceElementClassNames.some((className) => style.innerHTML?.includes(className))); // filter all matching classNames between sourceElementClassNames and the style tag
return elementStyles.map(item => item.innerHTML).join(''); // join all classes and parse it as one css string
};
页面:
<Box sx={{
display: 'flex',
justifyContent: centerContent ? 'center' : 'flex-start'
}}>
{'dummy content'}
</Box>
使用它:
expect(getElementStyleFromHead(customScreen.getByText('dummy content'))).toContain('justify-content:center')
编辑:我发现动态风格并不总是被及时清理。我的用例是,当我在内容窗格中滚动时,应该使用:after和: case将滚动指示器(阴影)添加到窗格的顶部和底部。我的测试没有按顺序运行,但在隔离运行时却通过了。我在beforeEach中添加了这一行,以确保头部始终被清除。不确定这是否还有其他副作用..。
beforeEach(() => {
document.head.innerHTML = '';
});发布于 2022-11-10 22:04:49
如果您想测试屏幕大小,您可能必须移动逻辑以检测屏幕大小。
如果您使用windows.innerWidth,然后在此基础上显示您的元素。
const mobileScreenSize = someNumberYouPick
const screenSize = window.innerWidth;
const mobile = () => { return screenSize - mobileScreenSize =< 0 ? true : false}
{ mobile() && {
<AppBar
data-testid="mobile"
...
>
MOBILE
</AppBar>
}}
{ !mobile() && {
<AppBar
data-testid="desktop"
...
>
DESKTOP
</AppBar>
}}然后在测试中,您可以设置您的windows.innerwidth并设置您想要的值。
describe("Demo", () => {
it("should have display props", () => {
Object.defineProperty(window, 'innerWidth', {
writable: true,
configurable: true,
value: 150,
});
render(
<ThemeProvider theme={darkTheme}>
<App />
</ThemeProvider>
);
expect(screen.getByTestId("mobile")).not.toBeVisible()
expect(screen.getByTestId("desktop")).toBeVisible()
});
});这应该能起作用。如果使用以下方法设置测试,我想知道是否需要更改代码逻辑:
Object.defineProperty(window, 'innerWidth', {
writable: true,
configurable: true,
value: 150,
});https://stackoverflow.com/questions/71217789
复制相似问题