Skip to content

端到端测试 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与执行策略
  8. 视觉回归与 UI 一致性验证
  9. 故障排查指南
  10. 结论
  11. 附录:测试脚本示例索引

引言 ​

本文件面向 AI Helper Chrome 扩展(Manifest V3,版本 2.3.1)的端到端测试体系。文档聚焦 Playwright e2e 测试框架的配置与环境搭建、浏览器自动化配置、测试环境准备、测试数据管理、E2E 场景设计、测试执行策略、具体测试脚本示例、视觉回归与 UI 一致性验证,以及测试维护指南。

本项目采用双进程架构:Chrome 扩展端与独立本地 Agent 端。Agent 端源码修改后必须重启进程,新接口才生效;但当前仓库中的 Playwright e2e 主要覆盖扩展侧内容脚本工具、侧边栏交互、选项页保存按钮栏等前端行为,不直接启动或连接 Agent HTTP/WebSocket 服务。因此,本节 E2E 文档以扩展端真实 Chromium 页面和 content script 工具为主。

项目结构 ​

Playwright e2e 测试位于 test/e2e,由根级 playwright.config.js 驱动,并通过 package.json 中脚本统一入口。

graph TB
Root["仓库根目录"] --> PWConfig["playwright.config.js"]
Root --> Package["package.json"]
Root --> TestE2E["test/e2e"]
TestE2E --> Helpers["helpers/load-module.js"]
TestE2E --> SpecA["content-tools.e2e.spec.js"]
TestE2E --> SpecB["demo-product-form.e2e.spec.js"]
TestE2E --> SpecC["message-jump-interaction.e2e.spec.js"]
TestE2E --> SpecD["message-jump.e2e.spec.js"]
TestE2E --> SpecE["options-save-bar.e2e.spec.js"]
TestE2E --> SpecF["iframe-ref.e2e.spec.js"]

图表来源

章节来源

核心组件 ​

Playwright e2e 的核心由三部分构成:

组件职责关键实现位置
Playwright 配置定义测试目录、并行策略、重试、headless、动作超时、Chromium 设备playwright.config.js
模块加载器使用 esbuild 将 content script 相关模块打包为 IIFE,注入到被测页面并暴露全局调用能力test/e2e/helpers/load-module.js
测试用例集覆盖内容工具链路、商品录入 Demo、消息跳转交互、消息跳转布局、选项页保存按钮栏吸附、iframe 跨帧 ref各 .e2e.spec.js 文件

Playwright 配置要点 ​

  • 测试目录:./test/e2e
  • 并行执行:开启 fullyParallel
  • CI 模式:forbidOnly 在 CI 下启用,避免误提交 test.only
  • 失败重试:CI 下重试 1 次,本地默认 0 次
  • 浏览器运行:headless 模式,动作超时 10 秒
  • 项目:仅 Chromium,使用桌面 Chrome 设备描述

章节来源

模块加载器 ​

load-module.js 通过 esbuild 把以下 content script 模块聚合为 IIFE:

  • src/content/page-utils.js
  • src/content/shadow-dom-utils.js
  • src/content/page-interaction.js
  • src/content/page-extract.js
  • src/content/interaction-tools.js
  • src/shared/page-snapshot-renderer.js

打包结果挂载到 window.__tools,并提供:

  • getContentBundle():缓存 bundle,避免重复构建
  • callTool(page, fnName, ...args):在 page 上下文调用工具函数
  • callToolInFrame(page, frameName, fnName, ...args):在指定 iframe 上下文中调用工具

该设计使 e2e 测试能在真实 Chromium 中直接验证 content script 的工具链,而不必依赖扩展安装流程。

章节来源

架构总览 ​

Playwright e2e 的执行路径可概括为:

sequenceDiagram
participant Dev as "开发者"
participant NPM as "npm test : e2e"
participant PW as "Playwright"
participant Browser as "Chromium"
participant Page as "被测页面"
participant Tools as "window.__tools"
Dev->>NPM : 运行 npm run test : e2e
NPM->>PW : playwright test
PW->>Browser : 启动 headless Chromium
Browser->>Page : 导航到 file : // 或内置 HTML
Page->>Tools : addInitScript 注入 IIFE
Page->>Tools : 调用 query / interact / extract 等工具
Tools-->>Page : 返回 success / content / availableOptions 等
Page-->>PW : expect 断言
PW-->>Dev : 测试结果

