# 手工浏览器实测脚本 不进 `npm test` —— 它们需要一个跑着的 Chromium 与一个活的 Gateway。 日常回归靠 `../narrow-layout.test.mjs`(读源码验形态,无外部依赖)。 ## 为什么两套都要 结构性断言守住「代码写成了什么形态」,量不出「按钮实际多大、点下去命中谁」。 窄屏那轮修复里最严重的一个 bug 是抽屉式侧栏(`fixed ... z-50` 铺满视口高度) 把底部导航最左那一项盖住 —— 按钮在那里、尺寸也够、`md:hidden` 之类的规则也 没写错,**只有 `elementFromPoint` 才能发现它命中的是抽屉里的 SVG**。 ## 用法 ```bash # 窄屏:390px(iPhone 14 Pro)+ 320px(iPhone SE) ADMIN_PW=<密码> npm run test:narrow # 宽屏回归:窄屏修复不能把桌面改坏 ADMIN_PW=<密码> npm run test:wide ``` 环境变量: | 变量 | 默认 | 说明 | |---|---|---| | `ADMIN_PW` | 无(必填) | 管理员密码 | | `ADMIN_USER` | `admin` | 登录用户名 | | `AGENTMAIL_URL` | `https://mail.jianfgit.xyz` | 目标地址 | | `CDP_URL` | `http://127.0.0.1:9222` | 浏览器 CDP 端点 | | `PLAYWRIGHT` | `/usr/lib/node_modules/playwright/index.mjs` | playwright 入口 | 浏览器用的是本机 systemd 托管的共享 Chromium(`homeagent-browser.service`), 通过 CDP 连上去开自己的标签页,用完关掉。没有它时先 `systemctl start homeagent-browser`。 ## 文件 | 文件 | 作用 | |---|---| | `narrow-probe-helper.mjs` | 连浏览器、登录、量盒子/溢出/命中区/命中测试 | | `narrow-verify.mjs` | 窄屏 13 项验收 | | `wide-regression.mjs` | 宽屏 5 项回归 | | `inbox-group-verify.mjs` | 收件箱按会话分组 | | `theme-verify.mjs` | 深浅两色的 WCAG 对比度 | | `accent-verify.mjs` | 强调色(红/绿/橙/黄/蓝)17 组配色,两模式各一遍 | | `desktop-phase3-verify.mjs` | **桌面客户端**:写信 + 附件 + 权限面板(见下) | `narrow-probe-helper.mjs` 里两个函数值得单独知道: - `tapTargets(page, labels)` —— 量 `.tap` 按钮的**真实**命中区(`::after` 伪元素的尺寸)。`.tap` 刻意不改变视觉尺寸,所以只看 `boundingBox` 会误判成偏小 - `hitTest(page, selector)` —— 每个元素点下去是否命中自己。遮挡类 bug 只能这样查 `accent-verify.mjs` 存在的理由是一次真实事故:`tailwind.config.js` 的 `colors` 里同时写了固定 hex 与 `accent()` 两份 red/green/amber/orange/yellow,JS 对象 字面量重复键**后者胜出**(不报错),而 `index.css` 当时没有对应的 `--c-red-*` 变量。`rgb(var(--c-red-600) / 1)` 里变量未定义 → 整条 `background-color` 声明 失效 → `bg-red-600` 退回透明、`text-white` 的白字落在白卡片上: **按钮看不见但点得动**。所有静态检查都过,只有肉眼能发现。 因此这个脚本量的是**实际计算值**:它把类名注入真页面、读 `getComputedStyle`, 把「背景透明」单独判为失败(那正是上述 bug 的指纹),再算 WCAG 对比度。 只以 `hover:` 变体出现的档(`bg-red-700` / `bg-blue-700`)**不能**放进探针: Tailwind 不生成未被使用的基础类,探它必然得到透明背景 —— 那是假阳性。 它们由 `../theme.test.mjs` 的档位断言覆盖。 ## 桌面客户端那一个(`desktop-phase3-verify.mjs`) 它不连共享浏览器,而是**自己起打包好的 Electron 应用**(xvfb + `--remote-debugging-port`), 然后走一条贯穿全流程的链: ```bash ADMIN_PW=<密码> DESKTOP_BIN=release/linux-unpacked/agentmail-web \ node test/manual/desktop-phase3-verify.mjs ``` 1. 用桌面 UI 写一封信、**带一个附件**,发给 `zcode` 2. 外部(直接打网关 API)核验:信真的在、附件真的挂着 —— 界面说「已发送」不算证据 3. 这封信让 `zcode` 触发一次**真实的授权请求**(执行门禁) 4. 在桌面的**授权面板**里点「同意」 5. 外部核验:决策被记录 **且** Agent 真把命令执行了(标记文件出现) 第 5 步是这条链的重点:它证明界面上的那一下点击真的走到了 Agent 那侧。 只验界面变成「已同意」的话,一个只在本地改状态、根本没提交给网关的实现也能全绿。 第一条判据是「**应用渲染出内容了吗**」(`#root` 有子节点)—— 白屏时后面每一条都会 以奇怪的方式失败,而真正的原因只以一条资源错误出现。这个脚本第一次跑就靠它抓到了 `base` 那个白屏缺陷(见 `../packaging.test.mjs`)。 ## 已知限制 headless Chromium 报告 `hover: none`,因此 `.reveal`(只在支持悬停的设备上隐藏) 在这里永远是可见的 —— 脚本只能验「触摸设备上可见」这一半, 「鼠标设备上隐藏」那一半靠 `../narrow-layout.test.mjs` 检查 CSS 规则存在。 没有像素级视觉比对:字体差异下极脆,维护成本高于收益。