ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Dify 的 @langgenius/dify-ui 组件包测试体系:Vitest 双项目、Storybook 渲染契约与 a11y 门禁

Dify 的 @langgenius/dify-ui 组件包测试体系:Vitest 双项目、Storybook 渲染契约与 a11y 门禁 Dify 的 langgenius/dify-ui 组件包测试体系Vitest 双项目、Storybook 渲染契约与 a11y 门禁【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify本文以 Dify 仓库中packages/dify-ui/docs/testing.md这份《Testing and Development》文档为核心系统讲解langgenius/dify-ui组件包的完整测试与开发工作流如何运行格式化/lint/类型检查与双 Vitest 项目、Storybook 故事即渲染契约的测试边界设计、Storybook a11y 门禁的配置细节以及 Base UI 动画在测试中的处理策略。读完本文你将能够在该包中正确选择测试归属unit 还是 storybook、运行全部测试命令、并为组件编写符合包规范的单元测试与 Storybookplay测试。一、包的定位与命令入口packages/dify-ui是 Dify 工作区内的私有 UI 原语包langgenius/dify-ui提供独立 UI 原语、设计 token、CSS 优先的 Tailwind 样式和cn()工具函数大部分交互原语是对 Base UI headless 组件的薄而有主见的封装见 README。测试体系正是围绕Base UI 上游行为归上游、Dify 自有契约归本包这一边界来组织的。文档给出的命令分为两层仓库根目录执行格式、lint 与 TypeScript 诊断vp check packages/dify-ui在packages/dify-ui/目录下执行测试与 Storybook 命令命令作用vp test --project unit运行原语primitive单元测试vp run storybook启动 Storybookvp test --project storybook --run以浏览器模式运行 Storybook 组件测试vp test同时运行两个测试项目这些命令与包内 package.json 中的scripts一一对应test: vp test --project unit、test:storybook: vp test --project storybook --run、test:watch: vp test --project unit --watch、storybook: storybook dev -p 6006、type-check: tsc。也就是说vp test这类 vite-plus 命令既可以通过根目录直接执行也可以落到 npm script 上日常调用二者等价。二、测试边界两个 Vitest 项目一个 Chromium 运行时文档明确了两点架构性事实包内配置了两个 Vitest 项目Vitest projects二者都运行在Playwright Chromium Browser Mode中——项目名标识的是行为归属方而不是不同的运行时。Storybook 用于承载有文档的组件示例每一个 story 都是一份渲染契约render contract并通过 Storybook Vitest addon 运行配置的无障碍检查。当示例还承担可见状态变化、用户交互、键盘路径、overlay 流程、表单行为、加载行为、受控状态协同中的任一项时应为其添加play测试。普通 Vitest 测试用于更底层的 wrapper 契约如 class 变体cva variants、Base UI 透传 props、hidden-input 序列化、data-attribute 钩子、stores以及不需要有文档示例覆盖的边界情况。源码层面的项目配置印证vite.config.ts 完整实现了这一边界顶层test.browser开启enabled: trueprovider 为playwright()实例为chromiumheadless: true失败时自动截图screenshotFailures: true截图落在./.vitest-browser/screenshotsprojects[0]命名unit挂载 Tailwind 插件、开启globals、加载setupFiles: [./vitest.setup.ts]、include: [src/**/__tests__/**/*.spec.{ts,tsx}]并配置浏览器 trace 在失败时保留trace.mode: retain-on-failureprojects[1]命名storybook通过storybook/addon-vitest/vitest-plugin的storybookTest({ configDir })加载.storybook目录下的故事并生成测试覆盖率由 v8 提供include: [src/**/*.{ts,tsx}]排除 stories、__tests__、themes、stylesCI 环境process.env.CI输出json json-summary本地额外输出text报告。这条路径解释了为什么unit 项目也要跑在浏览器里因为组件依赖真实 DOM、CSS 布局与 Base UI 的 presence 生命周期浏览器模式才是与生产一致的验证环境。unit 测试实例Button 契约以 Button 单元测试 为例可以看到wrapper 契约测试的典型形态使用vitest-browser-react的render与vite-plus/test/browser的userEvent断言默认typebutton、可覆盖为submit、nativeButton{false}时经 render prop 渲染为非原生元素断言disabled使用原生语义toBeDisabled()且不带aria-disabledloading状态可通过focusableWhenDisabled{false}选择退出焦点断言 loading 中的 submit 按钮不会隐式触发表单提交——这正是文档所说不需要有文档示例的底层契约的典型用例。三、无障碍a11y门禁test error与唯一的 color-contrast 例外文档对 a11y 的约定非常严格Storybook 无障碍测试使用a11y.test error任何被启用的违例会直接让测试失败颜色对比度color-contrast是唯一被全局禁用的规则原因是它是已知的设计 token 缺口known design-token gap明确规定不要新增任何全局例外临时例外必须局部化到受影响的 story不要用play测试来替代一个无障碍修复。这一约定在 .storybook/preview.tsx 中逐行落实a11y: { test: error, config: { rules: [ { id: color-contrast, enabled: false, }, ], }, },同时该 preview 文件通过withThemeByDataAttribute装饰器以data-theme属性切换light/dark主题默认 light并以tags: [autodocs]为每个 story 自动生成文档页。而 .storybook/main.ts 声明了故事发现 glob../src/**/*.stories.(js|jsx|mjs|ts|tsx)、react-vite框架以及addon-a11y、addon-vitest、addon-docs、addon-themes等插件链——a11y与vitest两个 addon 正是story 即契约 违规即失败机制的执行者。实践含义如果你在某个 story 中确实需要临时豁免某条 a11y 规则应把该豁免写在对应 story 的局部配置里而不是回到 preview 里再加一条enabled: false。四、动画测试策略BASE_UI_ANIMATIONS_DISABLED标志Base UI 在卸载由 transition 驱动的原语前会等待element.getAnimations()。当测试断言的是最终 DOM 状态而非动画行为本身时文档要求在 Vitest setup 文件中关闭动画;( globalThis as typeof globalThis { BASE_UI_ANIMATIONS_DISABLED: boolean } ).BASE_UI_ANIMATIONS_DISABLED true包内三处相关配置分别对应文档中的三条规则unit 项目默认关闭动画vitest.setup.ts 正是文档中代码片段的落地此外它还引入./vitest.css并将document.documentElement.dataset.theme固定为light保证主题变量与故事一致Storybook 项目保留真实动画生命周期文档明确指出 Storybook 使用其 preview setupmust retain real animation lifecycles因此vitest.setup.ts只对 unit 项目生效见 vite.config.ts 中仅 unit 项目配置setupFiles有意断言动画行为的单测可局部恢复为false但必须在 cleanup 中还原旧值。仓库中已有两处示范这一模式popover 测试约 L41-L69在测试前读取并保存animationSettings.BASE_UI_ANIMATIONS_DISABLED置为false在 teardown 中还原为animationsDisabledtoast 测试L93-L162 附近同样先保存animationState测试中关闭禁用标志结束后还原。这种保存—改写—还原的写法避免了测试间的全局状态污染是遵循文档要求的具体实现范式。五、端到端自查流程综合文档与仓库配置修改packages/dify-ui中的一个组件后的完整验证流程为在packages/dify-ui/下运行vp test --project unit确认新增/修改的 wrapper 契约class 变体、透传 props、data-attribute 钩子等通过在packages/dify-ui/下运行vp test --project storybook --run确认所有 story 的渲染契约与 a11y 检查通过违规会因test error而失败需要交互式核对组件行为时运行vp run storybook打开 6006 端口的 Storybook注意 Storybook 保留真实动画验证 presence/transition 相关行为时不要依赖 unit 项目的动画禁用标志回到仓库根目录运行vp check packages/dify-ui完成格式化、lint 与 TypeScript 诊断若涉及动画相关的 DOM 状态断言确认你的测试落在 unit 项目setup 已自动关闭动画若要断言动画本身参考 popover/toast 的测试写法在局部临时恢复BASE_UI_ANIMATIONS_DISABLED false并保证 cleanup 还原。关键文件索引关注点文件本文核心文档testing.md命令脚本package.json双项目与浏览器模式配置vite.config.tsunit 项目 setup 与动画禁用vitest.setup.tsa11y 门禁与主题装饰器preview.tsxStory 发现与 addon 链main.tsunit 测试示例button/index.spec.tsx动画标志的局部恢复范式popover/index.spec.tsx、toast/index.spec.tsx这套体系的核心思想可以概括为用浏览器模式统一运行时用项目名划分行为归属用 Storybook 把文档示例升级为可执行的渲染契约用error级别的 a11y 检查把可访问性变成 CI 硬门禁并用一个全局动画标志在断言状态与断言动画两类测试之间做出清晰取舍。【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表