Ящик Testing Material Ui (v5) — не удается прочитать свойство ‘scrollTop’ с нулевым значением

#material-ui #mocha.js #enzyme

Вопрос:

Это простой пример, который показывает проблему. (переход на поверхностное тестирование не подходит для реальных тестов). Этого не произошло в 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@muimaterialnodetransitionsutils.js:9:29)
    at $SOMEPATHnode_modules@muimaterialnodeFadeFade.js:94:24
    at Object.onEnter (node_modules@muimaterialnodeFadeFade.js:87:9)
    at Transition.performEnter (node_modules@muimaterialnode_modulesreact-transition-groupcjsTransition.js:283:16)
    at Transition.updateStatus (node_modules@muimaterialnode_modulesreact-transition-groupcjsTransition.js:249:14)
    at Transition.componentDidMount (node_modules@muimaterialnode_modulesreact-transition-groupcjsTransition.js:193:10)
    at commitLifeCycles (node_modulesreact-domcjsreact-dom.development.js:20663:24)
    at commitLayoutEffects (node_modulesreact-domcjsreact-dom.development.js:23426:7)
    at Object.invokeGuardedCallbackProd (node_modulesreact-domcjsreact-dom.development.js:3862:10)
    at invokeGuardedCallback (node_modulesreact-domcjsreact-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@muimaterialnodetransitionsutils.js:9:29)
at $SOMEPATHnode_modules@muimaterialnodeFadeFade.js:94:24
at Object.onEnter (node_modules@muimaterialnodeFadeFade.js:87:9)
at Transition.performEnter (node_modules@muimaterialnode_modulesreact-transition-groupcjsTransition.js:283:16)
at Transition.updateStatus (node_modules@muimaterialnode_modulesreact-transition-groupcjsTransition.js:249:14)
at Transition.componentDidMount (node_modules@muimaterialnode_modulesreact-transition-groupcjsTransition.js:193:10)
at commitLifeCycles (node_modulesreact-domcjsreact-dom.development.js:20663:24)
at commitLayoutEffects (node_modulesreact-domcjsreact-dom.development.js:23426:7)
at Object.invokeGuardedCallbackProd (node_modulesreact-domcjsreact-dom.development.js:3862:10)
at invokeGuardedCallback (node_modulesreact-domcjsreact-dom.development.js:4056:31)
 

Однако тестирование внутреннего Fade компонента работает без ошибок.

 it('test Fade', () =>
{
    const wrapper = enzyme.mount(<Fade in={true}><div>hello</div></Fade>);

    console.log(wrapper.debug());
})
 

Ответ №1:

Обходной путь — примените следующие реквизиты к 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 in, которые используют Modal компоненты.

Например:

 <Dialog 
   {...this.context}
 

В производственном коде this.context равен {}, но в тестовом коде он возвращает disablePortal hideBackdrop и TransitionComponent реквизит, необходимый для обходного пути.

Для получения дополнительной информации о том, как использовать контекст, см. Документы react context docs — (они отличаются для классов и функциональных компонентов.

Ответ №2:

Это помогло мне поместить содержимое, которое я хочу показать внутри Fade, в поле со 100vh

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