一键导入
lina-e2e
Playwright E2E 测试用例管理规范。定义文件命名(模块本地 TC{NNN})、目录布局、TC ID 分配、文件隔离和子断言模式。创建、规划或审查 OpenSpec 变更中的 E2E 测试用例时使用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Playwright E2E 测试用例管理规范。定义文件命名(模块本地 TC{NNN})、目录布局、TC ID 分配、文件隔离和子断言模式。创建、规划或审查 OpenSpec 变更中的 E2E 测试用例时使用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
手动触发:将主仓库与 apps/lina-plugins 对齐最新 main 后, 按提示在两侧各建独立分支;分支就绪后继续处理提示词中的后续请求。 必须用户手动触发,禁止自动触发该技能。
用于处理用户对已有实现的反馈分诊与执行闭环:先判断是否需要纳入 OpenSpec 活跃变更或新建变更,再完成根因分析、实现、验证和必要测试。凡是用户针对已有实现反馈 Bug、缺陷、改进点、建议或实现遗漏,即使没有明确提到“反馈”或 OpenSpec,也必须使用本技能。
用于审查 LinaPro OpenSpec 工作流中的代码变更和规范合规性。在完成 /opsx:apply 任务、 完成 lina-feedback 反馈修复、执行 /opsx:archive 归档前必须使用;在用户要求代码审查、 规范合规检查,或明确调用 /lina-review 时也必须使用。
手动触发:为 LinaPro 主仓库及 apps/lina-plugins 子模块完成提交、PR 前 rebase、推送、创建 PR, 主仓 CI 修复回路,以及 PR 合并后恢复原始分支并同步 main。禁止自动触发。
审查 LinaPro 社区 GitHub Issues,并按项目规范和源码实现分类处理。 必须用户手动触发,禁止自动触发该技能。
先执行 lina-openspec-archive-changes 归档活跃变更,再执行 lina-openspec-archive-consolidate 做归档摘要。 必须用户手动触发,禁止自动触发。
| name | lina-e2e |
| description | Playwright E2E 测试用例管理规范。定义文件命名(模块本地 TC{NNN})、目录布局、TC ID 分配、文件隔离和子断言模式。创建、规划或审查 OpenSpec 变更中的 E2E 测试用例时使用。 |
| compatibility | 依赖 Playwright。 |
本项目中 Playwright E2E 测试用例的组织、命名和编写标准。
交互语言:与用户交互的内容语言以用户上下文使用的语言为准,用户使用英文则使用英文,用户使用中文则使用中文。
规范来源:E2E 质量审查、截图验证、i18n 文案断言等执行要求的唯一事实来源为 .agents/rules/testing.md。本技能只负责用例组织、命名和目录布局,不重复维护质量审查和验证细则。创建或审查 E2E 用例时,必须读取并遵守 .agents/rules/testing.md 中的 E2E 质量审查要求和 E2E 截图验证要求。
hack/tests/
├── e2e/
│ ├── auth/ # 宿主模块:认证
│ │ ├── TC001-login-verification.ts
│ │ └── TC002-logout.ts
│ ├── admin/ # 宿主模块:管理功能
│ │ ├── TC001-spec-management.ts
│ │ └── TC002-user-management.ts
│ ├── notebook/ # 宿主模块:笔记本生命周期
│ │ ├── TC001-create-notebook.ts
│ │ ├── TC002-jupyterlab-access.ts
│ │ ├── TC003-training-execution.ts
│ │ ├── TC004-multi-image-notebook.ts
│ │ └── TC005-shared-directory.ts
│ └── {module}/ # 宿主新模块遵循相同模式
│ └── TC{NNN}-{brief-name}.ts
├── fixtures/
│ ├── auth.ts
│ ├── config.ts
│ └── k8s.ts
├── pages/ # 宿主/共享页面对象模型文件
│ ├── LoginPage.ts
│ ├── NotebookPage.ts
│ └── ...
└── playwright.config.ts
源码插件的插件专属 E2E 必须闭环在插件自己的目录中:
apps/lina-plugins/<plugin-id>/
└── hack/tests/
├── e2e/
│ └── TC{NNN}-{brief-name}.ts
├── pages/
│ └── <PluginPageObject>.ts
└── support/
└── <plugin-helper>.ts
关键规则:
hack/tests/e2e/{module}/。apps/lina-plugins/<plugin-id>/hack/tests/e2e/。hack/tests/e2e/extension/plugin/ 只用于宿主插件框架、动态插件运行时、源码插件生命周期这类宿主级插件能力测试;禁止把某个源码插件自身功能的 E2E 放到这里。每个测试文件必须遵循以下模式:
TC{NNN}-{brief-name}.ts
| 组成部分 | 格式 | 示例 |
|---|---|---|
| 前缀 | TC | TC |
| ID | 3 位数字,补零 | 001、012、100 |
| 分隔符 | - | - |
| 简短名称 | kebab-case | login-verification |
| 扩展名 | .ts | .ts |
完整示例:
TC001-login-verification.tsTC014-bulk-delete-notebooks.ts规则:
test.describe 块)。TC ID 只在当前模块目录内唯一并连续递增。.spec.ts 后缀,使用普通的 .ts。添加新测试用例前:
find hack/tests/e2e/<module> -maxdepth 1 -type f -name 'TC*.ts' | sort
# 或源码插件:
find apps/lina-plugins/<plugin-id>/hack/tests/e2e/<module> -maxdepth 1 -type f -name 'TC*.ts' | sort
示例: 如果当前模块目录内现有最大文件为 TC005-shared-directory.ts,则下一个测试用例为 TC006。
重要: TC ID 只在所属模块目录内维护,必须从 TC001 开始连续递增。不要因为其他模块或其他插件使用过更大的编号而跳号。
每个测试文件遵循以下结构:
宿主测试:
import { test, expect } from '../../fixtures/auth'
import { SomePage } from '../../pages/SomePage'
import { config } from '../../fixtures/config'
test.describe('TC-{N} {简短描述}', () => {
// 可选:共享设置
test.beforeEach(async ({ adminPage }) => {
// ...
})
test('TC-{N}a: {子断言描述}', async ({ page }) => {
// 单一聚焦断言
})
test('TC-{N}b: {子断言描述}', async ({ adminPage }) => {
// 另一个聚焦断言
})
test('TC-{N}c: {子断言描述}', async ({ adminPage }) => {
// ...
})
})
源码插件测试:
import { test, expect } from '../../../../../../hack/tests/fixtures/auth'
import { SomePluginPage } from '../pages/SomePluginPage'
test.describe('TC-{N} {插件功能描述}', () => {
test('TC-{N}a: {子断言描述}', async ({ adminPage }) => {
// 插件专属流程断言
})
})
文件内约定:
test.describe 标签使用 TC-{N}(不补零)后跟简短描述。TC-{N}{字母}: 作为前缀(如 TC-1a:、TC-1b:)。TC-{N}a~c:。每个测试文件必须可独立运行:
beforeEach、beforeAll、固件或内联设置自行完成。npx playwright test hack/tests/e2e/auth/TC001-login-verification.ts
pnpm -C hack/tests test:module -- plugin:<plugin-id>
所有页面交互必须通过页面对象类进行:
import { Page, Locator } from '@playwright/test'
export class SomePage {
readonly page: Page
readonly someElement: Locator
constructor(page: Page) {
this.page = page
this.someElement = page.locator('[data-testid="some-element"]')
}
async goto() {
await this.page.goto('/some-path')
await this.page.waitForLoadState('networkidle')
}
async performAction() {
// 封装复杂交互
}
}
规则:
hack/tests/pages/。apps/lina-plugins/<plugin-id>/hack/tests/pages/。hack/tests/pages/ 中;只有多个宿主测试或多个插件确实复用的通用能力,才提升到宿主共享 POM。data-testid 属性作为定位策略。共享的测试设置(认证、配置)放在 fixtures/ 目录中:
auth.ts — 扩展 Playwright test,提供已认证的页面固件(adminPage 等)config.ts — 环境相关配置(URL、凭据、超时时间)k8s.ts — Kubernetes 辅助工具(Pod 就绪检查、执行命令)使用固件而非直接导入 @playwright/test:
// 宿主测试
import { test, expect } from '../../fixtures/auth'
// 源码插件测试
import { test, expect } from '../../../../../../hack/tests/fixtures/auth'
// 错误
import { test, expect } from '@playwright/test'
在 OpenSpec 变更中编写 tasks.md 时,E2E 测试任务必须引用 TC ID:
### 任务 3:E2E — TC006 笔记本自动保存
- [ ] 创建 `hack/tests/e2e/notebook/TC006-notebook-auto-save.ts`
- [ ] 实现 TC-6a:空闲超时后文件自动保存
- [ ] 实现 TC-6b:UI 中显示保存指示器
- [ ] 实现 TC-6c:页面重新加载后内容持久化
源码插件示例:
### 任务 3:E2E — TC003 插件页面入口
- [ ] 创建 `apps/lina-plugins/example-plugin/hack/tests/e2e/TC003-example-plugin-entry.ts`
- [ ] 实现 TC-3a:插件公开接口可读取
- [ ] 实现 TC-3b:插件插槽内容可见
- [ ] 实现 TC-3c:插件管理页可访问
任务标题中的 TC ID 必须与文件名匹配。子断言(TC-6a、TC-6b)应列为子项。
当执行 E2E 测试的代理支持多模态图片识别时,必须在关键交互步骤后捕获浏览器截图并审查截图内容。截图可以发现文本断言无法捕获的问题,包括 i18n key 未翻译、布局错乱、接口报错 toast 等。
截图规范和审查要求的完整定义在 .agents/rules/testing.md 的"E2E 截图验证要求"章节。本节仅列出 Playwright 截图调用约定:
// 在关键交互后捕获截图
await adminPage.screenshot({
path: `temp/${new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)}-${description}.png`,
fullPage: false, // 只捕获视口,避免过大的截图
});
截图文件命名格式:{YYYYMMDD}-{HHmmss}-{描述}.png,放置在项目根目录 temp/ 下。
| 项目 | 规范 |
|---|---|
| 文件名 | TC{NNN}-{brief-name}.ts |
| TC ID 范围 | 当前模块目录内唯一并连续递增 |
| 宿主测试目录 | hack/tests/e2e/{module}/ |
| 源码插件测试目录 | apps/lina-plugins/<plugin-id>/hack/tests/e2e/ |
| Describe 标签 | TC-{N} {描述} |
| 子测试标签 | TC-{N}{字母}: {描述} |
| 宿主导入 test/expect | 从相对路径 ../../fixtures/auth 导入 |
| 插件导入 test/expect | 从相对路径 ../../../../../../hack/tests/fixtures/auth 导入 |
| 页面交互 | 通过宿主 pages/ 或插件 hack/tests/pages/ 中的 POM 类 |
| 独立性 | 每个文件可独立运行 |
| ID 分配 | 扫描当前模块目录已用最大值 → 递增 1 |
| 截图验证 | 多模态可用时,关键交互后截图并审查;详见 .agents/rules/testing.md |
| 质量审查 | 详见 .agents/rules/testing.md 的 E2E 质量审查要求 |