【问题标题】:How do I test React-Responsive components with Enzyme?如何使用 Enzyme 测试 React-Responsive 组件?
【发布时间】:2017-01-01 22:38:13
【问题描述】:

我正在使用库 React-Reponsive。 https://github.com/contra/react-responsive

我正在努力弄清楚如何测试嵌套在 React-Responsive Media Query Components 中的组件:

export default class AppContainer extends React.Component {
  render(){
    return(
      <MediaQuery minDeviceWidth={750}>
         <Header />
      </MediaQuery>
    );
  }
}

-

describe("AppContainer", () => {
  let App;
  let wrapper;
  beforeEach(() => {
    wrapper = mount(<Provider store={store}><AppContainer location={location} /></Provider>);
    App = wrapper.find(AppContainer);

  });
  it('to have a <Header /> component', () => { 
    console.log(App.debug());
    expect(App.find(Header)).to.have.length(1);
  });
}

测试结果:

1) AppContainer to have a <Header /> component:
AssertionError: expected { Object (component, root, ...) } to have a length of 1 but got 0

console.log输出的相关部分是:

<MediaQuery minDeviceWidth={750} values={{...}} />

表示 Header 确实没有出现在渲染树中。但是,如果我删除 MediaQuery 并使 Header 成为 AppContainer 的直接子级,则测试通过。

我想这不是一个错误,因为我对 Enzyme 和测试组件非常陌生。任何帮助或示例将不胜感激。

请注意:我在这个组件上的其他测试都通过了。我相信导入和设置都是正确的。

【问题讨论】:

  • 应该不是expect(App.find(MediaQuery)).to.have.length(1);
  • 是的,这可以用于测试媒体查询,但我正在寻找的是在这种情况下如何测试 Header

标签: reactjs enzyme


【解决方案1】:

问题是媒体查询正在寻找带有 jsdom 未定义的 window.matchMedia。

在这种情况下,我需要使用服务器端渲染实现。然而,这需要一个静态的宽度值,这会破坏响应能力。

我的解决方案是在测试虚拟 DOM 上设置一个全局变量。

window.testMediaQueryValues = {width:740};

如果它们存在,那么 MediaQuery 可以访问它们:

<MediaQuery maxWidth={smallViewMaxWidth} values={window.testMediaQueryValues}>

在未设置变量的情况下,忽略空值,组件照常呈现。

非常感谢@Contra 的帮助和超级图书馆

【讨论】:

  • 也许当你写的时候 react-responsive 是不同的,但截至今天,values 没有在浏览器上下文中使用。所以你不需要全局测试值。相反,您可以传递一个用于保存目的的道具。
  • @rodrigo-silveira 你能详细说明一下吗?不知道你是什么意思传递一个道具来达到同样的目的
  • 我想我的意思是你的组件可以接受一个可选的属性,例如widthdisplayMode,它可以用来决定要渲染哪个子组件,而不是依赖于窗口状态告诉你视口宽度。
【解决方案2】:

对我有用的是使用__mocks__ 目录添加一个模拟的react-responsive 组件。基本上在目录结构中创建如下文件:

-your-component

--component-using-media-query.js

--__mocks__

---react-responsive.js

然后你可以模拟出react-responsive.js文件中的MediaQuery组件。

const MediaQuery = ({ children }) => children;

export default MediaQuery; 

【讨论】:

  • 经过数小时的尝试解决方案,这很有效,而且非常简单。
  • 这行得通...但是如何添加不同的宽度?..现在它根据模拟呈现所有 ..
【解决方案3】:

我能够使用react-responsive v7.0.0 使其工作。

给定:

<MediaQuery minDeviceWidth={750}>
  <Header />
</MediaQuery>

以下作品:

import { Context as ResponsiveContext } from 'react-responsive'
import { mount } from 'enzyme'

const wrappingComponent = ResponsiveContext.Provider
const wrappingComponentProps = { value: { width: 750 } }
const mountProps = { wrappingComponent, wrappingComponentProps }

const wrapper = mount(<AppContainer />, mountProps)

【讨论】:

    【解决方案4】:

    尝试在您的单元测试中模拟 react-responsive 依赖项。使用 Webpack,我使用 inject-loader 将测试依赖项注入模块。您可以使用“inject-loader”导入您的组件,并将您想要覆盖的依赖项传递给它。

    例子:

    import YourComponentInjector from 'inject-loader!../YourComponent.jsx';
    

    然后

    class MediaQueryDesktopMock extends React.Component {
        render() {
          const {minDeviceWidth, children} = this.props;
          if(minDeviceWidth === 765) {
            return (<div>{children}</div>)
          }
          return <span/>;
        }
      }
      let YourComponentMock = YourComponentInjector({
        'react-responsive': MediaQueryDesktopMock
      });
    

    然后您可以测试特定的媒体查询

    【讨论】:

      猜你喜欢
      • 2017-04-13
      • 2017-02-12
      • 1970-01-01
      • 2018-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-09
      • 2017-05-03
      相关资源
      最近更新 更多