这是一个显示问题的简单示例。 (对于真正的测试来说,切换到浅层测试不是一个选项)。这在materialui v4 中没有发生。 (仅在升级到mui v5后)
it('Test Drawer', () =>
{
enzyme.mount(<Drawer
open={true}
>
<div>hello world</div>
</Drawer>);
})
产生以下错误:
TypeError: Cannot read property 'scrollTop' of null
at reflow (node_modules\@mui\material\node\transitions\utils.js:9:29)
at $SOMEPATH\node_modules\@mui\material\node\Fade\Fade.js:94:24
at Object.onEnter (node_modules\@mui\material\node\Fade\Fade.js:87:9)
at Transition.performEnter (node_modules\@mui\material\node_modules\react-transition-group\cjs\Transition.js:283:16)
at Transition.updateStatus (node_modules\@mui\material\node_modules\react-transition-group\cjs\Transition.js:249:14)
at Transition.componentDidMount (node_modules\@mui\material\node_modules\react-transition-group\cjs\Transition.js:193:10)
at commitLifeCycles (node_modules\react-dom\cjs\react-dom.development.js:20663:24)
at commitLayoutEffects (node_modules\react-dom\cjs\react-dom.development.js:23426:7)
at Object.invokeGuardedCallbackProd (node_modules\react-dom\cjs\react-dom.development.js:3862:10)
at invokeGuardedCallback (node_modules\react-dom\cjs\react-dom.development.js:4056:31)
lib 版本
"react": "^17.0.2",
"@mui/material": "^5.0.4",
"enzyme": "^3.9.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.3",
现在 v4 -> v5 迁移指南说:
“您需要确保子级将自定义组件的引用转发到 DOM。”
这是我尝试过的
let r = React.createRef();
enzyme.mount(<Drawer
ref={r}
open={true}
>
<div>hello world</div>
</Drawer>);
但这没有什么区别,Drawer
的
文档示例没有通过参考。
如何安装测试
Drawer
?这仅发生在测试中(不会在实际运行时发生)
更新:
测试安装
Modal
做同样的事情:
it('test Modal', () =>
{
const wrapper = enzyme.mount(<Modal open={true}><div>hello</div></Modal>);
console.log(wrapper.debug());
})
因此产生此错误:
TypeError: Cannot read property 'scrollTop' of null
at reflow (node_modules\@mui\material\node\transitions\utils.js:9:29)
at $SOMEPATH\node_modules\@mui\material\node\Fade\Fade.js:94:24
at Object.onEnter (node_modules\@mui\material\node\Fade\Fade.js:87:9)
at Transition.performEnter (node_modules\@mui\material\node_modules\react-transition-group\cjs\Transition.js:283:16)
at Transition.updateStatus (node_modules\@mui\material\node_modules\react-transition-group\cjs\Transition.js:249:14)
at Transition.componentDidMount (node_modules\@mui\material\node_modules\react-transition-group\cjs\Transition.js:193:10)
at commitLifeCycles (node_modules\react-dom\cjs\react-dom.development.js:20663:24)
at commitLayoutEffects (node_modules\react-dom\cjs\react-dom.development.js:23426:7)
at Object.invokeGuardedCallbackProd (node_modules\react-dom\cjs\react-dom.development.js:3862:10)
at invokeGuardedCallback (node_modules\react-dom\cjs\react-dom.development.js:4056:31)
但是测试内部
Fade
组件可以正常工作。
it('test Fade', () =>
{
const wrapper = enzyme.mount(<Fade in={true}><div>hello</div></Fade>);
console.log(wrapper.debug());
})
它帮助我用 100vh 将想要显示的内容封装在 Fade in a Box 中
<Box minHeight="100vh">{children}</Box>
解决方法 - 在
Drawer
或任何基于 Modal
的组件(例如 Dialog
)上应用以下属性,以在运行测试时禁用转换。
const disableTransitionProps = {
disablePortal: true,
hideBackdrop: true,
TransitionComponent: ({ children }) => children
};
enzyme.mount(<Drawer
open={true}
{...disableTransitionProps }
>
<div>hello world</div>
</Drawer>);
更新:
我在反应上下文中完成了解决方法
// ModalProps.Context.jsx
import React from 'react';
const ModalPropsContext = React.createContext({});
// for unittest - workaround MUI c5 (5.0.5) Transitions bugs when runing tests.
export const DefaultForTests = {value : {
disablePortal : true,
hideBackdrop: true,
TransitionComponent: ({ children }) => children
}}
// For unittests
export const MountRendererPropsForModalComponents = {wrappingComponent : ModalPropsContext.Provider, wrappingComponentProps : DefaultForTests};
export default ModalPropsContext;
可以这样使用它:
import {MountRendererPropsForModalComponents} from 'ModalPropsContext.jsx'
然后:
const wrapper = enzyme.mount(<SomeComponentThatContainsModalComponents />, MountRendererPropsForModalComponents);
然后您只需在使用
ModalPropsContext
组件的组件中导入并使用 Modal
即可。
例如:
<Dialog
{...this.context}
在生产代码中,this.context 是 {},但在测试代码中,它返回解决方法所需的
disablePortal
、hideBackdrop
和 TransitionComponent
属性。
有关如何使用上下文的更多信息,请参阅 react 上下文文档 - (对于类和功能组件来说它是不同的。
这建立在汤姆的回答之上。您可以在主题中定义 MUI 组件默认属性。这节省了您为每个 Modal 组件提供上下文的精力。
创建主题并将其提供给被测组件:
import * as React from "react";
import { createTheme } from "@mui/material";
import { StyledEngineProvider, ThemeProvider } from "@mui/material/styles";
import defaultTheme from "../../src/renderer/data/theme";
export default class TestProvider extends React.Component {
disableTransitions = {
defaultProps: {
disablePortal: true,
hideBackdrop: true,
TransitionComponent: ({ children }) => children
}
};
render() {
const theme = createTheme({
...defaultTheme,
// disable Transitions when runing tests, throws errors otherwise.
components: {
MuiDialog: this.disableTransitions,
MuiModal: this.disableTransitions
}
} as any);
return (
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>{this.props.children}</ThemeProvider>
</StyledEngineProvider>
);
}
}
然后用
<TestProvider>
包裹你想要测试的组件:
import renderer from "react-test-renderer";
const component = renderer.create(
<TestProvider>
<MyTestComponent/>
</TestProvider>
);