关于 peach-e2e-scenario
peach-e2e-scenario 是用于创建和运行浏览器 E2E 场景的 Skill,并会在失败后修改脚本重试。它参考既有场景模式,必要时检查实时 DOM,并通过有限次数的修复循环和执行审批门槛控制流程。
主要功能
- 01支持创建、运行或组合模式
- 02调试时检查 DOM 和选择器
- 03使用 node --check 验证脚本
- 04最多进行三轮脚本修复
- 05执行前要求选择标签页
- 06敏感会话执行需审批
适用场景
- 01根据任务描述生成浏览器测试
- 02运行现有场景并修复失败
- 03将 codegen 录制代码转换为场景
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ peachsolution/ peach-harness --skill peach-e2e-scenario安装后在 Claude Code 中输入/peach-e2e-scenario确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/daemon-잔류-대응.mddialog-handler-패턴.mdvalidation-통과-패턴.md변환규칙.md시나리오-생성-패턴.md자동수정-판단트리.md코드패턴.md프레임워크-대응.md详细介绍
E2E 场景集成专家
通过一个循环完成场景生成、执行和自动修复。 参考现有场景代码模式,并在必要时实时检查 DOM 以编写场景。 执行失败时分析错误,直接修改脚本并重新执行。
模式
| 模式 | 触发方式 | 行为 |
|---|---|---|
auto(默认) | /peach-e2e-scenario [说明] | 生成 + 执行 + 自动修复循环 |
create | /peach-e2e-scenario create [说明 or codegen] | 仅生成场景 |
run | /peach-e2e-scenario run [路径 or 编号] | 执行 + 自动修复循环 |
工具分工
| 用途 | 工具 |
|---|---|
| 场景执行 | ./e2e.sh run(基于 playwright-cli) |
| 选择器调试/DOM 检查 | agent-browser eval(速度快) |
| iframe 调试 | ./e2e/pwc.sh eval(备用) |
| 语法验证 | node --check |
强制关卡
- 启动 Chrome Beta 时优先使用
cd e2e && ./e2e.sh chrome。如需直接启动,必须包含--user-data-dir=$HOME/.chrome-beta-e2e-profile。 - 使用
./e2e.sh status检查标签页列表,在用户指定执行标签页之前,不要启动./e2e.sh run、agent-browser eval或切换标签页。 - 对于 Google 登录、OAuth、管理控制台、支付、需要保留现有 Chrome Beta 配置文件会话的任务,只进行场景生成/分析,确认用户同意后再实际执行。
- 如果
agent-browser调试异常,不要通过操作系统级别的浏览器绕过(open -a、启动其他浏览器、使用其他配置文件路径)。 - 如果需要登录/二次验证,不要由 AI 直接处理;请引导用户先在 Chrome Beta 固定配置文件中完成身份验证。
Chrome Beta 启动不可变规则
以 CDP 模式启动 Chrome Beta 时,必须使用固定配置文件选项。未指定配置文件选项的启动视为无法维持会话。
- 允许:
cd e2e && ./e2e.sh chrome - 直接启动时的必需选项:
--remote-debugging-port=9222、--remote-allow-origins=*、--user-data-dir=$HOME/.chrome-beta-e2e-profile、--disable-extensions - macOS 直接启动标准命令:
/usr/bin/open -na "Google Chrome Beta" --args ... - 禁止:单独运行
open -a "Google Chrome Beta"、不带--args的open命令、不带--user-data-dir的 Chrome Beta 启动、擅自使用其他配置文件路径、绕过并使用默认 Chrome 或其他浏览器
工作流
通用:环境检查 + 标签页检查
cd e2e && ./e2e.sh setup
setup 会自动检查/安装所有环境(Chrome Beta、agent-browser、playwright-cli、CDP 连接)。
如果 CDP 未连接,先按以下顺序尝试自动恢复。
- 执行
cd e2e && ./e2e.sh chrome & - 等待
sleep 4 - 执行
cd e2e && ./e2e.sh status重新检查 - 如果仍未连接,请引导用户手动执行
cd e2e && ./e2e.sh chrome
./e2e.sh chrome是通过固定配置文件($HOME/.chrome-beta-e2e-profile)启动 Chrome Beta 的标准方式。即使改为直接启动 Chrome,也不要省略--user-data-dir选项。
cd e2e && ./e2e.sh status
向用户显示标签页列表,并询问 “要在哪个标签页执行?”。
标签页编号从 0 开始。排除
chrome://标签页。[编号]与--tab N中的 N 相同。 使用用户已登录的标签页。不区分环境(local/test/prod)。 在收到标签页编号之前不要执行。对于敏感会话任务,即使已收到标签页编号,也只进行分析,直到获得用户批准。 防止标签页漂移:用户回复标签页编号后,紧接着运行agent-browser tab N,然后运行agent-browser eval "document.title + ' | ' + location.href",重新确认标签页是否正确。 如果与预期不符,重新输出./e2e.sh status并让用户重新选择。调试/复现时建议固定E2E_TAB_ID。 (详情:peach-e2e-browse/references/탭-선택-패턴.md)
文件上传场景:如果场景代码需要使用
page.setInputFiles()或操作 file input, 请使用Page.setInterceptFileChooserDialog方式阻止操作系统原生文件对话框。 使用 CDP Escape /agent-browser press Escape无法关闭 macOS 原生对话框。 (详情:peach-e2e-browse/references/SPA-프레임워크-입력패턴.md §3)
auto 模式(默认)
- 判断输入来源 — 自然语言请求还是 codegen 录制代码
- 参考现有场景模式 — 阅读
e2e/시나리오/下的现有代码,了解模式- 参考
references/시나리오-생성-패턴.md
- 参考
- 预先检查 DOM(必要时)— 使用 agent-browser eval 预先确认 URL 结构和选择器
- 生成场景 — 参考
references/코드패턴.md编写脚本- 输入为 codegen 时,额外参考
references/변환규칙.md - 框架差异请参考
references/프레임워크-대응.md
- 输入为 codegen 时,额外参考
- 确认信息 — 场景名称(韩文)、保存类别文件夹(韩文业务领域)、类别内序号(
NN-)、此场景会留下的 state 契约、此场景所需的前置 state 契约 - 语法验证 — 确认通过
node --check - 确认执行授权
- 普通页面:确认标签页编号和场景路径后执行
- Google/OAuth/管理/支付/需要保留现有 Chrome Beta 配置文件会话的任务:
执行
./e2e.sh run前,必须再次向用户确认是否批准实际执行
- 执行 —
./e2e.sh run --tab N 시나리오/경로 - 自动修复循环 — 失败时按照下方的自动修复循环处理
- 报告结果
create 模式
- 判断输入来源
- 自然语言请求 → 参考
references/시나리오-생성-패턴.md+references/코드패턴.md - codegen 录制 → 参考
references/변환규칙.md+references/코드패턴.md
- 自然语言请求 → 参考
- 确认信息 — 场景名称(韩文)、保存类别文件夹(韩文业务领域)、类别内序号(
NN-)、此场景留下的 state 契约、此场景要求的前置 state 契约 - 生成场景
- 必需的转换项(输入为 codegen 时):
chromium.launch()→connect()(使用 lib/connect.js)page.goto('/path')→ 确认当前标签页状态后再按条件跳转- 属于敏感会话或未经用户批准时,禁止自动跳转
- 仅在会话非敏感且已获得用户批准时使用
page.goto()
- 删除
browser.close()/context.close() - 删除
page.pause() - 添加对话框处理程序(替换
setDialogHandler+ 必须在 finally 中恢复) - 使用 try-catch-finally + exitCode 模式封装(禁止固定使用
process.exit(0)退出) - 添加表情符号日志
- 尽量减少
waitForTimeout→ 改为条件等待 - 弹出窗口(
waitForEvent('popup'))→ 检测关闭时使用waitForEvent('close')
- 必需的转换项(输入为 codegen 时):
- 语法验证 — 确认通过
node --check - 报告保存结果 —
e2e/시나리오/{한글카테고리}/{NN}-{시나리오명}.js- 如果类别文件夹不存在,则自动创建
- 现有的扁平结构文件不会立即批量迁移,而是在修改/重写时逐步按新规则迁移
- 迁移时,在完成报告中注明旧路径和新路径
run 模式
- 选择场景
cd e2e && ./e2e.sh list - 确认执行批准
- 对于关键在于保持已登录的真实标签页/固定配置文件会话的场景,执行前必须获得用户批准
- 执行
cd e2e && ./e2e.sh run --tab N 시나리오/경로 - 自动修复循环 — 执行失败时,按以下自动修复循环进行
- 报告结果
自动修复循环(最多 3 次)
如果场景执行结果为 ❌ 에러:,则直接修改脚本并重新执行。
此技能的职责不止于提供简单的调试指导,还包括查明原因、修复场景文件并重新执行。
自动修复期间,如果怀疑是选择器/DOM/框架交互问题,则应用
peach-e2e-browse 的决策树,重新确认当前标签页中的 DOM 和交互方式。
将确认过的选择器和事件模式反映到场景代码中,然后重新执行。
详情:参考 references/자동수정-판단트리.md
判断标准
| 错误类型 | 处理方法 |
|---|---|
| 选择器不匹配(timeout,locator not found) | 使用 agent-browser eval 检查实际 DOM → 修改场景选择器 |
dialog 自动关闭(기록하지 못했습니다,dismiss) | 确认是否有残留 daemon,然后 kill → 如果未应用 setDialogHandler 模式则进行修改 |
popup waitForEvent('close') 错误 | 应用 Promise.race + .catch(() => {}) 模式 |
URL 模式不匹配(waitForURL timeout) | 确认实际跳转的 URL → 修改模式 |
时序问题(waitForTimeout 后立即失败) | 将固定等待改为基于事件的 waitForEvent 或 waitForFunction |
Target page, context or browser has been closed | popup/标签页比预期更早关闭 → 添加 .catch(() => {}) 或 closeTarget 选项 |
| navigation timeout(AJAX submit) | 删除 waitForNavigation 或替换为 waitForURL |
| 服务器错误(500、网络错误) | 无法自动修复 → 报告用户后停止 |
循环步骤
1. 에러 메시지 파싱 → 유형 판별
2. agent-browser eval로 실제 DOM/URL 확인
3. 시나리오 스크립트 수정
4. 재실행
5. 여전히 실패? → 1로 돌아감 (최대 3회)
6. 3회 실패 → 진단 패키지 출력 → 사용자에게 보고 → peach-e2e-browse 안내
失败 3 次时输出诊断包
自动修复 3 次全部失败时,anchoring(累积错误偏差)风险会增加。 不要在同一上下文中勉强增加到第 4 次、第 5 次,而应结构化输出诊断包,以便在新对话窗口中使用干净的上下文进行调试。
输出格式
🩺 자동수정 3회 실패 — 진단 패키지
## 시나리오
- 파일: <시나리오 파일 절대경로>
- 대상 URL: <실행 대상 URL>
- 탭 ID: <E2E_TAB_ID>
## 시도 이력 (3회)
| 회차 | 추정 원인 | 적용한 수정 | 재실행 결과 |
|------|----------|------------|-----------|
| 1 | <유형> | <변경 요약> | <에러 메시지 첫 줄> |
| 2 | <유형> | <변경 요약> | <에러 메시지 첫 줄> |
| 3 | <유형> | <변경 요약> | <에러 메시지 첫 줄> |
## 마지막 실패 컨텍스트
- 마지막 에러 메시지 (전문)
- 실패 시점 DOM 스냅샷 또는 셀렉터 평가 결과
- 실패 시점 URL
## 추정 막힌 지점
<3회 모두 같은 유형이면 그 유형, 다르면 "다중 원인 의심" 명시>
## 사용자 다음 액션 가이드
1. 새 대화창에서 위 패키지를 첨부하여 디버깅 진행
2. peach-e2e-browse로 현재 탭 상태 직접 확인
3. 시나리오 의도 자체 재검토 필요 가능성
原则
- 为便于重新开始上下文,将绝对路径、完整错误信息和全部尝试记录以内联形式全部包含(禁止摘要)
- 不自动扩展到第 4 次、第 5 次(Bounded Autonomy:May Suggest 范围,由用户决定)
- 如果用户希望在同一会话中继续,则可追加尝试,但须先提示一次 anchoring 风险
修改后重新执行
E2E_TAB_ID=<id> ./e2e.sh run '시나리오/대상.js'
如果是 dialog 相关错误,执行前必须确认是否有残留 daemon:
lsof -iTCP:9222 -sTCP:ESTABLISHED -n -P | awk '/node/{print $2}' | xargs kill -9 2>/dev/null
选择器调试(优先使用 agent-browser eval)
# CDP 연결 (1회)
agent-browser connect 9222
# 현재 URL 확인
agent-browser eval "location.href"
# 셀렉터 존재 여부
agent-browser eval "document.querySelector('.target') !== null"
# 버튼 목록
agent-browser eval "JSON.stringify(Array.from(document.querySelectorAll('button')).map(function(b){return b.innerText}))"
# 요소 개수
agent-browser eval "document.querySelectorAll('tr').length"
无法使用 agent-browser 调试 iframe 内部 → 回退到 playwright-cli:
./e2e/pwc.sh eval "document.querySelector('iframe[src*=target]').contentDocument.querySelector('#element').innerText"
native dialog 场景规则
window.alert/confirmJS monkey-patch 不起作用 — Playwright CDP 自动 dismiss 会先执行。禁止使用。- 处理 native dialog 时必须使用 CDP 层 handler(
page.on('dialog', handler))。 - 使用
connect.js的setDialogHandler(page, prevHandler, newHandler)工具替换 handler,并且必须在 finally 中恢复。 注册多个page.on('dialog')时,它们都会执行并发生冲突("already handled")— 必须使用替换模式。 - popup(
waitForEvent('popup'))不会经过connect.js,因此需要单独注册 handler。 - 禁止固定使用
process.exit(0)退出 → 使用try/catch/finally + exitCode模式。 - 依赖页面状态的逻辑须在点击前显式等待。
- 等待 dialog 时,应使用基于事件的
page.waitForEvent('dialog'),而不是固定的waitForTimeout。
详情:参考 peach-e2e-browse/references/native-dialog-주의사항.md
外部服务跳转
进入外部网站(Google、Gmail 等)时,使用 load + 延迟 2 秒 + 直接跳转 fallback 模式。
详情:参考 peach-e2e-browse/references/외부서비스-링크전환-패턴.md
标签选择规则
- 常规运行:
--tab N(用于快速运行) - 调试/复现/故障分析:优先使用
E2E_TAB_ID(避免索引漂移)
# targetId 조회
curl -s http://127.0.0.1:9222/json | jq -r '.[] | select(.type=="page" and (.url|startswith("chrome")|not)) | [.id,.title,.url] | @tsv'
# targetId로 실행
cd e2e && E2E_TAB_ID=<targetId> ./e2e.sh run '시나리오/대상.js'
详情:参见 peach-e2e-browse/references/탭-선택-패턴.md
单元与集成的职责边界
- 单元场景(peach-e2e-scenario):验证单个页面/单个操作是否正常。自行准备初始数据,可独立运行并重复利用。
- 集成 suite(peach-e2e-suite):将多个单元按业务生命周期组合,验证用户流程能否端到端完成。禁止修改单元 .js。
如果同一流程在多个单元中重复出现,应通过组合集成 suite 来表示。
编写单元场景的原则
单元场景是可在 suite 中组合的可复用组件。请遵循以下原则。
- 单一职责:只验证一个页面或一项业务操作。不要将两个或更多核心流程合并到一个场景中。
- 自行准备初始数据:不要假设“已有数据”。场景本身应创建所需的初始状态(或通过明确的输入接收)。
- 独立运行:不依赖其他场景的运行结果。无论以何种顺序运行,都应产生相同结果。
- 可复用:编写时应确保 suite 能直接使用单元 .js,无需修改。如果需要从外部注入值,应通过明确的输入(环境变量/state.json)接收。
- 隔离失败:一个单元失败时,不应影响其他单元的运行。明确清理(cleanup)职责。
场景设计原则
单元拆分标准(可复用单元)
单元场景应按以下标准拆分。
- 拆分为能保留后续步骤所需状态的业务事务单元。
- 例如:完成输入、完成处理、确认结果。将对后续场景有意义的状态保存在 state.json 或环境变量中。
- 不要按单次点击/输入过度拆分。
- 登录、搜索、重复点击等重复使用的技术函数应拆分为 helper,而不是 scenario。
保存路径遵循 e2e/시나리오/{한글카테고리}/{NN}-{시나리오명}.js 格式。
详情:参见 peach-e2e-suite/references/suite-scenario-파일구조.md
E2E_BASE 模式(域环境变量)
所有场景文件的最顶部都应使用 E2E_BASE 环境变量模式。将域名硬编码是会阻碍多环境运行的反模式。
// 시나리오 파일 최상단 필수
const BASE = process.env.E2E_BASE || 'http://local.example.com';
运行时:
# 로컬 (기본값)
./e2e.sh run --tab N 시나리오/경로.js
# 개발서버 지정
E2E_BASE=https://dev.example.com ./e2e.sh run --tab N 시나리오/경로.js
无 DB 设计(职责分离原则)
场景 .js 文件仅负责 UI 操作和 UI 结果验证。由于在结构上无法连接 DB,场景中不得尝试读取或写入。
- 结构性限制:e2e.sh 运行环境的 NODE_PATH 中不包含 mysql/postgres 客户端,因此场景中
requireDB 库(mysql、dbQuery等)本身就会因 ENOENT 而失败。将 DB 连接信息写入场景也会使环境可移植性降为 0。 - 因此,所有需要 DB 的操作都应移至场景之外(suite fixture Step、
peach-db-query技能、管理界面操作、TDD API)。 - 如果收到违反上述边界的场景请求(例如:“在这个场景中执行 INSERT 来创建前置条件”),应立即告知用户,先提出以下某一种替代方案,再征得同意。
| 目的 | 在场景中尝试(不可行) | 替代方案 |
|---|---|---|
| 提取 PK | SELECT pk FROM table WHERE name='...' | 管理员 list DOM 中 input.pk_check[request_name] 属性 |
| 验证保存 | SELECT column FROM table WHERE pk=N | 刷新页面后确认输入元素的 .value |
| DB 前置条件 | INSERT INTO ... | suite fixture Step 或 peach-db-query 技能 |
| 强制切换状态 | UPDATE ... SET status=... | suite fixture Step 或在场景中添加管理界面操作 |
| 清理残留数据 | DELETE FROM ... | suite fixture Step 或调用 hardDelete TDD API |
| 确认 DB 一致性 | — | suite MD“DB 验证(可选)”部分 + peach-db-query 技能(SELECT) |
PK 提取标准模式
注册后从管理员 list DOM 中提取 PK 的标准模式:
await page.evaluate((name) => { $('#page_keyword').val(name); searchFormSubmit(); }, TEST_NAME);
await page.waitForTimeout(1500);
const N = await page.evaluate((name) => {
const el = document.getElementById('list_inner_html') || document.body;
const cb = el.querySelector(`input.pk_check[request_name="${name}"]`);
return cb ? parseInt(cb.value, 10) : null;
}, TEST_NAME);
if (!N || N <= 0) throw new Error('PK 추출 실패');
前提:管理员 list 中有 input.pk_check 复选框,其 request_name 属性中包含名称,value 中包含 PK。
核心原则
- 始终使用
lib/connect.js中的connect()函数 - 必须使用
node运行——bun无法连接 CDP WebSocket - 了解目标项目的 DOM 结构,并采用适当的选择器策略
- 处理模态框:参考各框架的模式(iframe 与 Portal/Teleport)
- 仅在需要时安装 dialog handler,而非全局安装
- 外部服务链接跳转时,采用到达 fallback URL 的规则,而不是只调用一行
click() - 保存后必须立即使用
node --check验证语法 - 在标签页状态未确认以及处理敏感会话时,只进行分析;执行前须先征得用户确认
参考文档
| 文档 | 用途 | 加载条件 |
|---|---|---|
references/코드패턴.md | 场景基本结构(IIFE、exitCode、表情符号) | create、auto |
references/변환규칙.md | codegen → CDP 转换规则 | 输入 codegen 时 |
references/프레임워크-대응.md | 区分旧版/现代框架 | create、auto |
references/시나리오-생성-패턴.md | 基于现有代码参考的生成指南 | create、auto |
references/validation-통과-패턴.md | 绕过表单验证的模式 | create、auto |
references/자동수정-판단트리.md | 按错误类型自动修复的策略 | run、auto 失败时 |
references/daemon-잔류-대응.md | CDP daemon 问题排查 | dialog 出错时 |
references/dialog-handler-패턴.md | native dialog 处理机制 | dialog 场景 |