enzyme 中 `.not(selector)` 方法详解:如何过滤出所有不匹配选择器的节点
测试前端【免费下载链接】enzymeJavaScript Testing utilities for React项目地址https://gitcode.com/gh_mirrors/en/enzyme点击查看免费下载导读.not(selector)是 enzyme 为ReactWrapper由mount()产生与ShallowWrapper由shallow()产生提供的筛选方法它返回一个仅包含当前 wrapper 中不匹配指定选择器的节点的新 wrapper本质上是.filter(selector)的逻辑取反。本文以 docs/api/ReactWrapper/not.md 为核心结合仓库源码与共享测试用例完整讲解其签名、参数类型、返回值、底层实现原理与实战用法帮助你在测试断言中熟练运用排除法筛选节点。方法签名与核心语义.not(selector) ReactWrapper // mount 渲染后的完整 DOM 树 .not(selector) ShallowWrapper // shallow 渲染的单层组件树官方文档给出的定义非常精炼Returns a new wrapper with only the nodes of the current wrapper that dont match the provided selector.This method is effectively the negation or inverse offilter.翻译过来就是返回一个新 wrapper其中只保留当前 wrapper 中不匹配所提供选择器的节点该方法本质上是filter的否定或逆操作。换言之下面两条语句在逻辑上是等价的wrapper.not(selector) // 等价于 wrapper.filter((node) !matches(node, selector))它非常适合从一组节点中剔除某几类节点的场景例如找出所有带foo类但不带bar类的元素、找出所有div以外的元素等。参数Arguments方法只有一个参数参数类型说明selectorEnzymeSelector用于匹配节点的选择器EnzymeSelector在 enzyme 中一共支持三类形态这一事实可从 packages/enzyme/src/selectors.js 的buildPredicate实现中得到印证字符串形式的简单 CSS 选择器如.foo、div、[data-foobar]、#id。注意not底层复用的buildPredicate只支持简单选择器传入包含组合符如div span、.a .b的复杂 CSS 选择器会抛出TypeError: This method does not support complex CSS selectors。组件构造函数Component Constructor用于按组件类型筛选例如not(MyComponent)。非空属性对象props object键值对作为要匹配的 props例如not({ disabled: true })。若对象中包含undefined值会抛出TypeError: Enzyme::Props cant have \undefined values. Try using findWhere() instead.。返回值Returns对于ReactWrapper返回ReactWrapper——一个包装了过滤后节点的新 wrapper。对于ShallowWrapper返回ShallowWrapper——语义相同类型对应。返回的是新的wrapper 实例原 wrapper 不会被修改因此可以继续链式调用其他方法。底层实现原理源码级解析虽然文档很短但源码实现非常清晰值得展开。.not在ReactWrapper与ShallowWrapper两个类中的实现完全一致ReactWrapper 实现packages/enzyme/src/ReactWrapper.js/** * Returns a new wrapper instance with only the nodes of the current wrapper that did not match * the provided selector. Essentially the inverse of filter. * * param {EnzymeSelector} selector * returns {ReactWrapper} */ not(selector) { const predicate buildPredicate(selector); return filterWhereUnwrapped(this, (n) !predicate(n)); }ShallowWrapper 实现packages/enzyme/src/ShallowWrapper.jsnot(selector) { const predicate buildPredicate(selector); return filterWhereUnwrapped(this, (n) !predicate(n)); }整个流程可拆解为三步构建谓词函数buildPredicate(selector)位于 packages/enzyme/src/selectors.js负责把字符串选择器解析为 tokensafelyGenerateTokens、按组件类型或 props 对象分别生成对应的节点匹配函数nodeMatchesToken/matchesElementType/nodeMatchesObjectProps。取反(n) !predicate(n)把匹配选择器的谓词翻转成不匹配选择器的谓词——这正是not与filter的唯一差别其余逻辑 100% 复用。过滤并重新包装调用filterWhereUnwrappedReactWrapper.jsfunction filterWhereUnwrapped(wrapper, predicate) { return wrapper.wrap(wrapper.getNodesInternal().filter(predicate).filter(Boolean)); }getNodesInternal()取出当前 wrapper 内部持有的全部节点数组.filter(predicate)执行筛选.filter(Boolean)剔除因 React 条件渲染可能残留的null/false空节点最后通过wrapper.wrap(...)生成并返回一个新的 wrapper。这一实现同时解释了文档中Returns a new wrapper的语义原始 wrapper 的节点列表不会受影响。使用示例文档原始示例以mount为例ReactWrapperconst wrapper mount(MyComponent /); expect(wrapper.find(.foo).not(.bar)).to.have.lengthOf(1);含义先find(.foo)找出所有带foo类的节点再.not(.bar)从中剔除带bar类的节点最终断言剩下的节点数量为 1。官方共享测试用例仓库中 packages/enzyme-test-suite/test/shared/methods/not.jsx 提供了更丰富的验证场景该测试文件同时被ReactWrapper-spec与ShallowWrapper-spec复用因此下列断言对两种 wrapper 都成立const wrapper Wrap(( div div classNamefoo bar baz / div classNamefoo / div classNamebar baz / div classNamebaz / div classNamefoo bar / /div )); // 5 个节点中带 .foo 的有 3 个foo bar baz、foo、foo bar其中带 .bar 的有 2 个 // 剔除后剩下 1 个纯 .foo 节点 expect(wrapper.find(.foo).not(.bar)).to.have.lengthOf(1); // 带 .baz 的有 3 个foo bar baz、bar baz、baz其中带 .foo 的有 1 个 // 剔除后剩下 2 个 expect(wrapper.find(.baz).not(.foo)).to.have.lengthOf(2); // 带 .foo 的 3 个节点全部是 div剔除所有 div 后为 0 个 expect(wrapper.find(.foo).not(div)).to.have.lengthOf(0);更多实战写法shallow场景ShallowWrapper与mount完全同构const wrapper shallow(MyComponent /); expect(wrapper.find(.foo).not(.bar)).to.have.lengthOf(1);按组件类型过滤适用于浅渲染下的自定义组件const wrapper shallow( div Foo / Foo / Bar / /div ); expect(wrapper.find(Foo)).to.have.lengthOf(2); expect(wrapper.find(div).not(Foo)).to.have.lengthOf(1); // 只剩根 div按 props 对象过滤const wrapper mount( ul li disableda/li lib/li li disabledc/li /ul ); // 找出所有未禁用没有 disabled 属性的 li expect(wrapper.find(li).not({ disabled: true })).to.have.lengthOf(1);组合断言场景——包含 A 但不包含 B的经典写法const wrapper mount(MyComponent /); // 所有包含 btn 类的节点中剔除同时包含 btn--disabled 类的节点 const enabledButtons wrapper.find(.btn).not(.btn--disabled); expect(enabledButtons).to.have.lengthOf(2);由于not返回新的 wrapper可以继续链式调用.hostNodes()、.at(index)、.first()等方法进行二次筛选与取值const wrapper mount(MyComponent /); const firstEnabled wrapper.find(.item).not(.item--hidden).first();not与相关方法的对比文档末尾列出了两个密切相关的兄弟方法.filterWhere(predicate) ReactWrapper接受谓词函数而非选择器对每个节点调用predicate(wrapper)保留返回true的节点。not恰好可以看成filterWhere的反选形态.not(sel)等价于filterWhere((n) !n.is(sel))。.filter(selector) ReactWrapper接受同样的EnzymeSelector但保留的是匹配选择器的节点是not的直接逆操作。三者对比速查方法参数保留规则底层复用.filter(selector)EnzymeSelector匹配选择器buildPredicatefilterWhereUnwrapped.not(selector)EnzymeSelector不匹配选择器buildPredicate取反 filterWhereUnwrapped.filterWhere(predicate)函数谓词返回truefilterWhereUnwrapped从 ReactWrapper.js 的源码可以看到三者是相邻实现的filter与not共享buildPredicate区别仅在谓词是否取反——这也是为什么文档称not是filter的 negation or inverse。另外需要注意not是对当前 wrapper 已有节点的筛选不深入渲染树查找后代若需要查找并排除应先用.find(selector)定位节点集再在其结果上调用.not()。常见问题与注意事项不支持复杂 CSS 选择器not底层走buildPredicate对包含后代/子代组合符的选择器如.parent .child会直接抛出TypeError。需要按谓词逻辑筛选时请改用.filterWhere(predicate)。props 对象不能含undefined值{ disabled: undefined }会触发类型错误请改用filterWhere。空结果也是合法结果所有节点都匹配选择器时如示例中find(.foo).not(div)返回的 wrapper 长度为 0用于断言全部符合或不存在例外非常顺手。不影响原 wrappernot返回新 wrapper原 wrapper 的节点集合与length保持不变可放心继续使用。两种渲染模式行为一致由于两个 wrapper 类共用同一套filterWhereUnwrapped与buildPredicatemount与shallow下.not的语义完全对齐docs/api/ShallowWrapper/not.md 提供了同构的文档说明共享测试 not.jsx 也同时覆盖两种 wrapper。小结.not(selector)是 enzyme 节点筛选中排除法的核心工具它复用filter的选择器解析与过滤管线仅对谓词取反从而在 ReactWrapper 与 ShallowWrapper 上提供一致、可链式调用、不修改原 wrapper 的反向筛选能力。掌握它与.filter、.filterWhere的差异就能用最少的代码写出排除特定节点的精确断言。赞分享测试前端【免费下载链接】enzymeJavaScript Testing utilities for React项目地址https://gitcode.com/gh_mirrors/en/enzyme点击查看免费下载相关推荐Enzyme 的 .some(selector) 方法如何判断包装器中是否存在匹配节点Enzyme 的 .some selector 方法如何判断包装器中是否存在匹配节点 .some selector 是 enzyme 为 ReactWrapp测试前端Enzyme 选择器匹配判定全面解析 .is(selector) 方法ReactWrapper / ShallowWrapperEnzyme 选择器匹配判定全面解析 .is selector 方法ReactWrapper / ShallowWrapper 本文围绕 enzyme 核测试前端Enzyme ReactWrapper.exists() 方法完全指南检测节点存在性与选择器匹配Enzyme ReactWrapper.exists 方法完全指南检测节点存在性与选择器匹配 .exists 是 Enzyme 测试工具库中用于判断 Wrap测试前端上一篇Grug-12B性能优化技巧10个方法提升推理速度与准确性下一篇Claudable数据库集成Supabase连接配置与实时数据处理完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