图表来源

详细组件分析 ​

内容工具端到端测试 ​

content-tools.e2e.spec.js 是内容脚本工具链的代表性 e2e 用例,覆盖:

  • queryInteractiveElements → interactByRef 完整链路
  • fillForm 多类型表单填充
  • selectDropdown 原生 select 选择
  • clickByText 文本点击
  • Shadow DOM 穿透查询与点击
  • scrollAndCollect 无限滚动收集
  • extractLinks、pageToJson 链接与表格提取
  • searchInPage 正则搜索
  • getIframeContent 同源 iframe 内容获取
  • queryInteractiveElements 分页、叠加层提升、去重、ref 稳定性

该用例通过 addInitScript 注入 window.__tools,再使用 callTool 调用工具方法,最后用 Playwright 断言 DOM 状态、返回值字段和交互结果。

flowchart TD
Start(["进入用例"]) --> LoadBundle["加载 content 工具 bundle"]
LoadBundle --> Inject["addInitScript 注入 window.__tools"]
Inject --> Navigate["导航到 fixtures 页面"]
Navigate --> Query["调用 queryInteractiveElements"]
Query --> ValidateQuery{"查询成功?"}
ValidateQuery --> |否| Fail["断言失败"]
ValidateQuery --> |是| Interact["调用 interactByRef 或 fillForm/select/click"]
Interact --> AssertDOM["断言 DOM 值、属性、可见性"]
AssertDOM --> End(["用例结束"])

图表来源

章节来源

商品录入 Demo 页面冒烟测试 ​

demo-product-form.e2e.spec.js 针对演示页面进行冒烟测试,覆盖:

  • 四步向导流转
  • 模态框打开、条款勾选、确认提交
  • 提交后列表追加、回到 Step1
  • 必填校验阻止下一步并显示错误
  • 双语切换保持选中值与持久化
  • 清空列表恢复空态
  • 叠加层提升到 [打开层],ref 可操作

该用例具备“素材缺失自动跳过”机制:若 .resources/demo/form-autofill/product-form.html 不存在,则整组用例 skip,避免克隆仓库时出现无关失败。

flowchart TD
CheckDemo["检查 demo 页面是否存在"] --> HasDemo{"存在?"}
HasDemo --> |否| Skip["跳过整组用例"]
HasDemo --> |是| RunSuite["运行商品录入用例"]
RunSuite --> StepFlow["四步向导填写"]
StepFlow --> Modal["打开确认模态框"]
Modal --> Terms["勾选条款并提交"]
Terms --> ListAppend["列表追加记录"]
ListAppend --> Reset["重置或清空列表"]
Reset --> OverlayRef["叠加层 ref 操作"]
OverlayRef --> End(["用例结束"])

图表来源

章节来源

消息跳转交互测试 ​

message-jump-interaction.e2e.spec.js 用真实鼠标、键盘事件驱动侧边栏消息跳转把手,覆盖:

  • 悬停把手展开列表
  • 鼠标移出自动收起,钉住后移出保持展开
  • Tab 键盘可达,↑/↓ 移动焦点
  • 搜索过滤命中子集,编号仍为全局组序
  • 中文输入法组合期间不销毁输入框,上屏后才过滤
  • Esc 优先清空搜索词,再按一次退钉住/收起
  • 边界反馈:最后一组继续向下跳时按钮进入 blocked 态
  • 钉住后手动滚列表去点远处条目,不会被“跟随当前项”拽回顶部
  • 点击条目后移开鼠标再滚对话,当前项会滚进列表可视区

该用例通过 esbuild 动态构建 NavKit,并在内存 HTML 中注入真实样式与 DOM,从而验证真实交互而非纯逻辑。

