npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-plugin-vant-testid

v1.0.2

Published

Vite plugin to auto-inject data-testid into Vue component templates for E2E testing with Vant UI

Readme

vite-plugin-vant-testid

English

一个 Vite 插件,自动为 Vant UI 组件的 DOM 元素注入 data-testid 属性,让 Playwright、Cypress、Testing Library 等 E2E 测试工具的选择器稳定可靠、零维护。

动机

在大型 Vue 应用中为每个 Vant 组件手动添加 data-testid 既繁琐又容易出错。随着 UI 迭代,选择器经常失效,测试变得不稳定。本插件通过两层自动注入解决此问题:

  • 编译期:Vue 模板编译器 transform 生成稳定的、模板作用域内的 testid(如 van-button-0van-field-1)。
  • 运行时:基于 MutationObserver 的注入器为弹出层面板、Teleport 渲染的组件以及子元素补注入 testid,覆盖编译期无法触及的场景。

安装

pnpm add -D vite-plugin-vant-testid
# 或
npm install -D vite-plugin-vant-testid
# 或
yarn add -D vite-plugin-vant-testid

Peer dependenciesvite >=5.0.0vue >=3.3.0vant >=4.0.0

快速上手

推荐方案:编译器 + Vue 插件 + 运行时

此方案能生成稳定的 testid(重渲染不变),同时拥有完整的运行时覆盖。

// vite.config.ts
import vue from '@vitejs/plugin-vue'
import { vueTestIdPlugin, testIdTransforms } from 'vite-plugin-vant-testid'

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          nodeTransforms: testIdTransforms(),
        },
      },
    }),
    vueTestIdPlugin(),
  ],
})
// main.ts
import { createApp } from 'vue'
import { createTestIdBridge } from 'vite-plugin-vant-testid/plugin'
import { setupVantTestIds } from 'vite-plugin-vant-testid/runtime'
import App from './App.vue'

const app = createApp(App)
app.use(createTestIdBridge())    // 编译器 testid → DOM 写入
setupVantTestIds()               // 面板、子元素、兜底注入
app.mount('#app')

纯运行时

最简单的方式,零配置,但 testid 由运行时全局计数器生成。

// vite.config.ts
import vue from '@vitejs/plugin-vue'
import { vueTestIdPlugin } from 'vite-plugin-vant-testid'

export default defineConfig({
  plugins: [vue(), vueTestIdPlugin()],
})
// main.ts
import { setupVantTestIds } from 'vite-plugin-vant-testid/runtime'

createApp(App).mount('#app')
setupVantTestIds()

仅编译期

无运行时开销,但弹出层/对话框面板及子元素不会被注入 testid。

// vite.config.ts
import vue from '@vitejs/plugin-vue'
import { vueTestIdPlugin, testIdTransforms } from 'vite-plugin-vant-testid'

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          nodeTransforms: testIdTransforms(),
        },
      },
    }),
    vueTestIdPlugin(),
  ],
})
// main.ts
import { createApp } from 'vue'
import { createTestIdBridge } from 'vite-plugin-vant-testid/plugin'
import App from './App.vue'

const app = createApp(App)
app.use(createTestIdBridge())
app.mount('#app')

API 参考

testIdTransforms(options?)

返回一组 Vue 编译器 NodeTransform,需注册到 vue() 的 compilerOptions 中。

testIdTransforms({
  attributeName?: string    // 默认:'data-testid'
  vantPrefix?: string       // 默认:'van-'
  customPrefixes?: string[] // 额外的组件前缀
})

vueTestIdPlugin(options?)

Vite 插件占位符。目前为空操作,实际的 testid 注入由 testIdTransforms()setupVantTestIds() 完成。

vueTestIdPlugin({
  attributeName?: string  // 默认:'data-testid'
})

createTestIdBridge(options?)

Vue 插件,从 VNode props 中读取编译期 testid 并写入组件的根 DOM 元素。使用编译期 transform 时必须引入,因为部分 Vant 组件使用了 inheritAttrs: false 或通过 Teleport 渲染。

createTestIdBridge({
  attributeName?: string  // 默认:'data-testid'
})

setupVantTestIds(options?)

启动基于 MutationObserver 的运行时注入器。返回清理函数。

const stop = setupVantTestIds({
  attributeName?: string    // 默认:'data-testid'
  prefixCls?: string        // 默认:'van'
  components?: Record<string, string> // 自定义 CSS 选择器 → 前缀映射
  panels?: Record<string, PanelInjectStrategy | undefined>
})

// 停止监听
stop()

injectCurrentPanels(options?)

一次性注入,适用于已存在或即将出现的面板。适合 SSR/hydration 或不想使用 MutationObserver 的场景。

import { injectCurrentPanels } from 'vite-plugin-vant-testid/runtime'

// 在弹窗/弹出层打开后调用
injectCurrentPanels()

工作原理

编译期 transform

在 Vue SFC 编译期间,testIdTransforms() 遍历模板 AST,为每个 Vant 组件标签注入 data-testid="{tagName}-{index}"。每个模板独立计数,按组件类型递增。