React Native Elements 主题定制完全指南:从 containerStyle 到 ThemeProvider 的组件样式体系

React Native Elements 主题定制完全指南:从 containerStyle 到 ThemeProvider 的组件样式体系

React Native Elements 主题定制完全指南:从 containerStyle 到 ThemeProvider 的组件样式体系 【免费下载链接】react-native-elements Cross-Platform React Native UI Toolkit 项目地址: https://gitcode.com/gh_mirrors/re/react-native-elements React …

2026/11/11 15:59:24 阅读更多 →
毕业论文知识图谱构建:SpringBoot+Vue+Neo4j实战

毕业论文知识图谱构建:SpringBoot+Vue+Neo4j实战

简介:本资源是一套面向高校计算机专业教师、毕业设计指导者及高年级本科生的毕业论文知识图谱构建与可视化教学原型系统,聚焦教育领域中毕业设计质量监控与技术热点分析的实际需求。系统基于SpringBoot后端与Vue前端实现,集成Neo4j图数据库与…

2026/11/11 1:45:12 阅读更多 →
把 OpenClaw 的 openclaw.json 改到 TaoToken 通道,Supervisor 与 Worker 各跑各的

把 OpenClaw 的 openclaw.json 改到 TaoToken 通道,Supervisor 与 Worker 各跑各的

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 21:29:11 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/10 23:32:01 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/10 23:32:03 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/11 2:31:33 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/10 16:14:15 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/10 12:51:50 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/10 23:32:10 阅读更多 →

日新闻

周新闻

月新闻