Imported from auto-stack/auto-lang (
.agents/skills/autoui-verifier/SKILL.md). Install upstream withnpx skills add auto-stack/auto-lang --skill autoui-verifier. Copyright stays with the author.
AutoUI Dual-Backend Verifier (AutoUI 跨端验证与测试技能)
本技能为 AutoUI 跨端应用(Vue 模式与 VM/Iced 模式)提供标准化的功能测试、交互验证与像素级视觉一致性核对流程。
0. AutoUI 运行模式快速备忘 (Quick Reference)
| 模式 | 运行命令 | 底层引擎 | 验证与交互工具 |
|---|---|---|---|
| Vue 模式 | auto run (或 auto gen && cd src/front && npx vite) |
Web (Vite + Vue 3 + Tailwind + shadcn) | Playwright 自动化截图 / DOM 交互 |
| VM 模式 | auto run -r vm |
Native VM + Iced GUI (内置 MCP Server) | Python MCP 驱动 / 截图 / 事件注入 |
1. 触发场景 (When to Use)
- 用户要求“验证/测试某个 UI 示例”(例如
examples/ui/003-converter,011-calculator,013-todo,022-kanban等)。 - 修改了 AutoUI 编译器、Aura View Builder (
aura_view_builder.rs)、Iced 渲染器 (renderer.rs) 或 VM 引擎后,需要回归检查 UI。 - 需要捕获双端运行截图,排查边框、背景、圆角、内边距、字号或交互计算的差异。
2. 双轨驱动工具体系
A. VM 模式 (auto run -r vm) — AutoUI MCP Server
Iced 桌面运行时内置了 HTTP JSON-RPC MCP Server(端点 http://127.0.0.1:<PORT>/mcp):
- 端口控制:运行
AUTOUI_MCP_PORT=<PORT> auto run -r vm动态分配空闲端口。 - 核心工具:
autoui_snapshot: 获取 AURA 树结构与 State,读取#aura_N或#vnode_N元素 ID。autoui_type: 向目标输入框键入文本(自动更新 State 并触发oninput/onchange)。autoui_press: 点击目标按钮/可点击元素,触发onclick。autoui_keyboard: 发送全局或带修饰键的按键(如"Enter",modifiers: ["ctrl"])。autoui_screenshot: 捕获无损渲染帧(保存至tests/screenshots/<name>.png)。
B. Vue 模式 (auto run) — Playwright
浏览器端通过 Playwright 捕获深色主题渲染图与执行 DOM 自动化交互:
- 快速命令行截图:
npx playwright screenshot --color-scheme dark --viewport-size "1280, 800" http://localhost:5173 vue_shot.png - Node.js 自动化脚本:利用 Playwright API 定位输入框、填值并截图。
3. 标准化执行工作流 (Standard Workflow)
flowchart LR
A["1. 启动 VM 进程<br/>(分配 AUTOUI_MCP_PORT)"] --> B["2. 连接 MCP Server<br/>(snapshot + screenshot)"]
C["3. 启动 Vite/Vue<br/>(auto run / npx vite)"] --> D["4. Playwright 捕获<br/>(dark viewport 1280x800)"]
B & D --> E["5. 对比初始视觉<br/>(卡片/边框/圆角/输入框)"]
E --> F["6. 双端执行交互测试<br/>(type_text / press)"]
F --> G["7. 交互后截图与计算值校验"]
步骤 1:VM 模式自动化交互与截图
编写或调用 Python MCP 驱动脚本(参考 scripts/test_vm_mcp.py):
client = AutoUiMcpClient(port)
client.screenshot("converter_vm_initial")
client.type_text("aura_9", "323") # 输入测试用例
time.sleep(0.5)
client.screenshot("converter_vm_decimal")
步骤 2:Vue 模式自动化交互与截图
启动 Vite 后,运行 Playwright 脚本(参考 scripts/test_vue_playwright.mjs)生成 converter_vue_initial.png 与 converter_vue_decimal.png。
步骤 3:视觉审查与状态一致性判定
对照 docs/design/autoui/base-styles-and-visual-parity.md 与第 5、7 节核对:
- 容器:深色底色
zinc-950,卡片bg-card,边框zinc-800,圆角rounded-2xl。 - 输入框:14px 字号,
px-3 py-2内边距,rounded-md(6px) 圆角,zinc-800细边框。 - 按钮与前景色:暗色模式下默认主按钮为浅色底(
239 84% 77%)+ 深黑字(#0f172a),带hover:bg-primary/90悬停微调。 - 计算精度:浮点/双精度四舍五入值在两端精确一致。
步骤 4:分级门禁与合入规范 (Change-Scoped Gating)
严格遵循 AGENTS.md 的测试纪律,杜绝无谓测试开销:
- 纯验证 / 资产 / 计划跟踪任务:未修改
crates/下 Rust 源码时,严禁运行cargo t和docs_gen,完成双端截图核验与计划矩阵更新后直接合入。 - 局部 Rust 代码修改任务:开发调试使用
cargo check -p auto-lang,验证使用作用域测试cargo t <module>(如cargo t iced或cargo t style)。 - 仅修改文档/Schema 时:才执行
cargo test -p auto-lang --test docs_gen。
4. 常见排查与排障指南 (Troubleshooting)
- 输入后 State 未更新:
- 检查
crates/auto-lang/src/ui/dynamic.rs中的extract_input_state_map是否正确识别了props["value"](支持Expr::Ident与Expr::Dot)。
- 检查
- 计算值显示为 0 或 NaN:
- 检查
crates/auto-lang/src/vm/engine.rs中的decode_tagged_nv是否支持is_f32/is_f64。 - 检查
crates/auto-lang/src/vm/codegen.rs的contains_double是否递归处理了Expr::Call。
- 检查
- 截图出现端口冲突:
- 使用 Python
socket.bind(('127.0.0.1', 0))动态分配端口并传入AUTOUI_MCP_PORT。
- 使用 Python
5. 跨端视觉精细核验 6 大检查项 (Visual Parity Checklist)
在对比 Vue 与 VM 截图时,必须逐项进行结构化审查,切忌仅做粗粒度概览:
- 图片与头像裁剪 (Image & Avatar Clipping):
- 圆形头像 (
rounded-full) 是否真正裁剪了位图本身,还是只在外层包裹了边框而图片本体仍为方形? - 头像阴影 (
shadow-md) 与白/灰边框 (border-4) 是否与背景正确叠加?
- 圆形头像 (
- 方向性圆角与容器形状 (Corners & Borders):
- 顶部 Banner 是否支持方向圆角(如
rounded-t-lg上圆下直)? - 外层卡片边框颜色、宽度与圆角半径是否一致?
- 顶部 Banner 是否支持方向圆角(如
- 文本盒模型与徽章背景 (Text Box-Model & Badges):
- 标签/徽章(如 Role Badge)是否渲染了浅色胶囊背景、内边距与圆角?
- 段落文本两端内边距 (
px-6) 是否贴边?
- 排版与行高 (Typography & Line Height):
- 段落行高 (
leading-relaxedvs 默认单倍行距) 是否一致?VM 是否因缺少行高而纵向紧凑? - 标题与正文字号、字重(Bold / Medium / Regular)是否准确?
- 段落行高 (
- 外边距与图层跨界 (Margins & Overlaps):
- 负外边距(如
-mt-10)是否将元素正确向上提升并跨越边界? - Flex gap(如
gap-4)在两端各元素间的间距是否均匀?
- 负外边距(如
- 按钮默认样式、色彩令牌与悬停态 (Button Defaults, Color Tokens & Hover):
- 暗色模式反转设计 (Dark Theme Primary Inversion): shadcn-vue 在暗色模式下默认 Button 为浅色高光胶囊(白/浅灰底
bg-primary+ 黑/深灰字text-primary-foreground)。核查 VM 端是否误渲染成了蓝紫底白字或硬编码纯白前景色! - 悬停反馈 (Hover State Feedback): 悬停时按钮是否具备透明度/亮度微调(如
hover:bg-primary/90)?VM 端是否在Hovered状态下具备对应变化? - 文字规格与圆角: 按钮文字字号是否对齐
14px(Sm)、字重500(Medium),内边距 (px-4 py-2) 与圆角 (rounded-md6px) 是否一致?
- 暗色模式反转设计 (Dark Theme Primary Inversion): shadcn-vue 在暗色模式下默认 Button 为浅色高光胶囊(白/浅灰底
- 表单控件指示器与微形态 (Form Indicators & Checkbox/Radio Styling):
- 指示器尺寸与比例: Checkbox/Radio 是否遵循
w-*/h-*样式类缩放(如w-10 h-12宽大选择框 vsw-4 h-4紧凑选择框),而非固定在 16px 默认尺寸? - 未选中与选中态底色/边框: 未选中态是否为干净的透明/白底配细灰边(
border-gray-300),选中态是否为鲜明主题色填充 + 清晰白色对勾/圆点?切忌在浅色卡片上误渲染为深色实心块! - 指示器形状: 是否根据
rounded-full渲染为圆形复选框,或根据rounded渲染为标准圆角方框?
- 指示器尺寸与比例: Checkbox/Radio 是否遵循
- 文本修饰线与条件状态 (Text Decorations & Conditional Styles):
- 删除线与下划线 (Line-Through & Underline): 已完成待办项、已核销金额等带
line-through的文本是否正确绘制水平穿透线?带underline的超链接/强调文本是否正确绘制底线? - 可点击文本组件的修饰继承: 当
text绑定了onclick(在 AST/AURA 中转为Button)时,其内部文本标签是否依然完整继承并渲染了line-through、字号和颜色?
- 删除线与下划线 (Line-Through & Underline): 已完成待办项、已核销金额等带
- 毛玻璃 backdrop-*(已知分歧白名单,Plan 518 G8):
backdrop-blur-*/backdrop-saturate-*词汇已声明冻结(共享 parser 识别),但 VM/iced 臂视觉 no-op 为既定降级语义(装饰性降级非错绘,不报错不 not-yet)——双端对拍中含玻璃样式的卡面(如examples/capability-tests/p518-glass-sample,PLAN-552 探针清退迁出)vue 出真毛玻璃、VM 无模糊属预期分歧,不计为回归;真 backdrop 渲染挂 RenderQueue(KNOWN-DEBT P518 planned-debt,翻转时移除本条)。玻璃配方另两腿(bg-white/10半透明底 + border)双端均应正常渲染。
6. AutoUI 跨端布局与状态黄金规则 (AutoUI Parity Domain Rules)
在编写或修复 AutoUI 布局与控件时,必须遵循以下经过验证的黄金实践:
- 表单控件聚焦态 (Focus State & Ring):
- 单行
input与多行textarea在 Iced 中必须通过matches!(status, iced::widget::text_input::Status::Focused { .. })捕获焦点。 - 聚焦时边框增粗至
2.0px并自动调用resolve_semantic_rgb(&Color::Primary)渲染主色(对齐 Vuefocus-visible:ring-2)。
- 单行
- 主题色与前景色映射 (Semantic Color Tokens):
- 暗色模式下
Color::Primary映射至--primary(210 40% 98%即rgb(248, 250, 252)),Color::OnPrimary映射至--primary-foreground(222.2 47.4% 11.2%即rgb(2, 8, 23))。 - 绝不可将
Color::OnPrimary硬编码为纯白(255, 255, 255),否则会导致暗色主按钮上的文字反差丢失。
- 暗色模式下
- 按钮默认 Hover 预设 (Button Hover Preset):
- 默认 Button variant preset 必须包含
hover:bg-primary/90,使 Icedwidget::button::Status::Hovered能够自动计算悬停微光样式。
- 默认 Button variant preset 必须包含
- Row 内文本排版与边距 (Row Baseline Alignment):
- 禁止在 Row 内部子文本上应用垂直外边距(如
mt-4),因为 Iced 容器外边距包装会导致各子元素内边距不对等,使水平文本垂直基线错位。 - 垂直外边距必须统一下沉到父级
Row容器(如row { style: "justify-center items-center mt-4" })。 - Row 内多个文本之间的间隙统一使用水平外边距(如
mr-1或ml-1),避免 HTML 尾部空白字符被浏览器渲染引擎折叠。
- 禁止在 Row 内部子文本上应用垂直外边距(如
- 控件外边距包装 (Margin Wrapping):
- 所有基础控件(
Input,Textarea,Checkbox,Button,Text)在IntoIcedElement与render_dynamic_view中转换为iced::Element时,必须显式调用wrap_with_margin(el, &iced_style),确保mt-*/mb-*/ml-*/mr-*不被静默丢失。
- 所有基础控件(
- 单侧边框颜色继承 (Side Border Color):
border-t/border-b/border-l/border-r必须优先消费is.border_color(如border-gray-200),无显式颜色时才回退至主题默认resolve_border_rgb(),避免在浅色卡片上误渲染为突兀深黑线。
overflow-hidden与高度推断解耦 (Overflow Clipping vs Height Inference):overflow-hidden在 CSS 中仅表示内容溢出裁剪与圆角遮罩,绝不可被误推断为height: Fill;仅overflow-y-auto/scroll具备纵向填充意图,避免造成卡片高度被撑满整屏。
- 单体表单控件的箱内居中 (Standalone Form Control Centering):
- 无 label 的独立
checkbox/radio在声明了w-*/h-*(如w-10 h-12)时,必须包裹在align_x(Center)与align_y(Center)容器中,确保在行高内垂直与水平居中。
- 无 label 的独立
7. 严格像素与色彩取色核验规程 (Pixel-Level & Design-Token Verification Protocol)
在判定双端视觉对齐(Pass)之前,必须执行以下三层硬性核对,切忌“仅凭宏观轮廓感觉”:
- 同屏并排放大审查 (Side-by-Side Zoom Audit):
- 将 Vue 截图与 VM 截图并排对比。放大至局部控件(如按钮、卡片、输入框),严禁仅查看全景缩略图。
- 色彩吸管与明暗反差校验 (Color Picker & Contrast Check):
- 检查主容器背景色(暗底 vs 亮底)。
- 检查主按钮背景色与文字色(白底黑字 vs 黑底白字 vs 彩色底)。
- 检查边框细线是否存在 1px 渲染丢失或颜色过淡。
- 动态状态双端捕获 (Interactive State Sampling):
- 至少捕获 初始态 (Initial) 与 交互/悬停态 (Hovered/Focused/Typed) 两组截图,确认动态视觉反馈一致。
- 截图保留与用户交付展示 (Local Archiving & User Presentation):
- 每个示例检验完成后,Vue 版与 VM 版的对比截图必须完整保存在本地(如
<example>/src/front/tests/screenshots/),并通过.gitignore排除,严禁将大体积二进制截图提交入 Git 历史。 - 在会话总结中,必须显式将双端截图列出/嵌入给用户查看,方便用户直观对比与双重把关。
- 每个示例检验完成后,Vue 版与 VM 版的对比截图必须完整保存在本地(如