♻️ 重构本地验证流程:常驻会话 + 命令驱动,替代一次性 spec - #1674
Open
CodFrm wants to merge 7 commits into
Open
Conversation
启动一次浏览器常驻,之后逐条命令附着驱动,验证一件事不再需要 先写一个 spec 再整体重跑。 - session.mjs:start/status/stop,默认无头,--headed 供人工旁观 - drive.mjs:open/goto/click/fill/snapshot/shot/eval/sw/storage/install 等 - 端口向内核申请(listen(0))、profile 走 mkdtemp、证据落各自的 scenario 目录,多个 worktree 可并发验证 - 会话全程记录 console/pageerror 与操作,报告直接引用
原先 9 处把 "--headless=new" 写死在 args 里,而启动参数会覆盖 Playwright 的 headless 选项,所以 headless: false(含 --debug/PWDEBUG) 其实一直开不出窗口。统一走 headlessArgs(),E2E_HEADED=1 才可见。
verification.md 以驱动会话为默认形式,写 spec 收敛为「顺序/时序即契约」 时的例外;驱动方法拆到 references/verification-methods.md;e2e/README.md 新增 §8 会话手册(命令表、证据目录、并发、能力边界)。
Playwright 只暴露页面的 console 事件,但脚本自测与后台脚本的断言打在 Service Worker、Offscreen 文档和 Sandbox iframe 里 —— 这些各自是独立 的 CDP target。改为连浏览器级 CDP 端点并递归 setAutoAttach。 - waitForDebuggerOnStart 保证 document-start 的输出不漏 - 每个 target 只 Runtime.enable 一次:重复 enable 会重放 console 历史 - 开 setDiscoverTargets,否则导航后 URL 停在附着那一刻 - 对象参数按 preview 渲染,不再是无信息的 Object
Collaborator
|
针对原 PR「♻️ 重构本地验证流程:常驻会话 + 命令驱动,替代一次性 spec」,我在原分支追加了 3 个修正 commits(未 force-push,未修改 PR 标题和描述):
本地验证证据:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist / 检查清单
N/A — 无关联 issue,本次是本地验证流程的自发重构。
Description / 描述
背景
本地验证一直是「写一个 spec → 整体跑一遍 → 看输出 → 想换个角度看 → 再改再跑」。
代价在仓库里是可量化的:
e2e/scratch/里累计了 20 个一次性 spec、6871 行,是 committed 套件(3251 行)的 2.1 倍,而它们几乎都只被跑过一次。
根因是没有可附着的浏览器:全仓
grep -rn "remote-debugging\|connectOverCDP"零命中,每次观察都必须从头启动一个 spec。
本次改动
e2e/session.mjs:启动一个常驻的、加载dist/ext的浏览器并保持存活。start/status/stop --all。e2e/drive.mjs:每次调用是一个短命进程,附着到会话做一件事。open/goto/click/fill/press/wait/snapshot/text/shot/eval/sw/storage/install/pages/use/close/console。Offscreen 文档、Sandbox iframe 里,它们各自是独立的 CDP target,Playwright 只暴露
页面的 console 事件。改为连浏览器级 CDP 端点并递归
setAutoAttach,四类上下文统一落到一个
console.log并标注来源。E2E_HEADED:原先 9 处把"--headless=new"写死在args里,覆盖了Playwright 的
headless选项 —— 也就是说headless: false和--debug一直开不出窗口。现在统一走
headlessArgs()。docs/verification.md改以驱动会话为默认形式;e2e/README.md新增§8 会话手册;驱动方法拆到
docs/references/verification-methods.md。实现考虑
--headed只为人工旁观保留。listen(0))而不写死;profile 走
mkdtemp,证据落各自的 scenario 目录。多个 worktree 可同时验证。已实测两个会话互不串扰(一个装了脚本读到 1,另一个读到 0)。
updateExtensionConfiguration授权userScripts会重载扩展,重载期间扩展自己的页面返回
ERR_BLOCKED_BY_CLIENT。所以授权放在一次性启动里,再从同一 profile 重启接管 —— 与既有 fixture 已验证过的两阶段模式同源。
Runtime.enable一次,重复 enable 会重放该上下文的 console 历史造成成倍重复;不开
setDiscoverTargets就收不到targetInfoChanged,页面导航后来源会一直停在附着那一刻的
about:blank;对象参数不带value,必须按preview渲染,否则断言里的
{passed, failed}只会记成Object。snapshot的选择器优先级:testid > 稳定 id > 可见文本。Radix 生成的radix-_r_0_每次渲染都会变,明确排除。已知限制
会话不适合验证 Service Worker 的驱逐 / 空闲终止行为,那条线仍走
keep-alive.spec.ts。.test域名映射,需要 mock server 的验证仍走 scratch spec。snapshot不进 iframe。e2e/scratch/下清掉了 21 个一次性文件;发版配图工具(
mobile-shots.spec.ts/promo-render.spec.ts/_assets/)保留,它们仍是平铺的,未纳入
<scenario>/约定。建议审查重点
e2e/fixtures.ts的headlessArgs()被另外三个 fixture 引入,确认 CI 仍为无头。attachConsoleCollector():waitForDebuggerOnStart要求每个 target 都必须收到runIfWaitingForDebugger,否则新 target 会被永久挂起 —— 这条路径值得重点看。session.mjs的 SIGTERM/context.on("close")清理路径,是否会残留 profile 或进程。drive.mjs的wrapEvalSource():带return当函数体、否则当表达式。验证
覆盖了全部 4 个被改动的 fixture 文件(
fixtures/server-fixtures/agent-fixtures/gm-api内联 fixture)。会话本身的实测(非推断):
(src/service_worker.js)、(src/sandbox.html)(装一个
@background脚本并启用后打出的行)、(src/options.html);对象渲染为{passed: 29, failed: 0}而非Objectstop --all后无残留 profile 与进程E2E_HEADED=1与session.mjs --headed均确认开出真实窗口(UA 无Headless)dist/ext/manifest.json缺失时start拒绝启动,退出码 1snapshot→click [data-testid="theme-toggle"]→documentElement.className变为
dark、lightMode=dark文档检查:6 个文档的 69 条相对链接与锚点全部解析通过;文中每条命令均已实跑。