sequenceDiagram
participant PW as "Playwright"
participant Page as "内存 HTML 页面"
participant NavKit as "NavKit.initMessageJumpNav"
participant User as "用户交互"
PW->>Page : setContent(navPageHtml)
Page->>NavKit : initMessageJumpNav()
User->>Page : hover 把手
Page-->>PW : 面板 expanded
User->>Page : click 钉住
User->>Page : type 搜索词
User->>Page : press Escape
Page-->>PW : 清词、恢复全部、退钉住、收起

图表来源

章节来源

消息跳转布局与渲染测试 ​

message-jump.e2e.spec.js 侧重真实布局与滚动下的消息跳转分组定位,覆盖:

  • 问答组覆盖每条提问与其后的回答,编号连续
  • 按编号跳转后反查当前组得到同一编号
  • 连按上一条/下一条在组间移动并停在边界
  • 面板为实色表面,条目不折行成单行截断
  • 长提问恰好两行且由 CSS 画省略号
  • 折行的第二行与第一行文字左对齐
  • 当前组条目高亮态样式
  • 暗色主题下列表同样是实色底
  • 列表垂直滚动时 Header 固定可见
  • 面板无显式高度时列表区不得塌成 0
  • 预览文案折叠空白并按上限截断

该用例读取真实 theme.css 与 side_panel/styles.css,并使用真实 renderQuestionListHtml 生成面板内容,避免手写副本漂移。

章节来源

选项页保存按钮栏吸附测试 ​

options-save-bar.e2e.spec.js 验证真实浏览器下保存按钮栏的吸附行为:

  • 内容超出一屏:按钮栏吸附在视口底部保持可见
  • 滚到页面底部后释放回文档流
  • 内容一屏放得下:按钮栏保持在文档流正常位置

该用例通过 esbuild 打包 src/options/save-bar.js,并注入真实 src/options/styles.css,构造与真实 options 页面一致的层级结构。

章节来源

iframe 跨帧 ref 测试 ​

iframe-ref.e2e.spec.js 验证真实 iframe 环境下跨帧 ref 采集与整体渲染组装,覆盖:

  • auto 采集:frame 节点属性与 display:none 剪枝
  • none 采集旧入口薄包装
  • 子帧内采集:frameInfo 来自 srcdoc 文档、loadId 存在
  • 可见性判定:可见帧 true;display:none 与零尺寸 false
  • 组装渲染:占位行编号 + 子帧区块缩进 + 隐藏帧移除
  • 子帧内本地 ref 交互:注册表解析 + type 生效

该用例复用 load-module.js 提供的 callTool 与 callToolInFrame,确保跨帧工具调用路径正确。

章节来源

依赖关系分析 ​

e2e 测试对仓库其他部分的依赖如下:

graph LR
PWConfig["playwright.config.js"] --> Specs["所有 .e2e.spec.js"]
Specs --> LoadModule["helpers/load-module.js"]
Specs --> ContentModules["src/content/*"]
Specs --> SharedModules["src/shared/*"]
Specs --> SidePanelCSS["src/side_panel/styles.css"]
Specs --> ThemeCSS["src/shared/theme.css"]
Specs --> OptionsCSS["src/options/styles.css"]
Specs --> Esbuild["esbuild"]

图表来源

章节来源

性能与执行策略 ​

并行测试 ​

Playwright 配置开启 fullyParallel: true,意味着每个 spec 文件内的用例可在不同 worker 中并行执行。这能显著缩短 CI 时间,但也要求用例之间保持隔离,避免共享全局状态。

重试机制 ​

  • 本地环境:retries: 0
  • CI 环境:retries: 1

建议在新增不稳定用例时先定位根因,而不是盲目增加重试次数。对于网络或外部资源依赖的用例,应优先改为本地 fixture 或 mock。

动作超时 ​

actionTimeout: 10000 表示每次 action 最多等待 10 秒。若某个用例频繁超时,应检查:

  • 是否缺少 waitForSelector 或 waitForFunction
  • 是否动画未结束就断言
  • 是否 fixture 页面加载过慢
  • 是否使用了错误的定位器

调试模式 ​

可通过 npm run test:e2e:headed 启动 headed 模式,便于观察浏览器行为。该命令对应 package.json 中的脚本定义。

