将上下文传递给ReactJS中动态添加的子项

时间:2016-06-22 15:35:35

标签: reactjs react-jsx enzyme

我正在尝试将上下文传递给React组件,但因为我正在使用Enzyme进行测试,所以我想动态地将组件添加到其父组件中,以便检查其状态。测试看起来像这样:

describe('<BeaconConfig />', () => {
  it('inherits the config from BeaconConfig', () => {
    mount(<BeaconConfig persistent><div id="parent"></div></BeaconConfig>, { attachTo: document.body });
    const wrapper = mount(<Beacon/>, { attachTo: document.getElementById('parent') });
    expect(wrapper.state('persistent')).to.be(true);
  });
});

测试失败,因为persistent组件状态的Beacon属性为undefined,但它应该通过上下文从BeaconConfig继承。

当我在挂载Beacon时尝试将BeaconConfig直接放在JSX中时,它可以正常工作,但在这种情况下,Enzyme不会让我进入Beacon组件状态它不是根源。

当我将动态添加到其父组件时,React没有将上下文传播到我的组件是否正常?

2 个答案:

答案 0 :(得分:1)

React没有传播上下文是正常的 - 它不会查看DOM并以这种方式将其与VDOM区分开来。

您希望在初始安装中将其设为子项,并使用MountWrapper的.find().children()方法(docs)来挖掘孩子,找到灯塔并做你的断言。

答案 1 :(得分:0)

以下是我最终使用的完整测试:

describe('Context', () => {
  let wrapper;
  let parent;
  const open = stub().returns({});
  const mockIndexedDB = { open };
  const config = mount(<BeaconConfig persistent position="bottom" indexedDB={mockIndexedDB} />);

  beforeEach(() => {
    parent = document.createElement('div');
    document.body.appendChild(parent);
    wrapper = mount(<Beacon>some text</Beacon>, {
      attachTo: parent,
      context: config.instance().getChildContext()
    });
  });

  afterEach(() => {
    wrapper.detach();
    document.body.removeChild(document.body.firstChild);
  });

  it('overrides the default values with the context if any', () => {
    expect(wrapper.state('persistent')).to.be(true);
    expect(wrapper.state('position')).to.be('bottom');
    expect(open.calledOnce).to.equal(true);
  });
});

@STRML提出了一个很好的建议,但我认为不可能访问非根组件的状态。

相反,我会孤立地实例化BeaconConfig并抓住它的子上下文,使用Beacon options参数手动将其传递给mount。这测试BeaconConfig创建正确的子上下文,Beacon正确使用上下文。当后者是后代时,它不测试BeaconConfig将配置传递给Beacon,但我们可以认为这是理所当然的,因为它是基本的React功能。