如何使用反应酶检查实际的 DOM 节点

Posted

技术标签:

【中文标题】如何使用反应酶检查实际的 DOM 节点【英文标题】:how to check the actual DOM node using react enzyme 【发布时间】:2016-10-09 22:42:02 【问题描述】:

有没有办法获取实际的 DOM 节点,这样我就可以使用 Dom api 来查询它,而不是需要使用酶的 api,这仅适用于边缘情况,例如我需要断言有关 dom 节点的事情自己。

【问题讨论】:

【参考方案1】:

你可以使用wrapper.getDOMNode()

Enzyme docs

【讨论】:

【参考方案2】:

也许您正在寻找酶的instance()?

const wrapper = mount(<input type="text" defaultValue="hello"/>)
console.log(wrapper.instance().value); // 'hello'

PS:

instance() 应该给你一个ReactComponent,你可以从中使用 ReactDOM.findDOMNode(ReactComponent) 来获取一个 DOMNode。但是,当我这样做时,如下所示,它与 wrapper.instance() 完全相同:

import ReactDOM from 'react-dom'
const wrapper = mount(<input type="text" defaultValue="sup"/>)
console.log(ReactDOM.findDOMNode(wrapper.instance()) == wrapper.instance()) // true

我不明白为什么会这样。如果你 console.log() 其中任何一个,你会看到一个 htmlInputElement,但它会包含很多看起来非本地 DOM 节点的东西:

HTMLInputElement 
  '__reactInternalInstance$yt1y6akr6yldi': 
   ReactDOMComponent 
     _currentElement: 
       '$$typeof': Symbol(react.element),
        type: 'input',
        key: null,
        ref: null,
        props: [Object],
        _owner: [Object],
        _store:  ,

【讨论】:

当我尝试您的技术时,它似乎按预期工作。换句话说,ReactDOM.findDOMNode(wrapper.instance()) != wrapper.instance()。 FWIW,我正在使用 React 15 和 Enzyme 2.3.0。 我想知道是不是因为我使用的是 jsdom(或者,我认为我是。愚蠢的我没有指向我运行的代码的永久链接)。你在用jsdom吗? 是的,我使用的是 jsdom 9.1.0 - 抱歉我忘了提 这仅适用于根包装器(React 组件mount()ed 或shallow()ed)。有关更广泛适用的解决方案,请参阅 @tonyjmnz 的答案。【参考方案3】:

我遇到了同样的问题。在我的例子中,我正在测试使用 react-aria-modal 构建的东西,它在 DOM 的不同部分呈现覆盖 div,而不是使用 mount() 呈现的初始元素。为了测试它是否正确呈现,我需要更全面地查看 DOM。为此,我使用了render()attachTo 选项来确保我的测试DOM 看起来应该在真实的浏览器中。 Here 是文档中对该技术的一个很好的一般描述。

根据您的需要,您可以将 Tyler Collier 的方法用于 DOM 的更多本地部分(findDOMNode 使用 instance())或我的方法以获得更全局的视图。

这是我的用例的示例规范,展示了如何设置/使用/拆除模拟 DOM:

import MyModalComponent from '../components/my-modal-component'
import React from 'react'
import  jsdom  from 'jsdom'
import  mount  from 'enzyme'

describe('<MyModalComponent /> Component', function()

  let wrapper

  beforeEach(function()
    window.document = jsdom('')
    document.body.appendChild(document.createElement('div'))
  )

  afterEach(function()
    wrapper.detach()
    window.document = jsdom('')
  )

  it('renders the modal closed by default', () => 
    wrapper = mount(
      <MyModalComponent prop1="foo"
                        prop2="bar"
      />,  attachTo: document.body.firstChild 
    )
    expect(wrapper.html()).to.contain('Content in component')
    expect(document.body.innerHTML).to.not.contain('Content in overlay')
  )

)

【讨论】:

【参考方案4】:

如果你使用 jsdom 创建一个 DOM,类似这样:

import jsdom from 'jsdom';
const doc = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.document = doc;
global.window = doc.defaultView;

然后你可以使用酶的mount() 来渲染你想要测试的任何东西。

然后您可以断言您正在寻找的样式:

expect(wrapper).to.have.style("display", "none");

【讨论】:

据我所知,我正在使用使用 jsdom 的 mount,但是您将如何获取实际包装器的 DOM 节点以便我可以使用 dom api?例如查询 className 但 not 使用 prop('className') 可能有更好的方法,但你总是可以在元素上调用.html(),然后使用类似DOMParser():***.com/questions/3103962/…【参考方案5】:

你可以使用类似的东西:

const dialog = component.find(Modal);
let modal = dialog.node._modal;
modal.getDialogElement().querySelector('#saveBtn')

基于 react-bootstrap 网站中对 Modal 的测试

https://github.com/react-bootstrap/react-bootstrap/blob/master/test/ModalSpec.js

【讨论】:

【参考方案6】:

如果你想打印出整个 DOM,

const wrapper = shallow(<MyComponent/>);
console.log("DOM tree for humans", wrapper.text());

【讨论】:

以上是关于如何使用反应酶检查实际的 DOM 节点的主要内容,如果未能解决你的问题,请参考以下文章

当它被包装在提供者组件中时,如何使用 mocha + 酶 + chai 测试反应原生组件

如何解析 DOM(反应)

你们如何测试复杂的反应原生应用程序?

开玩笑 - 如何测试组件是不是不存在?

方法“props”仅用于在单个节点上运行。 0找到了。酶 - 错误

您如何在控制台中检查反应元素的道具和状态?