章节来源

视觉回归与 UI 一致性验证 ​

当前仓库的 Playwright e2e 并未使用截图对比类视觉回归库,而是通过以下方式保证 UI 一致性:

验证方式说明对应用例
真实样式加载测试直接读取 theme.css 与 side_panel/styles.css,避免样式漂移test/e2e/message-jump.e2e.spec.js
计算样式断言断言背景透明度、textOverflow、lineClamp、visibleLines 等test/e2e/message-jump.e2e.spec.js
主题断言断言暗色主题下面板背景与文字颜色test/e2e/message-jump.e2e.spec.js
吸附行为断言断言 .floating 类名与视口位置test/e2e/options-save-bar.e2e.spec.js
面板结构断言断言面板内部 header、list、item 的滚动行为test/e2e/message-jump.e2e.spec.js

如果需要引入截图对比,建议:

  • 使用 Playwright 内置 toMatchSnapshot
  • 固定 viewport 尺寸
  • 固定字体与缩放
  • 区分 light/dark 主题基线
  • 将基线图片纳入版本控制
  • 在 CI 中比较差异并生成报告

章节来源

故障排查指南 ​

常见问题与处理 ​

问题可能原因处理建议
用例报 test.only本地误提交 test.onlyCI 下 forbidOnly 会直接失败;删除 only
用例不稳定动画未结束、DOM 未就绪、fixture 加载慢增加 waitForSelector、waitForFunction,或使用 expect.poll
content 工具调用失败bundle 未注入或全局名不对检查 addInitScript 与 window.__tools
iframe 工具调用失败未找到目标 frame使用 callToolInFrame 并确保 frame name 匹配
样式断言失败主题变量或 CSS 变更同步更新测试断言,或修复样式
中文输入法导致列表重建异常composition 期间重建输入框参考 message-jump-interaction.e2e.spec.js 的组合事件断言
吸附行为异常视口高度或内容高度变化检查 setupPage 中 contentHeight 与 viewportSize

调试技巧 ​

  • 使用 npm run test:e2e:headed 观察真实浏览器
  • 在 beforeEach 中打印 page.url() 与关键 DOM 结构
  • 对复杂交互使用 page.screenshot() 辅助定位
  • 对异步动画使用 waitForTimeout 或更精确的状态等待
  • 对 fixture 页面问题,先用浏览器手动复现

章节来源

结论 ​

该项目的 Playwright e2e 测试体系围绕真实 Chromium、真实样式与真实 DOM 展开,重点验证内容脚本工具链、侧边栏交互、选项页吸附行为与 iframe 跨帧能力。测试通过 esbuild 动态打包模块、通过 addInitScript 注入工具、通过 fixture 页面模拟业务场景,既避免了安装扩展的复杂度,又保留了足够的真实性。

未来可扩展的方向包括:

  • 引入截图对比进行视觉回归
  • 增加更多跨页面流程验证
  • 补充 Agent 集成测试(需启动本地 Agent 进程)
  • 细化性能基准用例
  • 完善测试数据管理与版本化

附录:测试脚本示例索引 ​

测试目标文件路径关键能力
内容工具链路test/e2e/content-tools.e2e.spec.jsquery、interact、fillForm、select、clickByText、Shadow DOM、scroll_collect、extract、search、iframe_content
商品录入 Demotest/e2e/demo-product-form.e2e.spec.js向导流程、模态框、双语、列表、叠加层 ref
消息跳转交互test/e2e/message-jump-interaction.e2e.spec.jshover、click、keyboard、composition、Esc、blocked、pinned
消息跳转布局test/e2e/message-jump.e2e.spec.js分组定位、两行截断、省略号、高亮、暗色主题、滚动
保存按钮栏吸附test/e2e/options-save-bar.e2e.spec.jsfloating、视口底部、文档流释放
iframe 跨帧 reftest/e2e/iframe-ref.e2e.spec.jsauto/none 采集、frameInfo、可见性、渲染组装
模块加载器test/e2e/helpers/load-module.jsgetContentBundle、callTool、callToolInFrame