<!-- 源码 -->
<van-button type="primary">提交</van-button>
<van-field v-model="name" placeholder="请输入姓名" />

<!-- 编译后 -->
<van-button type="primary" data-testid="van-button-0">提交</van-button>
<van-field v-model="name" data-testid="van-field-0" placeholder="请输入姓名" />

Vue 插件桥接

createTestIdBridge() 使用全局 mounted mixin,从 VNode props 中读取 data-testid 并显式调用 el.setAttribute()。这绕过了 van-popupvan-dialogvan-picker 等组件中 inheritAttrs: false 和 Teleport 的限制。

运行时注入

setupVantTestIds() 通过 MutationObserver 监听 DOM 变化。当检测到新的 Vant 组件根元素时,使用计数器注入 testid。同时处理:

  • 子元素注入:field 输入框、stepper 加减按钮、slider 滑块、rate 星星、tabs 标签/面板等。
  • 弹出层面板注入:Picker/DatetimePicker/Area 工具栏、ActionSheet 选项、ShareSheet 分享项、Dialog 按钮。
  • 兜底注入:编译期 transform 遗漏的组件。

运行时 Testid 覆盖范围

组件根元素

每个 Vant 组件的根元素都会获得 van-{组件名}-{n} 格式的 testid: van-buttonvan-fieldvan-searchvan-steppervan-switchvan-slidervan-ratevan-uploadervan-checkboxvan-radiovan-pickervan-datetime-pickervan-areavan-popupvan-dialogvan-action-sheetvan-share-sheetvan-notifyvan-overlayvan-dropdown-menuvan-tabsvan-nav-barvan-tabbarvan-sidebarvan-index-barvan-cellvan-cell-groupvan-cardvan-tagvan-collapsevan-imagevan-image-previewvan-progressvan-circlevan-stepsvan-dividervan-loadingvan-skeletonvan-emptyvan-resultvan-listvan-gridvan-swipevan-swipe-cellvan-password-inputvan-couponvan-coupon-listvan-submit-barvan-goods-actionvan-contact-cardvan-contact-listvan-address-listvan-address-editvan-action-barvan-tree-selectvan-pull-refreshvan-back-top

子元素

| 组件 | 子元素 | testid 格式 | |-----------|-------------|----------------| | Field | 输入框/文本域 | {testId}-control | | Field | 清除按钮 | {testId}-clear | | Field | 左侧图标 | {testId}-left-icon | | Field | 右侧图标 | {testId}-right-icon | | Field | 错误信息 | {testId}-error | | Field | 字数统计 | {testId}-word-limit | | Search | 搜索图标 | {testId}-search-icon | | Search | 输入框 | {testId}-search-input | | Search | 清除按钮 | {testId}-clear | | Search | 操作按钮 | {testId}-action-{文本} | | Stepper | 减号按钮 | {testId}-minus | | Stepper | 加号按钮 | {testId}-plus | | Stepper | 输入框 | {testId}-input | | Slider | 滑块按钮 | {testId}-button-{i} | | Rate | 星星图标 | {testId}-star-{i} | | Tabs | 标签项 | {testId}-tab-{i}-{文本} | | Tabs | 内容面板 | {testId}-pane-{i} | | Uploader | 文件输入 | {testId}-input | | Uploader | 预览项 | {testId}-preview-{i} | | Uploader | 删除按钮 | {testId}-preview-delete-{i} | | Uploader | 上传按钮 | {testId}-upload-btn | | Steps | 步骤项 | {testId}-step-{i}-{标题} | | PasswordInput | 密码圆点 | {testId}-item-{i} | | PasswordInput | 光标 | {testId}-cursor | | Tabbar | 标签项 | {testId}-item-{i}-{文本} | | Sidebar | 侧边项 | {testId}-item-{i}-{文本} | | IndexBar | 锚点 | {testId}-anchor-{索引} | | IndexBar | 侧边索引 | {testId}-index-{文本} | | DropdownMenu | 下拉项 | {testId}-item-{i}-{标题} | | NavBar | 左侧区域 | {testId}-left | | NavBar | 右侧区域 | {testId}-right | | NavBar | 标题 | {testId}-title | | Card | 底部区域 | {testId}-footer | | Card | 缩略图 | {testId}-thumb | | Collapse | 折叠项 | {testId}-item-{i}-{标题} | | Swipe | 滑动项 | {testId}-item-{i} | | Swipe | 指示器 | {testId}-indicator-{i} | | SwipeCell | 右侧操作 | {testId}-right-{i} | | ActionBar | 图标按钮 | {testId}-icon-{i}-{文本} | | ActionBar | 按钮 | {testId}-button-{i}-{文本} | | Grid | 宫格项 | {testId}-item-{i}-{文本} |

弹出层面板

渲染在 popup/portal 中的 Picker、ActionSheet、ShareSheet、DropdownMenu、Dialog 等组件会自动注入 testid,包括其工具栏、列、选项和操作按钮。

调试

在浏览器控制台中设置 window.__VANT_TESTID_DEBUG = true 即可看到 testid 注入日志:

window.__VANT_TESTID_DEBUG = true

License

MIT