ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Enzyme ReactWrapper.getElements() 方法详解:获取被包装的 ReactElement 数组

2026/9/20 12:46:09 拓冰建站 浏览量
Enzyme ReactWrapper.getElements() 方法详解:获取被包装的 ReactElement 数组 Enzyme ReactWrapper.getElements() 方法详解获取被包装的 ReactElement 数组【免费下载链接】enzymeJavaScript Testing utilities for React项目地址: https://gitcode.com/gh_mirrors/en/enzyme.getElements()是 Enzyme 中ReactWrapper以及ShallowWrapper提供的核心读取方法用于取出当前 wrapper 所包装的全部 React 元素ReactElement并以数组形式返回。本文以 docs/api/ReactWrapper/getElements.md 为主线结合仓库源码与共享测试用例完整讲解其返回语义、内部实现、与getElement()的差异以及基于 RST 节点树的底层转换原理帮助你在断言与调试中准确、高效地使用该 API。方法签名与返回语义.getElements() ArrayReactElement返回值ArrayReactElement——当前 wrapper 内部包装的所有 ReactElement 组成的数组。核心语义原文要点完整继承该方法返回被包装的 ReactElementsthe wrapped ReactElements如果当前 wrapper 正包装着根组件则返回该根组件最新一次渲染输出latest render output构成的数组。这意味着.getElements()读取的是 wrapper 当前持有的、经渲染后生成的元素快照而不是组件类定义或实例。无论 wrapper 通过mount()、shallow()创建还是通过.find()、.filter()、.first()等衍生方法获得.getElements()都会忠实返回该 wrapper 对应的元素数组。官方示例const one span /; const two span /; function Test() { return ( div {one} {two} /div ); } const wrapper mount(Test /); expect(wrapper.find(span).getElements()).to.deep.equal([one, two]);在该示例中mount(Test /)完整渲染组件树wrapper.find(span)定位到两个span /节点.getElements()返回[one, two]与原始 JSX 元素通过deep.equal断言完全一致。需要注意这里的深相等建立在one、two是模块级常量的基础上由于它们是同一个引用、相同的key/props转换回元素后能与原始元素深度相等。若在渲染内联创建元素则应优先使用.at(index)配合.getElement()逐个取元素比较。源码实现getElements() 的调用链.getElements()并非凭空返回元素而是经历wrapper 持有节点 → 适配器转换 → 映射为数组的完整链路。见 packages/enzyme/src/ReactWrapper.js/** * Returns the wrapped ReactElements. * * return {ArrayReactElement} */ getElements() { return this[NODES].map((n) getAdapter(this[OPTIONS]).nodeToElement(n)); }分解这条调用链this[NODES]wrapper 内部持有的 RST 节点React Standard Tree node数组即当前 wrapper 包装的全部节点getAdapter(this[OPTIONS])根据 wrapper 创建时的选项解析出当前 React 版本对应的适配器adapter参见 packages/enzyme/src/getAdapter.jsnodeToElement(n)由适配器将每个 RST 节点还原为 ReactElement.map(...)逐节点转换并组装成结果数组。ShallowWrapper的实现与之对称见 packages/enzyme/src/ShallowWrapper.jsgetElements() { return this.getNodesInternal().map((n) getAdapter(this[OPTIONS]).nodeToElement(n)); }两者唯一差别在于ShallowWrapper在取内部节点前会先调用getNodesInternal()若 wrapper 是根 wrapper 且仅包装单个节点会先执行this.update()刷新渲染输出从而保证返回的是最新一次渲染输出对应文档中根组件语义相关逻辑见 packages/enzyme/src/ShallowWrapper.js。nodeToElement从 RST 节点还原 ReactElementnodeToElement是 EnzymeAdapter 定义的抽象接口各 React 版本适配器都必须实现它见 packages/enzyme/src/EnzymeAdapter.js// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed // in order to implement the Wrapper.mount() and Wrapper.shallow() methods, but should // be pretty straightforward for people to implement. // eslint-disable-next-line class-methods-use-this, no-unused-vars nodeToElement(node) { throw unimplementedError(nodeToElement, EnzymeAdapter); }基类直接抛出未实现错误强制各适配器提供具体实现。以 React 16 适配器为例见 packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed // in order to implement the Wrapper.mount() and Wrapper.shallow() methods, but should // be pretty straightforward for people to implement. nodeToElement(node) { if (!node || typeof node ! object) return null; const { type } node; return React.createElement(unmemoType(type), propsWithKeysAndRef(node)); }实现要点对空节点或非对象节点直接返回null通过unmemoType(type)还原组件类型处理React.memo包裹的场景通过propsWithKeysAndRef(node)将节点上的key、ref一并还原到 props 中。仓库中 packages/enzyme-adapter-react-13、packages/enzyme-adapter-react-14、packages/enzyme-adapter-react-15、packages/enzyme-adapter-react-16.1 等各版本适配器均实现了同名的nodeToElement方法接口保持一致——这正是.getElements()能够在不同 React 版本下统一返回 ReactElement 数组的底层保证。与 getElement() 的对比.getElements()是.getElement()的复数版本二者是一对互补 API方法返回类型适用场景失败行为.getElement()ReactElementwrapper 恰好包装单个节点时取唯一元素包装多个节点时通过single()抛出异常.getElements()ArrayReactElement任意节点数量总是返回数组无节点时返回空数组[]对应文档见 docs/api/ReactWrapper/getElement.md 与 docs/api/ShallowWrapper/getElement.md。从源码看getElement()内部调用了this.single(getElement, ...)见 packages/enzyme/src/ReactWrapper.jssingle()会对节点数量做校验因此多节点 wrapper 必须使用.getElements()例如wrapper.find(span)命中多个元素时const wrapper mount(Test /); // ✅ 正确返回包含所有 span 元素的数组 const spans wrapper.find(span).getElements(); // ❌ 错误getElement() 在包装多个节点时会抛出异常 // const single wrapper.find(span).getElement();根组件包装场景当 wrapper 直接包装根组件未经.find()等衍生时.getElements()返回根组件最新渲染输出构成的单元素数组等价于[wrapper.getElement()]const wrapper mount(Test /); expect(wrapper.getElements()).to.have.lengthOf(1); expect(wrapper.getElements()[0]).to.equal(wrapper.getElement());历史演进取代已废弃的 getNodes().getElements()是 Enzyme 3 之后推荐的取值 API取代了早期版本的.getNodes()。仓库源码中保留了明确的弃用提示在 packages/enzyme/src/ReactWrapper.js 中getNodes()直接抛出错误getNodes() { throw new Error(ReactWrapper::getNodes() is no longer supported.); }在 packages/enzyme/src/ShallowWrapper.js 中错误信息进一步给出迁移指引getNodes() { throw new Error(ShallowWrapper::getNodes() is no longer supported. Use ShallowWrapper::getElements() instead); }旧的nodes属性访问同样被标记为私有并提示迁移见 packages/enzyme/src/ReactWrapper.jsprivateWarning(nodes, Consider using the getElements() method instead.);因此新代码中应统一使用.getElements()旧代码中的.getNodes()/.nodes需要迁移。测试验证共享测试套件中的行为约束Enzyme 的共享测试套件对.getElements()的行为做了明确约束见 packages/enzyme-test-suite/test/shared/methods/getElements.jsxdescribe(.getElements(), () { // FIXME: figure out why this fails on 15.0, 15.1, 15.2 and 15.3 itIf(!is(~15.0 || ~15.1 || ~15.2 || ~15.3), returns the wrapped elements, () { const one span /; const two span /; class Test extends React.Component { render() { return ( div {one} {two} /div ); } } const wrapper Wrap(Test /); expect(wrapper.find(span).getElements()).to.deep.equal([one, two]); }); });该测试要点通过Wrap抽象同时覆盖mount与shallow两种包装方式验证经过.find()后依然能取回原始元素数组的核心行为测试文件中的itIf条件表明在 React 15.015.3 的特定版本上该用例存在已知差异对应源码中的FIXME注释使用这些旧版本时需要留意.getElements()的结果可能与预期不完全一致该共享方法还被flatMap、deprecatedInstanceProperties等测试复用见 packages/enzyme-test-suite/test/shared/methods/flatMap.jsx说明.getElements()是构建其他取值逻辑的基础能力。常见使用场景与最佳实践1. 断言渲染输出内容配合deep.equal或deep.eql对渲染结果做结构性断言const wrapper mount(Test /); expect(wrapper.find(li).getElements()).to.deep.equal([ li keyaA/li, li keybB/li, ]);注意断言的元素最好使用与渲染时相同的常量引用或相同的key/props组合以确保深度相等成立。2. 遍历元素并提取 props 数据const wrapper mount(Test /); const texts wrapper.find(button).getElements().map((el) el.props.children); expect(texts).to.deep.equal([保存, 取消]);由于.getElements()返回标准 ReactElement每个元素都可通过el.type、el.props、el.key、el.ref直接读取结构化信息。3. 判断 wrapper 是否包含特定元素const elements wrapper.find(span).getElements(); expect(elements).to.include.members([one, two]);4. 与调试工具链配合当断言失败时可将.getElements()的结果配合.debug()输出见 docs/api/ReactWrapper/debug.md快速定位渲染差异。使用前提与限制适配器要求.getElements()依赖当前配置的 adapter 实现nodeToElement。使用官方 React 适配器react-13 至 react-16.3见 packages/enzyme-adapter-react-16 等均开箱即用自定义适配器必须实现该方法否则基类会抛出nodeToElement is a required method of EnzymeAdapter错误版本差异React 15.015.3 下存在测试标记的已知行为差异升级或降级 React 版本后建议重跑相关断言快照语义getElements()返回的是调用时刻 wrapper 持有的节点快照若在组件更新后需要最新输出对根 wrapper 请先触发更新ShallowWrapper内部会自动update()ReactWrapper则依赖其持有的最新节点。小结.getElements()以一行.map()调用将 wrapper 内部的 RST 节点通过适配器的nodeToElement完整还原为 ReactElement 数组是 Enzyme 中读取渲染结果类 API 的核心组成。它取代了旧版.getNodes()与.getElement()形成单数/复数互补单节点场景用.getElement()多节点与遍历场景用.getElements()。结合 共享测试套件 与各 React 版本适配器实现开发者可以放心地用它编写精确、稳定的渲染断言。相关文档.getElement() ReactElementReactWrapper.getElements() ArrayReactElementShallowWrapper.at(index) ReactWrapper.debug() Stringmount 完整渲染 APIshallow 浅渲染 API【免费下载链接】enzymeJavaScript Testing utilities for React项目地址: https://gitcode.com/gh_mirrors/en/enzyme创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考