如何使用酶 ShallowWrapper 查找作为道具存储在另一个 React 组件中的 React 组件?

How to use enzyme ShallowWrapper to find a React Component stored as a prop in another React Component?

我有一个 jest/enzyme 测试,它围绕一个组件创建一个 ShallowWrapper,找到一个指定的语义-ui-react 按钮(通过 id),模拟按钮上的点击,然后看起来查看点击是否切换了某些内容。

示例 JSX:

<Popup
  trigger={<Button onClick={this.toggleShowThing} id="special-btn">a button</Button>}
  content="Popup Words"
/>
{this.state.showThing &&
  <div className="special-thing">The Thing's Words</div>
}

样本测试:

it('shows the thing when the button is clicked', () => {
  const wrapper = shallow(<MyComponent />);
  wrapper.find('#special-btn').simulate('click', { preventDefault() {} });
  expect(wrapper.find('.special-thing').exists()).toBe(true);
});

当我只有 Button 时,此测试有效。当我添加 Popup 并将 Button 放入 trigger 道具时,我收到了一个错误,因为找不到 #special-btn。

Error: Method “props” is only meant to be run on a single node. 0 found instead.

该组件的酶快照显示 Popup 如下所示:

<Popup 
  content="Popup Words"
  on="hover"
  position="top left"
  trigger={
    <Button
      id="special-btn"
      onClick={[Function]}
    >
      a button
    </Button>
  }
/>

我需要我的测试才能再次运行。如何在测试中再次获得对#special-btn 的访问权限,以便我可以在其上调用 .simulate('click')?

问题是你做不到。你需要重写你的测试。您的按钮现在被 Popup 组件包裹,因此您无权访问它。但是您可以将选择器移动到 Popup 并测试单击弹出窗口是否会触发所需的更改。别无他法。

// JSX
<Popup
  trigger={<Button onClick={this.toggleShowThing} id="special-btn">a button</Button>}
  content="Popup Words"
  id="popup"
/>
{this.state.showThing &&
  <div className="special-thing">The Thing's Words</div>
}

// test
it('shows the thing when the button is clicked', () => {
  const wrapper = shallow(<MyComponent />);
  wrapper.find('#popup').simulate('click', { preventDefault() {} });
  expect(wrapper.find('.special-thing').exists()).toBe(true);
});

假设 Popup 是一些已经测试过的第三方组件,我将通过以下方式进行测试:

(1) 找到 Popup 并检查 trigger prop 的 Button 的 onClick prop 是否为 componentWrapper.instance().toggleShowThing

(2) 作为单独的事情,将 this.state.showThing 设置为 false 并验证没有 div with className special-thing 被渲染;将 this.state.showThing 设置为 true 并验证它是否已呈现。

(*) this.toggleShowThing 也要自己测试。

这对我有用,虽然没有文档:

import {shallow, ShallowWrapper} from "enzyme";

it('shows the thing when the button is clicked', () => {
  const wrapper = shallow(<MyComponent />);
  const button = new ShallowWrapper(
    wrapper.find('Popup').prop('trigger'), wrapper
  );
  button.simulate('click', { preventDefault() {} });
  expect(wrapper.find('.special-thing').exists()).toBe(true);
});

换句话说:

  1. 找到 Popup 组件。
  2. 获取在其 trigger 属性中呈现的组件。请注意,这还不是浅层包装器,因此还没有花哨的 API。
  3. 使用 ShallowWrapper 手动创建包装器(传递第二个参数很重要)。
  4. 现在您可以访问所有酶 API 以与按钮交互。

请注意,您似乎可以避免使用构造函数并改用 wrap() 实用方法(也未记录):

  const button = wrapper.wrap(wrapper.find('Popup').prop('trigger'));