Slate v2 的 WPT 收获测试加工:五大浏览器基座队列驱动的浏览器测试计划方法论
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
导读
本文基于 Plate 仓库中的 Slate v2 WPT Harvest Test Processing Ralplan 及其配套的行账目文档,完整还原一条从 Web Platform Tests(WPT)聚焦收获、到行级账目核算、再到"五条浏览器基座队列"落地执行的原始 Slate 浏览器测试计划。读者将掌握:为什么 1,139 个 WPT 文件不应被直接移植为 1,139 个测试、如何用行账目把收获文件归类为 portable / harness / skip / defer / uncertain 五类、WPT-1 至 WPT-5 五条执行队列各自的目标不变量与验证命令,以及"浏览器行为必须用浏览器证明、包级测试不替代浏览器证明"的决策边界。
一、问题背景:收获(Harvest)不等于可执行测试
Slate v2 在重构浏览器基座层时,面临一个典型的测试工程问题:上游 WPT(Web Platform Tests)为 contenteditable 编辑行为提供了海量素材,但收获原始素材 ≠ 获得可执行的测试计划。原始收获是面向 WPT 仓库自身组织结构的文件清单,而 Slate v2 需要的是"每条测试行都有 owner、action、proof kind、目标位置和验证命令"的执行级计划。
本 Ralplan 的意图边界(Intent Boundary)写得非常明确:
- 意图:把 WPT 聚焦编辑器收获转化为可执行的原始 Slate v2 测试计划;
- 结果:每条被提升(promoted)的 WPT 矩阵行都具备 Slate owner、action、proof kind、目标位置与验证命令;
- 范围内:原始 Slate 的浏览器输入、选区、剪贴板、contenteditable 结构性编辑、焦点与 Shadow DOM 行为;当前
.tmp/slate-v2包与浏览器测试 owner;带有 WPT 路径来源的本地不变量措辞; - 范围外:Plate 插件/产品行为、上游 WPT 的 helper / fixture / snapshot / 文案、超出聚焦收获的广泛 WPT 仓库挖掘、实时 GitHub issue 认领。
这一边界划分是本计划的灵魂:原始 Slate 只拥有基座(substrate)行为,Plate 产品行为一律排除在行之外。
二、核心判断:五条浏览器基座队列,而非 1,139 个直接移植
本计划最关键的战略结论(Current Verdict)是:
把 WPT 加工进 Slate v2 的方式是五条浏览器基座队列(five browser-substrate queues),而不是把 1,139 个文件直接移植为 1,139 个测试。起点应放在原生输入(native input)与 DOM Selection/Range,因为它们是原始 Slate 浏览器风险中杠杆率最高的两个面,且已有强 owner 测试可供去重(dedupe)。
这一判断的底层逻辑是:WPT 素材以浏览器行为为单位组织,而 Slate v2 的测试以"不变量 + owner"为单位组织。直接按文件数量移植会产生大量与现有 owner 测试重复的用例,而按基座行为归类,则可以把 1,139 个素材收敛为 5 条可执行、可验证、可去重的队列。
同时,计划自身声明"ready for Ralph execution":不产生任何实现编辑(no implementation edits)、不认领 Slate issue、不产生 Plate/产品积压认领。它是一份纯测试加工计划。
三、收获落地(Harvest Grounding):素材的出处、版本与许可约束
计划对素材来源做了完整登记,这是"证据可追溯"的基础:
| 字段 | 值 |
|---|---|
| 收获报告 | .tmp/editor-test-harvester/wpt/report.md |
| 库存清单 | .tmp/editor-test-harvester/wpt/inventory.md |
| 测试索引 | .tmp/editor-test-harvester/wpt/test-index.md |
| 收获报告进入时的状态 | pending(lane 级映射被推迟到本计划处理) |
| WPT 检出目录 | ../wpt |
| WPT 修订版本 | dd54691426 |
| 许可模式 | permissive(宽松许可),证据见../wpt/LICENSE.md |
| 输出模式 | scratch-forced-by-user(用户强制 scratch 输出) |
| 版本化策略 | 仅使用本地重新措辞的不变量;不复制上游代码、helper、fixture、snapshot 或文案 |
其中"版本化策略"值得强调:即使上游 WPT 是宽松许可,版本化输出也只用"带有 WPT 路径来源的本地措辞",绝不照抄上游内容。这一许可/来源纪律(License/Provenance Discipline)贯穿整个计划,并在置信度评分中获得最高的 0.96 分。
需要注意的是,收获报告、库存清单与测试索引均位于.tmp/editor-test-harvester/wpt/这一开发中间工作区;当前仓库快照中保留的永久化成果是行账目文档本身(仓库中另有docs/editor-test-harvester/目录记录 lexical、portabletext、prosemirror、tiptap、yjs-collaboration 等同类收获工作)。
四、行账目(Row Accounting):1,139 个文件的五分类核算
计划对聚焦收获的全部 1,139 个文件做了行级核算,完整账目见行账目文档。汇总如下:
| 源类别 | 数量 | 车道决策 |
|---|---|---|
| 提升的矩阵行 | 5 | 全部在车道内,编为 WPT-1 至 WPT-5 |
| 聚焦库存文件 | 1,139 | 按类别/动作分组;并非全部是 Slate 测试 |
| 可移植行 | 518 | 分组进 WPT-1 至 WPT-5 |
| 可移植-混合行 | 198 | 拆分原始基座部分;产品/插件行为排除 |
| 测试框架行 | 172 | 跳过 |
| 跳过行 | 182 | 车道外 |
| 延迟行 | 7 | 显式延迟 |
| 不确定行 | 62 | 不提升为 Slate v2 行;等待未来收获 pass 提升 |
这组数字揭示了"1,139 不等于 1,139 个测试"的直接证据:
- 518 + 198 =716 行进入五条队列的候选池;
- 172 行是 WPT 自身的测试框架/基础设施,与 Slate 行为无关;
- 182 行是明确的 lane 外内容;
- 7 行被显式延迟(defer);
- 62 行因归属不明确而不被提升,等待后续收获 pass 再行裁决。
五、当前 owner 覆盖:先搜索现状,再决定补什么
计划遵循"先搜索现有测试,再标记行动行"的纪律(Ralplan gate),对.tmp/slate-v2的现行测试按输入、选区、剪贴板、删除、焦点、Shadow DOM 等关键词做了 owner 搜索。五类基座行为各自映射到的现有 owner 文件如下:
- 原生输入(Native input):
packages/slate-react/test/model-input-strategy-contract.test.ts、packages/slate-react/test/selection-controller-contract.ts、packages/slate-react/test/editing-kernel-contract.ts、playwright/integration/examples/plaintext.test.ts、playwright/integration/examples/rendering-strategy-runtime.test.ts; - 选区/Range(Selection/Range):
packages/slate-browser/test/browser/selection.browser.test.ts、packages/slate-browser/test/core/selection.test.ts、packages/slate-react/test/selection-controller-contract.ts、packages/slate-react/test/dom-coverage-boundary-contract.tsx、playwright/integration/examples/dom-coverage-boundaries.test.ts、playwright/integration/examples/inlines.test.ts、playwright/integration/examples/shadow-dom.test.ts; - 剪贴板/DataTransfer:
packages/slate/test/clipboard-contract.ts、packages/slate-dom/test/clipboard-boundary.ts、packages/slate-dom/test/clipboard-boundary.test.ts、packages/slate-react/test/dom-coverage-native-bridge-contract.test.ts、playwright/integration/examples/paste-html.test.ts; - 结构性编辑/删除/插入:
packages/slate/test/delete-contract.ts、packages/slate/test/transforms-contract.ts、packages/slate/test/transforms/**、packages/slate-react/test/dom-coverage-native-bridge-contract.test.ts、playwright/integration/examples/inlines.test.ts、playwright/integration/examples/rendering-strategy-runtime.test.ts; - 焦点/Shadow DOM:
packages/slate-react/src/editable/runtime-focus-mouse-events.ts、packages/slate-react/src/editable/selection-controller.ts、playwright/integration/examples/shadow-dom.test.ts、playwright/integration/examples/iframe.test.ts、playwright/integration/examples/read-only.test.ts。
这些路径均位于.tmp/slate-v2开发工作区(当前仓库快照未包含该中间目录,属于收获加工过程中的内部产物);当前仓库中对应的永久源码与测试组织可从 packages/slate、packages/slate-react、packages/slate-dom 等目录进一步查阅。owner 覆盖搜索的意义在于:每条队列的默认动作是"重构现有测试 + 只补缺口",而不是无脑新增,这直接控制了测试膨胀。
六、执行队列:WPT-1 至 WPT-5 的目标不变量与落地动作
这是整个计划的核心可执行部分。五条队列每条都明确了收获行、目标不变量、动作、目标文件与证明方式:
队列 1:WPT-1 beforeinput/input(原生输入)
- 目标不变量:原生输入必须保留事件类型(event type)、目标范围(target range)、DataTransfer 所有权、取消(cancellation)以及 readOnly / model / native 所有权语义;
- 动作:先重构现有测试;仅为缺失的 DataTransfer / cancel / readOnly 行新建测试;
- 目标文件:
packages/slate-react/test/model-input-strategy-contract.test.ts、packages/slate-react/test/selection-controller-contract.ts、playwright/integration/examples/plaintext.test.ts、playwright/integration/examples/rendering-strategy-runtime.test.ts; - 证明方式:package + Chromium 浏览器。
队列 2:WPT-2 DOM Selection/Range(选区导入导出)
- 目标不变量:DOM Selection/Range 的导入/导出必须在 hidden、removed、shadow、detached、odd range 状态下fail closed(失败即关闭,宁可拒绝也不导入脏状态);
- 动作:重构现有测试;为 selection / dom-coverage 测试未覆盖的状态补窄缺口行;
- 目标文件:
packages/slate-browser/test/browser/selection.browser.test.ts、packages/slate-react/test/selection-controller-contract.ts、playwright/integration/examples/dom-coverage-boundaries.test.ts、playwright/integration/examples/shadow-dom.test.ts; - 证明方式:browser + package。
队列 3:WPT-3 clipboard/DataTransfer(剪贴板所有权)
- 目标不变量:剪贴板/DataTransfer 事件在取消时归应用所有(app-owned)、仅在接受时归模型所有(model-owned);复制/粘贴不得泄漏渲染包装器,也不得丢失换行;
- 动作:重构现有测试;仅在取消与 DataTransfer 载荷路径周围补缺口行;
- 目标文件:
packages/slate/test/clipboard-contract.ts、packages/slate-dom/test/clipboard-boundary.ts、packages/slate-react/test/dom-coverage-native-bridge-contract.test.ts、playwright/integration/examples/paste-html.test.ts; - 证明方式:package + 桌面浏览器。
队列 4:WPT-4 contenteditable 结构性编辑
- 目标不变量:删除(delete)、插入(insert)、分割(split)、noneditable、void、SVG/table/hidden/removed-node 等场景不得崩溃,且必须路由到明确的 core 或 browser owner;
- 动作:重构现有测试;去重之后才创建浏览器压力测试行;
- 目标文件:
packages/slate/test/delete-contract.ts、packages/slate/test/transforms-contract.ts、packages/slate/test/transforms/**、playwright/integration/examples/inlines.test.ts、playwright/integration/examples/rendering-strategy-runtime.test.ts; - 证明方式:package + browser。
队列 5:WPT-5 focus/Shadow DOM(焦点与影子 DOM)
- 目标不变量:焦点、activeElement、shadow-root 内选区、iframe、blur、detached host 移动不得导入陈旧或外部(foreign)DOM 选区;
- 动作:重构现有测试;为 detached / shadow host 缺口补 fail-closed 行;
- 目标文件:
packages/slate-react/src/editable/selection-controller.ts、playwright/integration/examples/shadow-dom.test.ts、playwright/integration/examples/iframe.test.ts、playwright/integration/examples/read-only.test.ts; - 证明方式:browser。
从五条队列的目标不变量可以归纳出两条贯穿性的安全语义:fail closed(失败即关闭)——遇到无法可靠解释的 DOM 状态宁可拒绝导入;app-owned vs model-owned——事件所有权必须随接受/取消状态切换,这是剪贴板与原生输入行为正确性的分水岭。
七、聚焦验证命令:先窄后宽的执行纪律
计划为执行者 Ralph 给出了明确的命令执行顺序:"先跑聚焦门(focused gates),只有当实现触及共享运行时代码时才放宽范围"。
slate-react 包级聚焦命令(在.tmp/slate-v2/packages/slate-react下执行):
bun test:vitest test/model-input-strategy-contract.test.ts test/selection-controller-contract.test.ts test/editing-kernel-contract.ts test/dom-coverage-native-bridge-contract.test.ts test/dom-coverage-boundary-contract.tsx工作区级组合命令(在.tmp/slate-v2下执行):
bun --filter slate-browser test:selection bun test ./packages/slate/test/clipboard-contract.ts ./packages/slate-dom/test/clipboard-boundary.ts ./packages/slate/test/delete-contract.ts ./packages/slate/test/transforms-contract.ts bunx playwright test playwright/integration/examples/plaintext.test.ts playwright/integration/examples/dom-coverage-boundaries.test.ts playwright/integration/examples/paste-html.test.ts playwright/integration/examples/shadow-dom.test.ts playwright/integration/examples/inlines.test.ts playwright/integration/examples/rendering-strategy-runtime.test.ts --project=chromium其中bunx playwright test ... --project=chromium是浏览器证明的主体手段,覆盖 plaintext、dom-coverage-boundaries、paste-html、shadow-dom、inlines、rendering-strategy-runtime 六个 Playwright 示例。命令清单的搭配方式本身就是方法论:同一批不变量同时接受包级测试与 Chromium 浏览器测试双重检验。
计划还特别给出了一条 IME 红线:
如果某条 WPT 行成为 IME/组合(composition)行,必须使用真实浏览器组合证明(real browser composition proof)。不要把 jsdom 的 contenteditable composition 当作权威。
这条红线与仓库中既有 IME/移动端浏览器证明工作(见 docs/plans 下 2026-04-11 至 2026-04-12 的 IME/mobile browser 系列计划)一脉相承:jsdom 对组合输入行为的模拟不可作为浏览器行为证据。
八、排除行与决策边界:什么不该进 Slate v2
计划对不进车的行做了显式登记,防止范围蔓延:
| 家族 | 决策 |
|---|---|
| WPT support/resources/reference 文件 | skip |
| 手动(manual)文件 | skip |
| 剪贴板权限、权限策略、grants | 车道外浏览器策略 |
| 通用 Shadow DOM slots/style/layout | 车道外(除非与选区、焦点、caret、输入或编辑宿主行为绑定) |
| 编辑数据 fixtures | 延迟(待收获解释产生直接不变量后再处理) |
| EditContext tentative API | 延迟 |
| Plate 插件/产品行为 | 车道外 |
同时,计划明确了"决策边界"(Decision boundary):包级测试可以关闭 model/core 行为;而浏览器、剪贴板、选区、焦点、Shadow DOM、IME、原生输入等声明必须有浏览器证明。这意味着在验收标准上,包级测试通过 ≠ 浏览器行为正确,二者不可互相替代。
九、Ralplan 门控与通行状态账目(Pass-State Ledger)
作为一份 "ralplan"(ralph + plan)类型的计划,文档末尾完整列示了所应用的 Ralplan 门控清单与各 pass 的完成状态:
应用的 Ralplan 门控(Slate Ralplan Gates Applied):
- 意图、结果、范围、非目标、决策边界均显式;
- 原始 Slate 只拥有基座行为;Plate/产品行保持排除;
- 行动行被标记前,已先搜索当前
.tmp/slate-v2测试; - 浏览器声明具备浏览器证明命令;
- 包级检查不计入浏览器证明;
- 无 issue 认领变更;无需为 WPT 来源编辑
docs/slate-issues/**; - 上游 WPT 的代码、helper、fixture、snapshot、期望输出与文案均不复制进版本化输出;
- 执行交给 Ralph;本技能不编辑
.tmp/slate-v2。
Pass 状态账目(节选关键项):
| Pass | 状态 | 证据 |
|---|---|---|
| 参数解析 | complete | 依据先前请求的下一步推断出slate-v2 .tmp/editor-test-harvester/wpt/report.md |
| 产物验证 | complete | 读取了 report、inventory、test-index 与 harvester 完成文件 |
| 行账目 | complete | 附录核算了提升的矩阵行与全部 1,139 个库存文件 |
| 当前 owner 搜索 | complete | 按 input/selection/clipboard/delete/focus/shadow 术语搜索了实时.tmp/slate-v2测试与源码 |
| 下游 Slate Ralplan 应用 | complete | 浏览器证明、owner 拆分、无 issue 认领、无源码编辑 |
| Ralph 全量执行 | complete | WPT-1 至 WPT-5 已加工进.tmp/slate-v2;聚焦 package、typecheck、lint 与 Chromium 浏览器门全部通过 |
十、Ralph 执行结果:五条队列的落地实况
计划附带执行后的结果账目,逐队列给出最终处置与证据:
| 队列 | 结果 | 证据 |
|---|---|---|
| WPT-1 beforeinput/input | implemented | 在.tmp/slate-v2/packages/slate-react/test/editing-kernel-contract.ts新增了beforeinputDataTransfer 命令覆盖;Slate React 聚焦 owner 套件通过 |
| WPT-2 DOM Selection/Range | implemented | takeEditorSelectionSnapshot现在对外部/部分外部 DOM 选区返回null(fail closed);slate-browser选区套件 7 个测试通过 |
| WPT-3 clipboard/DataTransfer | deduped plus payload row | 现有 native bridge、Slate clipboard、Slate DOM clipboard 套件已覆盖 readOnly/app-owned/copy/paste/drop 所有权;DataTransfer beforeinput 载荷路由在 WPT-1 下补入 |
| WPT-4 contenteditable 结构性编辑 | deduped | 现有 delete、transforms、inlines、rendering-strategy、void、table、DOM coverage 行已覆盖被提升的结构性编辑队列;package 与 Chromium 浏览器门通过 |
| WPT-5 focus/Shadow DOM | implemented plus deduped | 新增 shadow-root 选区快照行;现有 shadow DOM 与 iframe 浏览器行覆盖浏览器焦点/根行为 |
执行后的"新鲜验证"命令(fresh verification,全部在.tmp/slate-v2工作区执行):
bun --filter slate-browser test:selectionbun test:vitest test/editing-kernel-contract.test.ts test/model-input-strategy-contract.test.ts test/selection-controller-contract.test.ts test/dom-coverage-native-bridge-contract.test.ts test/dom-coverage-boundary-contract.test.tsxbun test ./packages/slate/test/clipboard-contract.ts ./packages/slate-dom/test/clipboard-boundary.test.ts ./packages/slate/test/delete-contract.ts ./packages/slate/test/transforms-contract.ts bun test ./packages/slate/test/transforms-contract.ts bunx playwright test playwright/integration/examples/plaintext.test.ts playwright/integration/examples/dom-coverage-boundaries.test.ts playwright/integration/examples/paste-html.test.ts playwright/integration/examples/shadow-dom.test.ts playwright/integration/examples/inlines.test.ts playwright/integration/examples/rendering-strategy-runtime.test.ts --project=chromium bun --filter slate-browser typecheck bun --filter slate-react typecheck bun lint:fix注意执行结果中的一个重要模式:五条队列中只有 WPT-1、WPT-2、WPT-5 新增了测试行(implemented),WPT-3 与 WPT-4 以去重(deduped)为主。这正是"先搜索 owner、默认重构、只补缺口"纪律的实证——收获素材的多数价值在于确认既有覆盖并暴露少量真实缺口,而非无限堆测试。
十一、置信度评分:0.94 的依据
计划以五维置信度评分收尾,总分为 0.94:
| 维度 | 得分 | 证据 |
|---|---|---|
| 收获源就绪度 | 0.95 | 记录了 report、inventory、test-index、修订版本、许可与输出模式 |
| 车道过滤完备性 | 0.93 | 五条提升矩阵行全部路由;完整库存按需分组/排除/延迟 |
| 当前 owner 覆盖映射 | 0.92 | 实时.tmp/slate-v2测试/源码已搜索并映射到每行 |
| 执行队列可行动性 | 0.94 | 每条车道内行都有 owner、目标文件、证明种类与聚焦命令 |
| 许可/来源纪律 | 0.96 | 宽松许可源仍仅使用本地措辞与路径来源 |
这五维评分本质上是计划质量的自我审计维度,可以复用为任何"素材收获 → 测试计划"类任务的验收模板:源头可追溯、过滤可解释、owner 可执行、命令可复现、许可可合规。
十二、Ralph 交接(Handoff)
计划以交接指令收尾,明确执行入口与启动顺序:
[$ralph](https://link.gitcode.com/i/1bed67b3af2128f9596e84bc42cf9d72) docs/plans/2026-05-11-slate-v2-wpt-harvest-test-processing-ralplan.md并给出三条执行约束:
- 从队列 1 与队列 2 开始(原生输入与 DOM Selection/Range,即风险杠杆最高的两面);
- 在添加测试前,先与点名的当前 owner 文件去重;
- 不要重开 TinyMCE TMS 车道;不要仅凭 WPT 行更改 Slate issue 认领——除非后续执行以精确证据复现了某个具名 issue。
总结
这份 Ralplan 展示了把外部测试语料(WPT)加工为内部可执行测试计划的标准方法论闭环:聚焦收获 → 行账目五分类 → 当前 owner 搜索 → 五条基座队列(每条含不变量/动作/目标文件/证明方式)→ 聚焦验证命令 → 排除行与决策边界 → 门控与状态账目 → 执行结果回写 → 置信度自评 → 交接指令。对于任何面临"外部语料如何低成本转化为高质量测试资产"的编辑器团队,WPT-1 至 WPT-5 的队列划分逻辑(先重构、只补缺口、浏览器声明用浏览器证明、fail closed 与 app-owned/model-owned 语义)都是可以直接复用的工程范式。
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考