测试 Material Ui (v5) 抽屉 - 无法读取 null 的属性“scrollTop”

问题描述 投票:0回答:3

这是一个显示问题的简单示例。 (对于真正的测试来说,切换到浅层测试不是一个选项)。这在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());
})
material-ui mocha.js enzyme
3个回答
1
投票

它帮助我用 100vh 将想要显示的内容封装在 Fade in a Box 中

<Box minHeight="100vh">{children}</Box>

0
投票

解决方法 - 在

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 上下文文档 - (对于类和功能组件来说它是不同的。


0
投票

这建立在汤姆的回答之上。您可以在主题中定义 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>
);
© www.soinside.com 2019 - 2024. All rights reserved.