enzyme ShallowWrapper 的 `.not(selector)` 方法:按选择器反向过滤节点的完整指南

enzyme ShallowWrapper 的 `.not(selector)` 方法:按选择器反向过滤节点的完整指南 测试前端【免费下载链接】enzymeJavaScript Testing utilities for React项目地址https://gitcode.com/gh_mirrors/en/enzyme点击查看免费下载.not(selector)是 enzyme 为ShallowWrapper提供的反向过滤 API它返回一个新的 wrapper只包含当前 wrapper 中不匹配指定选择器的节点。它常与.find()链式配合使用用于排除符合某条件的一批节点也可以单独在任意 wrapper 上对现有节点做筛选。本文以官方 API 文档为基础结合仓库源码与共享测试用例讲解其签名、行为、支持的选择器类型、底层实现原理及常见坑位帮助你准确掌握这个过滤的取反工具。API 签名与语义官方文档给出的签名与描述如下.not(selector) ShallowWrapperReturns a new wrapper with only the nodes of the current wrapper that dont match the provided selector.即返回一个新 wrapper仅包含当前 wrapper 中不匹配所给选择器的节点。文档明确说明This method is effectively the negation or inverse offilter.也就是说对同一组节点分别调用filter(selector)与not(selector)二者取到的节点集合互为补集前提是节点总数确定。参数与返回值项目说明参数selectorEnzymeSelector要匹配的选择器返回值ShallowWrapper包装了过滤后节点的新 wrapper其中EnzymeSelector支持四种形式详见 docs/api/selector.mdCSS 选择器子集类名.foo、标签名div、id#foo、属性[hreffoo]、通配*以及 React 组件名与 props 组合如Button[typesubmit]React 组件构造函数直接传入组件引用只按组件类型判断忽略 props 与 children组件的 displayName 字符串仅当字符串以大写字母开头时才按 displayName 匹配小写开头的字符串会被当作 CSS 标签名对象属性选择器如{ foo: 3 }按 props 子集匹配属性值不允许为undefined否则抛出TypeError。官方示例文档示例展示了not与find链式使用的典型场景const wrapper shallow(MyComponent /); expect(wrapper.find(.foo).not(.bar)).to.have.lengthOf(1);含义是先find(.foo)取出所有带foo类的节点再用.not(.bar)排除其中带bar类的节点最终断言剩下的节点数为 1。结合源码理解实现not是如何工作的not的实现在 packages/enzyme/src/ShallowWrapper.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 {ShallowWrapper} */ not(selector) { const predicate buildPredicate(selector); return filterWhereUnwrapped(this, (n) !predicate(n)); }实现路径非常清晰buildPredicate(selector)把选择器编译成一个单节点匹配判定函数predicate(n)见 packages/enzyme/src/selectors.js。它对字符串选择器走 CSS token 解析分支对函数/组件构造函数走元素类型匹配分支对非空对象走 props 匹配分支并分别抛出相应TypeError如 props 含undefined、空对象、数组、null。取反用(n) !predicate(n)对判定结果取反这正是not与filter的唯一差异。对比filter的实现同文件 L1065-L1068它传的是predicate本身而not传的是取反后的函数。filterWhereUnwrapped对内部节点数组执行过滤并重新包装见 packages/enzyme/src/ShallowWrapper.jsfunction filterWhereUnwrapped(wrapper, predicate) { return wrapper.wrap(wrapper.getNodesInternal().filter(predicate).filter(Boolean)); }getNodesInternal()取当前 wrapper 的所有节点filter(predicate)保留通过判定的节点随后filter(Boolean)剔除空值最后wrap生成新的ShallowWrapper返回。因此not返回的始终是一个新 wrapper不会修改原 wrapper。值得注意的是同名方法也存在于ReactWrapper上见 packages/enzyme/src/ReactWrapper.js实现逻辑与浅渲染版本完全一致因此本文讨论的语义与注意事项同样适用于完整挂载场景。一个重要限制不支持复杂 CSS 选择器从buildPredicate的字符串分支可以看到selectors.js当选择器包含组合器如空格后代、、、~时会被判定为复杂选择器并直接抛出if (isComplexSelector(tokens)) { throw new TypeError(This method does not support complex CSS selectors); }也就是说.not(.foo .bar)这类带层级组合的写法会直接报错应改用.findWhere()配合自定义谓词实现等价过滤。实战示例多种选择器形式下的反向过滤仓库的共享测试 packages/enzyme-test-suite/test/shared/methods/not.jsx 给出了可运行、可验证的完整用例const wrapper Wrap(( div div classNamefoo bar baz / div classNamefoo / div classNamebar baz / div classNamebaz / div classNamefoo bar / /div )); expect(wrapper.find(.foo).not(.bar)).to.have.lengthOf(1); expect(wrapper.find(.baz).not(.foo)).to.have.lengthOf(2); expect(wrapper.find(.foo).not(div)).to.have.lengthOf(0);逐条拆解find(.foo)得到 3 个节点foo bar baz、foo、foo bar.not(.bar)排除带bar的 2 个剩 1 个find(.baz)得到 3 个节点foo bar baz、bar baz、baz.not(.foo)排除带foo的 1 个剩 2 个find(.foo)的 3 个节点都是div.not(div)按标签名全部排除剩 0 个——这验证了.not同样支持标签名选择器。除 CSS 选择器外.not也接受其他EnzymeSelector形式例如// 按组件构造函数排除 expect(wrapper.find(MyComponent).not(OtherComponent)).to.have.lengthOf(2); // 按 displayName 排除字符串需以大写字母开头 expect(wrapper.find(MyComponent).not(OtherComponent)).to.have.lengthOf(2); // 按 props 对象排除 expect(wrapper.find(span).not({ type: text })).to.have.lengthOf(3); // 对象属性值不能为 undefined否则抛 TypeError wrapper.find(span).not({ foo: 3, bar: undefined }); // TypeError需要搜索属性值是否为 undefined这种场景时请改用.findWhere()对象属性选择器对此会直接抛错参见 docs/api/selector.md 的 Undefined Properties 一节。与相关方法的辨析文档末尾给出了两个相关方法.filterWhere(predicate) ShallowWrapper接受一个ShallowWrapper Boolean的谓词函数而非选择器适用于无法用选择器表达的复杂判定例如类型不是字符串的复合组件.filter(selector) ShallowWrapper语义上与not完全互逆filter保留匹配节点not保留不匹配节点。三者的取舍建议需求推荐方法排除匹配某选择器的节点.not(selector)保留匹配某选择器的节点.filter(selector)按自定义函数条件过滤.filterWhere(fn)配合!fn亦可实现取反由于not的底层判定仍然来自buildPredicate它与.find()、.filter()、.is()、.some()、.every()等方法共享同一套选择器解析逻辑掌握 docs/api/selector.md 中列出的选择器规则就能在所有接受EnzymeSelector的 API 间无缝迁移。小结.not(selector)是 enzyme 浅渲染测试中做排除式筛选的标准工具它基于buildPredicate编译选择器、对判定结果取反再通过filterWhereUnwrapped返回一个新 wrapper实现上非常轻量。使用时注意三点选择器不支持复杂 CSS 组合写法会抛TypeError对象选择器属性值不可为undefined返回的新 wrapper 与原 wrapper 相互独立可安全链式断言。赞分享测试前端【免费下载链接】enzymeJavaScript Testing utilities for React项目地址https://gitcode.com/gh_mirrors/en/enzyme点击查看免费下载相关推荐enzyme .filter(selector) 方法详解在 ShallowWrapper 中按选择器精确筛选节点enzyme .filter selector 方法详解在 ShallowWrapper 中按选择器精确筛选节点 .filter selector 是 enz测试前端enzyme 中 .not(selector) 方法详解如何过滤出所有不匹配选择器的节点enzyme 中 .not selector 方法详解如何过滤出所有不匹配选择器的节点 导读 .not selector 是 enzyme 为 ReactWr测试前端enzyme ReactWrapper.filter(selector) 完全指南按选择器精确筛选渲染树节点enzyme ReactWrapper.filter selector 完全指南按选择器精确筛选渲染树节点 导读 .filter selector 是 enz测试前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考