ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Cypress 组件测试实战:用 @cypress/vue 测试 Vue 命名插槽与具作用域插槽

Cypress 组件测试实战:用 @cypress/vue 测试 Vue 命名插槽与具作用域插槽 Cypress 组件测试实战用 cypress/vue 测试 Vue 命名插槽与具作用域插槽【免费下载链接】cypressFast, easy and reliable testing for anything that runs in a browser.项目地址: https://gitcode.com/GitHub_Trending/cy/cypress本文以 Cypress 仓库中 slots 示例 为主体系统讲解如何用cypress/vue的mount在组件测试中传入命名插槽named slots、默认插槽以及具作用域插槽scoped slots并验证插槽未提供时的回退内容fallback content。读完本文你能掌握slots/scopedSlots挂载选项的完整用法理解其底层是如何直通vue/test-utils的mount的以及如何在真实的 Cypress 组件测试配置中运行这些用例。场景背景cypress/vue 如何挂载组件cypress/vue是 Cypress 官方提供的 Vue 3 组件测试适配器随cypress包一起发布其 README 明确说明它已捆绑在cypress包中通常无需单独安装见 npm/vue/README.md。它的核心导出是mount函数类型系统直接复用了vue/test-utils下文简称 VTU的MountingOptions// 摘自 npm/vue/src/index.ts type MountingOptionsProps, Data {} OmitVTUMountingOptionsProps, Data, attachTo { log?: boolean /** * deprecated use vue-test-utils global instead */ extensions?: GlobalMountOptions { ... } }也就是说除了把attachTo从选项中剔除由适配器内部管理挂载目标其余 VTU 挂载选项——包括本文的主角slots与scopedSlots——都原样透传。这正是 slots 示例 Card.cy.js 顶部注释所强调的Usage is the same as Vue Test Utils, since slots and scopedSlots in the render options are directly passed through to the Utils mount().该示例的运行环境配置见 npm/vue/cypress.config.ts其中component段声明了framework: vue与devServer: { bundler: vite }测试文件采用.cy.js命名约定。被测组件Card.vue 的插槽设计示例取自 Vue Testing Library 的组件测试用例Card.vue 源码注释中指明了出处完整代码如下template div classcard slot nameheader / slot :contentcontent !-- Fallback content if no default slot is given -- pNothing used the {{ content }}/p /slot slot namefooter / /div /template script export default { data () { return { content: Scoped content!, } }, } /script这个组件一次性覆盖了三种插槽形态插槽写法关键点命名插槽headerslot nameheader /调用方需以header为键提供内容默认插槽回退内容slot :contentcontent.../slot标签内pNothing used the {{ content }}/p是回退内容调用方不提供默认插槽时渲染它具作用域插槽:contentcontent把组件内部data中的content值为Scoped content!通过属性绑定暴露给插槽内容供其解构使用注释中解释了为何要“把简单字符串传进默认插槽”——纯粹是为了演示 scoped slots 的测试方式。编写测试三种插槽形态各一条用例完整测试文件见 Card.cy.js三个用例分别验证“未提供插槽”“提供命名插槽”“提供具作用域插槽”。用例一不提供任何插槽验证回退内容it(skipped slots, () { mount(Card) cy.contains(Nothing used the Scoped content!).should(be.visible) })只传入组件本身即可。默认插槽未被占用Vue 渲染模板中的回退内容pNothing used the {{ content }}/p其中{{ content }}插值为组件data中的Scoped content!因此断言文案是Nothing used the Scoped content!。用例二以 render 函数提供命名插槽it(renders slots, () { // TODO: use HTML syntax (not render function with h) // when its working. // Blocked by upstream bug in Test Utils: https://github.com/vuejs/test-utils/issues/1166 // mount(Card, { // slots: { // header: h1HEADER/h1 // }, // }) mount(Card, { slots: { header: () h(h1, HEADER), footer: () h(div, FOOTER), }, }) cy.contains(h1, HEADER) cy.contains(div, FOOTER) })两个要点mount的第二个参数中slots是一个以插槽名为键的对象每个值是一个返回 VNode 的函数。这里用 Vue 的h渲染函数构造内容文件顶部import { h } from vue。被注释掉的header: h1HEADER/h1HTML 字符串写法因上游 VTU 的 bug 而暂时不可用源码注释保留了该写法与问题链接等待上游修复后可切换为更直观的 HTML 字符串形式。写插槽测试时建议直接采用 render 函数写法。用例三具作用域插槽——消费组件透出的作用域数据it(renders scopedSlots, () { mount(Card, { slots: { default: ({ content }) h(div, {}, h(p, Yay! ${content})), }, }) cy.contains(Yay! Scoped content!).should(be.visible) cy.contains(Nothing used the Scoped content!).should(not.exist) })scoped slot 的核心机制slots.default的值是一个接收作用域对象的函数。Card 通过:contentcontent把Scoped content!传出来测试中的({ content }) ...解构取出该值渲染为Yay! Scoped content!。断言有两层一是确认插槽内容正确渲染should(be.visible)二是确认回退内容被替换should(not.exist)——这正好与用例一形成互补证明“默认插槽被占用时回退内容不再生效”。源码纵深slots选项在 mount 内部发生了什么回到 npm/vue/src/index.ts 中的mount实现可以确认插槽选项确实没有经过任何特殊处理原样进入 VTU// 关键调用链npm/vue/src/index.ts const el getContainerEl() // 找到 [data-cy-root] 容器 const componentNode document.createElement(div) componentNode.id VUE_ROOT // __cy_vue_root el.append(componentNode) const wrapper VTUmount(componentOptions, { attachTo: componentNode, ...options })从源码结构看...options展开时slots与scopedSlots会一并透传给VTUmount即vue/test-utils的mountattachTo指向刚挂到[data-cy-root]容器下的#__cy_vue_root节点。挂载完成后Cypress.vueWrapper/Cypress.vue被赋值为 wrapper 与组件实例便于在测试中直接访问组件状态每次调用mount前会先执行cleanup()卸载上一个测试挂载的组件并移除#__cy_vue_root节点保证测试间 DOM 隔离挂载后cy.wait(1)并打印ComponentName ... /形式的命令日志可用log: false关闭。容器与清理逻辑来自共享包 npm/mount-utils/src/index.tsgetContainerEl要求页面中存在data-cy-root属性的根元素否则抛错setupHooks会在组件测试中覆写cy.visit/cy.session/cy.origin使其直接报错组件测试不允许整页跳转并注册test:before:after:run钩子触发cleanup回调。运行方式与适用前提在仓库的 npm/vue/package.json 中提供了如下脚本{ cy:open: node ../../scripts/cypress.js open --component --project ${PWD}, cy:run: node ../../scripts/cypress.js run --component --project ${PWD}, test: yarn cy:run }即在npm/vue目录下执行yarn cy:open打开交互式测试界面或yarn test无头运行全部组件测试含 slots 目录下以.cy.js命名的用例。适用前提与限制面向Vue 3peerDependencies要求vue 3.0.0开发依赖锁定vue 3.2.47与vue/test-utils 2.4.6示例使用 Vue 3 的h渲染函数 APIVue 2 时代scopedSlots的function(props)选项写法不适用于本示例slots值若希望用 HTML 字符串需等待上游 VTU 修复如用例二注释所述当前请统一使用 render 函数组件测试场景下cy.visit被禁用断言只能针对当前挂载的组件 DOM 本身。小结这份 slots 示例虽然只有两个文件却构成了一个完整的 Vue 插槽测试模板Card.vue 集中了命名插槽、回退内容与作用域插槽三种形态Card.cy.js 则演示了对应的三种挂载断言策略——验证回退可见、验证插槽替换、验证作用域数据透出。由于cypress/vue的mount对 VTU 选项是直通设计你在 Vue Test Utils 文档中查到的slots/scopedSlots配置在 Cypress 组件测试中同样适用只需注意用 render 函数提供插槽内容、并针对“提供 / 未提供插槽”两种分支分别断言即可。【免费下载链接】cypressFast, easy and reliable testing for anything that runs in a browser.项目地址: https://gitcode.com/GitHub_Trending/cy/cypress创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表