研发协作
需要快速迭代调试 Web UI 时,用持久 Node.js…
适用于本地 Web UI 需要反复改代码后快速重跑、覆盖功能 QA、视觉 QA 和视口适配检查的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
需要快速迭代调试 Web UI 时,用持特定
解决思路
- 测试前先写一份简短 QA inventory:从三个来源构建:用户要求的需求、你实际实现的用户可见功能或行为、你预期在最终回复中提出的声明。
- QA inventory 中任何出现在上述三个来源之一的内容,在 signoff 前必须映射到至少一个 QA 检查。
- 列出你打算 sign off 的用户可见声明。
- 列出每个有意义的用户可见控件、模式切换或已实现的交互行为。
- 列出每个控件或已实现行为可能引起的状态变化或视图变化。
- 将这份 inventory 作为 functional QA 和 visual QA 共享的覆盖列表。
- 对每个声明或控件-状态组合,记录预期功能检查、必须进行视觉检查的具体状态、以及预期捕获的证据。
- 如果某个需求在视觉上核心但主观,将其转换为可观察的 QA 检查,而不是保持隐式。
- 添加至少 2 个探索性或偏离 happy path 的场景,用于暴露脆弱行为。
- 在持久 TTY session 中启动或确认任何所需 dev server。
- 为变更流程编写专用 Playwright verification script。
- 先运行 desktop script,然后在变更影响移动布局或触摸行为时再添加 mobile script。
- 每次代码变更后,从干净 Node.js 进程重跑 verification script。
- 用正常用户输入运行 functional QA。
- 单独运行 visual QA pass。
- 验证 viewport fit,并捕获支持你声明所需的 screenshots。
- 保存成功运行产生的 screenshot artifacts。
- 将 TARGET_URL 设为你要调试的 app。使用 port 4444,并优先 127.0.0.1 而不是 localhost。
- 在此 sandbox 中,Playwright browsers 预装在 /ms-playwright,且 PLAYWRIGHT_BROWSERS_PATH 可能已设置到该位置。不要假设默认缓存路径 ~/.cache/ms-playwright。
- 在此 Debian sandbox 中,Playwright 使用 headless 模式。除非环境明确提供 X server,不要花尝试在 headed 模式。
- 桌面验证脚本导入 chromium,设置 TARGET_URL = 'http://127.0.0.1:4444',以 chromium.launch({ headless: true }) 启动。
- 创建 context,viewport 为 { width: 1600, height: 900 },然后 newPage()。
- 在 try 中 page.goto(TARGET_URL, { waitUntil: 'domcontentloaded' }),并打印 Loaded: 和 await page.title()。
- 在脚本中添加任务特定交互和断言。
- await page.screenshot({ path: 'playwright-desktop.png', type: 'png' })。
- 在 finally 中关闭 context 和 browser,使用 .catch(() => {}) 避免清理错误。
- 用此模式处理主变更流程。保持脚本聚焦于你确实需要验证的精确行为。
- 若要确认 Playwright browser path 和 installed browser payload,运行 echo "$PLAYWRIGHT_BROWSERS_PATH" 和 ls -al /ms-playwright。
- 示例检查运行:node /tmp/playwright-verify-desktop.mjs。
- 当任务影响响应式布局或触摸行为时,使用单独的 mobile script。
- 移动脚本导入 chromium,设置 TARGET_URL = 'http://127.0.0.1:4444',以 chromium.launch({ headless: true }) 启动。
- 创建 context,viewport 为 { width: 390, height: 844 },isMobile: true,hasTouch: true,然后 newPage()。
- 在 try 中 page.goto(TARGET_URL, { waitUntil: 'domcontentloaded' }),并打印 Loaded mobile: 和 await page.title()。
- 在移动脚本中添加任务特定交互和断言。
- await mobilePage.screenshot({ path: 'playwright-mobile.png', type: 'png' })。
- 在 finally 中关闭 context 和 browser,使用 .catch(() => {})。
- 每次 verification pass 使用一个独立 Node.js script。
- 代码变更后,从干净进程重跑 verification script,而不是试图跨运行保留状态。
- 保持每个 script 窄:一个变更流程、其主要断言和其 screenshot artifacts。
- 如果 desktop 和 mobile 都重要,运行单独 scripts 或单独 invocations,而不是一个大型有状态 script。
- 为当前 validation run 编写并运行 Node.js Playwright verification script。
- 从当前 workspace 启动目标 web app。
- 进行代码变更。
- 针对该变更使用正确路径 reload 或 restart。
- 如果探索发现额外 control、state 或 visible claim,更新共享 QA inventory。
- 重新运行 functional QA。
- 重新运行 visual QA。
- 仅在当前状态就是你要评估的状态后捕获最终 artifacts。
- Renderer-only change:reload 现有页面。
- 对当前 script 是否仍匹配变更后的行为出现新不确定性:重跑干净 script,而不是猜。
- signoff 使用真实用户控件:键盘、鼠标、click、touch 或等效 Playwright input APIs。
- 验证至少一个端到端关键流程。
- 确认该流程的可见结果,而不仅是内部状态。
- 对 realtime 或 animation-heavy apps,在实际交互 timing 下验证行为。
- 按共享 QA inventory 推进,而不是临时 spot checks。
- signoff 前至少覆盖每个明显可见 control 一次,不只是主 happy path。
- 对 inventory 中 reversible controls 或 stateful toggles,测试完整 cycle:initial state、changed state、return to initial state。
- scripted checks 通过后,用 normal input 做 30-90 秒短 exploratory pass,而不是只走 intended path。
- 如果 exploratory pass 发现新 state、control 或 claim,加入共享 QA inventory 并在 signoff 前覆盖。
- page.evaluate(...) 可以 inspect 或 stage state,但不计为 signoff input。
- 将 visual QA 视为独立于 functional QA。
- 使用测试前定义并在 QA 中更新的同一个共享 QA inventory;不要从不同 implicit list 开始 visual coverage。
- 重述 user-visible claims 并显式逐一验证;不要假设 functional pass 证明 visual claim。
- 一个 user-visible claim 直到在它 intended 被感知的 specific state 中被 inspected 后才算 sign off。
- 滚动前 inspect initial viewport。
- 确认 initial view 明显支持 interface 的 primary claims;如果 core promised element 在那里不 clearly perceptible,视为 bug。
- 检查所有 required visible regions,不只是 main interaction surface。
- 检查 shared QA inventory 中已列举的 states 和 modes,包括任务 interactive 时至少一个 meaningful post-interaction state。
- 如果 motion 或 transitions 是体验的一部分,除 settled endpoints 外 inspect 至少一个 in-transition state。
- 如果 labels、overlays、annotations、guides 或 highlights 意在 track changing content,在相关 state change 后验证该 relationship。
- 对 dynamic 或 interaction-dependent visuals,inspect 足够久以判断 stability、layering 和 readability;不要依赖 single screenshot for signoff。
- 对 loading 或 interaction 后可能变密的 interfaces,inspect 在 QA 中可达到的 densest realistic state,不只是 empty、loading 或 collapsed state。
- 如果产品有 defined minimum supported viewport 或 window size,在那里运行 separate visual QA pass;否则选择一个更小但仍 realistic 的 size 并显式 inspect。
- 区分 presence 与 implementation:如果 intended affordance 技术上存在但因 weak contrast、occlusion、clipping 或 instability 不 clearly perceptible,视为 visual failure。
- 如果在评估 state 中任何 required visible region 被 clipped、cut off、obscured 或 pushed outside viewport,即使 page-level scroll metrics 看似 acceptable,也视为 bug。
- 查找 clipping、overflow、distortion、layout imbalance、inconsistent spacing、alignment problems、illegible text、weak contrast、broken layering、awkward motion states。
- 评判 aesthetic quality 和 correctness。UI 应感觉 intentional、coherent、visually pleasing for task。
- 默认用 viewport screenshots for signoff。Full-page captures 仅作为 secondary debugging artifacts;区域需要 closer inspection 时 capture focused screenshot。
- 如果 motion 使 screenshot ambiguous,briefly wait for UI settle,然后 capture 你实际评估的 image。
- signoff 前显式问:这个 interface 还有哪些 visible part 我尚未 inspect closely?
- signoff 前显式问:如果用户 look closely,哪个 visible defect 最可能 embarrass 这个 result?
- Functional path 用 normal user input 通过。
- 对 shared QA inventory 显式 coverage:注明哪些 requirements、implemented features、controls、states 和 claims 被 exercised,并 call out 任何 intentional exclusions。
- Visual QA pass 覆盖 whole relevant interface。
- 每个 user-visible claim 都有 matching visual check 和 reviewed screenshot artifact,来自该 claim 重要的 state 和 viewport 或 window size。
- Viewport-fit checks 对 intended initial view 和任何 required minimum supported viewport size 通过。
- UI 不仅 functional;对 task 而言 visually coherent 且 not aesthetically weak。
- Functional correctness、viewport fit 和 visual quality 必须各自独立通过;一个不意味着另一个。
- 对 interactive products 完成 short exploratory pass,并在 response 中 mention 该 pass 覆盖了什么。
- 如果 screenshot review 和 numeric checks 在任一时刻不一致,signoff 前 investigate discrepancy;screenshots 中的 visible clipping 是 failure to resolve,not something metrics can overrule。
- 包含对 main defect classes 的 brief negative confirmation,你检查了且未发现。
- 保留 final successful screenshot artifacts 作为 evidence,并移除 failed 或 intermediate runs 留下的 stale 或 superseded image artifacts。
- 用 normal Playwright screenshots 作 evidence 和 debugging。
- Desktop screenshot:await page.screenshot({ path: 'playwright-desktop.png', type: 'png' });
- Mobile screenshot:await mobilePage.screenshot({ path: 'playwright-mobile.png', type: 'png' });
- Focused region clipped screenshot:const clip = await page.locator('[data-testid="target"]').boundingBox(); if (clip) { await page.screenshot({ path: 'playwright-target.png', type: 'png', clip }); }
- 默认用 viewport screenshots for signoff。Full-page screenshots 只在需要时作 secondary debugging artifacts。
- 不要仅因 main widget 可见就假设 screenshot 可接受。Signoff 前显式用 screenshot review 和 numeric checks 验证 intended initial view 匹配 product requirement。
- Signoff 前定义 intended initial view。对 scrollable pages,这是 above-the-fold experience。对 app-like shells、games、editors、dashboards 或 tools,这是 full interactive surface 加上使用它所需的 controls 和 status。
- 用 screenshots 作为 fit 的 primary evidence。Numeric checks 支持 screenshots;不能 overrule visible clipping。
- 如果在 intended initial view 中任何 required visible region 被 clipped、cut off、obscured 或 pushed outside viewport,signoff fails,即使 page-level scroll metrics 看似 acceptable。
- 当产品设计为 scroll 且 initial view 仍 communicates core experience 并 exposes primary call to action 或 required starting context 时,scrolling acceptable。
- 对 fixed-shell interfaces,如果为到达部分 primary interactive surface 或 essential controls 需要 scrolling,则 scrolling 不是 acceptable workaround。
- 不要仅依赖 document scroll metrics。Fixed-height shells、internal panes 和 hidden-overflow containers 可能 clip required UI,而 page-level scroll checks 仍看似 clean。
- 检查 region bounds,不只是 document bounds。验证每个 required visible region 在 startup state 中 fits within viewport。
- Passing viewport-fit checks 只证明 intended initial view 无 unintended clipping 或 scrolling 可见。它不证明 UI visually correct 或 aesthetically successful。
- Web 或 renderer check:console.log(await page.evaluate(() => ({ innerWidth: window.innerWidth, innerHeight: window.innerHeight, clientWidth: document.documentElement.clientWidth, clientHeight: document.documentElement.clientHeight, scrollWidth: document.documentElement.scrollWidth, scrollHeight: document.documentElement.scrollHeight, canScrollX: document.documentElement.scrollWidth > document.documentElement.clientWidth, canScrollY: document.documentElement.scrollHeight > document.documentElement.clientHeight })));
- 在特定 UI 中当 clipping 是 realistic failure mode 时,用 getBoundingClientRect() 检查 required visible regions 来 augment numeric check;document-level metrics 单独对 fixed shells 不足。
- 本地 web debugging 时,保持 app 在 persistent TTY session 中运行。不要依赖 short-lived shell 的 one-shot background commands。
- 先 build,然后只在 port 4444 启动 built app:pnpm run build,然后 PORT=4444 pnpm run start。
- 在 page.goto(...) 前验证 port 4444 正在 listening 且 app 响应。
- interactive verification 完成后,停止你在 port 4444 启动的 server process,以保持 sandbox clean。
- fuser 在 Debian sandbox 不可用。使用 ss -ltnp | rg ":4444" 找 listening PID,然后 kill <pid>,然后重跑 ss -ltnp | rg ":4444" 确认 port 4444 不再 listening。
- clean up 后移除 stale 或 superseded interactive image artifacts,使只有 final successful evidence 保留。
- Cannot find module 'playwright':确保 playwright package 安装在 current workspace,并在运行 Node.js script 前 verify import。
- Playwright package 已安装但 browser executable 似乎 missing:先 verify echo $PLAYWRIGHT_BROWSERS_PATH 和 ls -al /ms-playwright。在此 sandbox 中 browsers 预期在 /ms-playwright,不是 ~/.cache/ms-playwright。只有该 directory 实际 absent 或 unusable 时才运行 npx playwright install chromium。
- page.goto: net::ERR_CONNECTION_REFUSED:确保 dev server 仍在 persistent TTY session 中运行,recheck port,并优先 http://127.0.0.1:<port>。
- Node.js process unexpectedly exited 或 reset:从 clean process 重跑 verification script。
适用边界 · 注意事项
- 没有 Node.js/Playwright 运行环境,或无法安装 Playwright 浏览器时,不适用。
- 无法在持久 TTY 会话中启动并保持 dev server,或没有本地构建/启动流程时,不适用。
- 需要真实有头浏览器交互、物理移动设备或完整跨浏览器/设备矩阵时,不适用;此技能主要面向 Debian sandbox 中的 headless 本地调试。