Jestjs 如何将材质UI样式表注入jest/react测试库测试?

Jestjs 如何将材质UI样式表注入jest/react测试库测试?,jestjs,material-ui,react-testing-library,Jestjs,Material Ui,React Testing Library,似乎如果您不将材质UI样式表注入jest/react测试库测试,那么jsdom将无法从组件中获取正确的样式(例如,运行getComputedStyle(组件)将返回组件的错误样式) 如何正确设置jest/react测试库测试,以便将样式正确地注入测试?我已经将组件包装在主题提供程序中,这很好。我不能专门谈论材质UI样式表,但您可以将样式表插入渲染组件中: 从'@testing library/react'导入{render}; 从“fs”导入fs; 从“路径”导入路径; const styles

似乎如果您不将材质UI样式表注入jest/react测试库测试,那么jsdom将无法从组件中获取正确的样式(例如,运行
getComputedStyle(组件)
将返回组件的错误样式)


如何正确设置jest/react测试库测试,以便将样式正确地注入测试?我已经将组件包装在主题提供程序中,这很好。

我不能专门谈论材质UI样式表,但您可以将样式表插入渲染组件中:

从'@testing library/react'导入{render};
从“fs”导入fs;
从“路径”导入路径;
const stylesheetFile=fs.reactFileSync(path.resolve(uu dirname,../path to stylesheet'),'utf-8');
const styleTag=document.createElement('style');
styleTag.type='text/css';
styleTag.innerHTML=样式表文件;
const rendered=render();
附加(样式);

你不必从文件中读取,你可以使用任何你想要的文本。

这最终似乎是一个问题,各种浏览器实现,如jsdom和Blink(至少在Chrome中)。当您试图修改/启用/禁用这些样式规则时,可以在Chrome中看到它(您不能)

该行为似乎是JSS库使用的结果。DOM中为组件中的样式生成了一个样式表,但是标记是空的——它只是用来将阴影CSS链接回DOM。样式永远不会写入DOM中的内联样式表,因此,
getComputedStyle
方法不会返回预期的结果

有很多方法可以解决这种行为,并使开发更容易

我将我的自定义组件切换到,它没有这些特性。
.

作为一种解决方法,在断言之前重新插入整个头部(或注入JSS样式的元素)似乎可以正确地应用样式,包括
getComputedStyle()
和react测试库的
toHaveStyle()

从“React”导入React;
导入“@测试库/jest dom/extend expect”;
从“@testing library/react”导入{render}”;
测试(“测试我的风格”,()=>{
常量{getByTestId}=render(
);
const button=getByTestId(“包装器”).firstChild;
document.head.innerHTML=document.head.innerHTML;
expect(button).toHaveStyle(`border radius:4px;`);
});
但在您使用时仍然会失败,例如:

myButton:{
填充:props=>props.spating,
...
}
这是因为JSS使用方法注入这些样式,它不会在头部显示为
style
节点。解决这个问题的一个方法是连接到浏览器的
insertRule
方法,并将传入的规则作为样式标记添加到头部。要将所有这些提取到函数中,请执行以下操作:

函数mockStyleInjection(){
const defaultInsertRule=window.CSSStyleSheet.prototype.insertRule;
window.CSSStyleSheet.prototype.insertRule=函数(规则,索引){
constyleElement=document.createElement(“样式”);
const textNode=document.createTextNode(规则);
appendChild(textNode);
document.head.appendChild(styleElement);
返回defaultInsertRule.bind(this)(规则,索引);
};
//清除功能,可重新插入磁头并清除方法覆盖
返回函数applyJSSRules(){
window.CSSStyleSheet.prototype.insertRule=defaultInsertRule;
document.head.innerHTML=document.head.innerHTML;
};
}
在上一次测试中使用此函数的示例:

从“React”导入React;
导入“@测试库/jest dom/extend expect”;
从“@testing library/react”导入{render}”;
测试(“测试我的风格”,()=>{
const applyJSSRules=mockStyleInjection();
常量{getByTestId}=render(
);
const button=getByTestId(“包装器”).firstChild;
applyJSSRules();
expect(按钮).toHaveStyle(“边框半径:4px;”);
expect(button).toHaveStyle(“padding:8px;”);
});
您可以将其添加到。渲染后,该函数将样式从中拉出,并将其放入样式标记中。下面是一个实现:

let customRender = (ui, options) => {
    let renderResult = render(ui, options);
    let styleElement = document.createElement("style");
    let styleText = "";
    for (let styleSheet of document.styleSheets) {
        for (let rule of styleSheet.cssRules) {
            styleText += rule.cssText + "\n";
        }
    }
    styleElement.textContent = styleText.slice(0, -1);
    document.head.appendChild(styleElement);
    // remove old style elements
    let emptyStyleElements = document.head.querySelectorAll('style[data-jss=""]');
    for (let element of emptyStyleElements) {
        element.remove();
    }
    return renderResult;
}

你有没有想过?没有,这似乎是一个限制与笑话/RTL这正是我所寻找的!我使用的是动态样式,而我使用
toHaveStyle
的Jest测试由于某种原因一直失败。你把它清理干净了,谢谢!