- 将 playwright.config.ts 的 mkdtemp 替换为固定路径,解决主进程/worker 临时目录不一致问题 - 交换后端 WAL 与迁移执行顺序,确保 sql.js 能读取到完整 schema - 修复 models.spec.ts 断言使用 exact:true 避免统一模型 ID 列干扰 - 移除全部 10 个 test.skip,26 个 E2E 测试全部通过
8.8 KiB
8.8 KiB
ADDED Requirements
Requirement: E2E 测试基础设施
前端 E2E 测试 SHALL 自动启动隔离的 Go 后端实例,提供真实 API 交互能力。
Scenario: 双 webServer 自动启动
- WHEN 执行
bun run test:e2e - THEN Playwright SHALL 按 webServer 数组顺序先启动 Go 后端(端口 19026),再启动 Vite 前端(端口 5173)
- THEN Go 后端 SHALL 使用临时目录中的独立数据库文件和日志目录
- THEN Go 后端启动命令 SHALL 包含
--server-port 19026、--database-path、--log-path、--log-level warn参数 - THEN Go 后端 cwd SHALL 指向
backend/目录 - THEN webServer 等待超时 SHALL 为 60000ms
- THEN 两个 webServer SHALL 设置
reuseExistingServer: false
Scenario: 环境变量传递
- WHEN Playwright 配置加载
- THEN
playwright.config.tsSHALL 设置process.env.NEX_BACKEND_PORT为'19026' - THEN
process.env.NEX_E2E_TEMP_DIRSHALL 设置为临时目录路径 - THEN Vite dev server 子进程 SHALL 自动继承上述环境变量
- THEN E2E 测试文件 SHALL 通过
process.env读取后端端口和临时目录信息
Scenario: Vite proxy 动态化
- WHEN
vite.config.ts配置 proxy target - THEN proxy target SHALL 读取
process.env.NEX_BACKEND_PORT,回退到'9826' - THEN 日常
bun run dev时(无环境变量)proxy target SHALL 为http://localhost:9826 - THEN E2E 测试时 proxy target SHALL 为
http://localhost:19026
Requirement: 临时文件隔离
E2E 测试 SHALL 使用固定临时目录隔离所有文件,确保主进程与 worker 进程使用同一路径,测试结束后自动清理。
Scenario: 临时目录创建
- WHEN Playwright 配置加载
- THEN SHALL 使用固定路径
path.join(os.tmpdir(), 'nex-e2e')作为临时目录 - THEN SHALL 先执行
fs.rmSync(tempDir, { recursive: true, force: true })清理残留 - THEN SHALL 执行
fs.mkdirSync创建log/子目录 - THEN 临时目录 SHALL 包含
test.db(数据库)和log/(日志)子路径
Scenario: 临时目录清理
- WHEN Playwright 所有测试完成
- THEN
globalTeardownSHALL 使用固定路径path.join(os.tmpdir(), 'nex-e2e')定位临时目录 - THEN SHALL 使用
fs.rmSync(dir, { recursive: true, force: true })删除临时目录 - THEN 清理 SHALL 在 webServer 进程关闭之后执行
Requirement: 统计数据 seed
E2E 测试 SHALL 能通过 sql.js 直接操作 SQLite 文件 seed 历史统计数据。
Scenario: SQLite 统计数据插入
- WHEN 统计页面测试需要历史数据
- THEN SHALL 使用 sql.js 打开临时数据库文件
- THEN SHALL 通过
INSERT INTO usage_stats插入指定日期和请求量的统计数据 - THEN SHALL 将修改后的数据库写回文件(
db.export()→fs.writeFileSync) - THEN seed 操作 SHALL 在 API 创建供应商和模型之后串行执行
- THEN seed 完成后 SHALL 关闭 sql.js 数据库连接
Requirement: E2E 共享工具模块
E2E 测试 SHALL 提供共享工具模块(e2e/fixtures.ts)封装常用操作。
Scenario: 共享常量
- WHEN 测试文件需要后端 API 地址
- THEN fixtures SHALL export
API_BASE常量,值为http://localhost:${process.env.NEX_BACKEND_PORT}
Scenario: API seed 工具
- WHEN 测试需要通过 API 准备数据
- THEN fixtures SHALL export
seedProvider(request, data)函数,通过request.post创建供应商 - THEN fixtures SHALL export
seedModel(request, data)函数,通过request.post创建模型
Scenario: SQLite seed 工具
- WHEN 测试需要 seed 统计数据
- THEN fixtures SHALL export
seedUsageStats(statsData)函数,通过 sql.js 插入usage_stats记录
Requirement: 供应商管理 E2E 测试
E2E 测试 SHALL 验证供应商的完整 CRUD 用户流程。
Scenario: 创建供应商并验证
- WHEN 用户通过 UI 填写供应商表单并提交
- THEN 对话框 SHALL 关闭
- THEN 新供应商 SHALL 出现在表格中
- THEN 表格 SHALL 显示正确的 id、name、base_url、协议、enabled 状态
Scenario: 编辑供应商并验证
- WHEN 用户点击编辑按钮、修改名称并提交
- THEN 对话框 SHALL 关闭
- THEN 表格中该供应商的名称 SHALL 更新为新值
Scenario: 删除供应商并验证
- WHEN 用户点击删除按钮并确认
- THEN 确认框 SHALL 消失
- THEN 该供应商 SHALL 从表格中消失
Requirement: 模型管理 E2E 测试
E2E 测试 SHALL 验证模型的完整 CRUD 用户流程,断言 SHALL 精确匹配以避免多列文本干扰。
Scenario: 前置数据准备
- WHEN 模型测试开始前
- THEN SHALL 通过 API seed 一个供应商(不通过 UI)
Scenario: 创建模型并验证
- WHEN 用户展开供应商行、填写模型表单并提交
- THEN 对话框 SHALL 关闭
- THEN 新模型 SHALL 出现在展开行的模型表格中
- THEN 模型表格 SHALL 显示统一模型 ID(
provider_id/model_name格式) - THEN 验证断言 SHALL 使用
{ exact: true }精确匹配模型名称文本,避免匹配到"统一模型 ID"列
Scenario: 编辑模型并验证
- WHEN 用户点击模型编辑按钮、修改并提交
- THEN 对话框 SHALL 关闭
- THEN 模型表格 SHALL 显示更新后的数据
- THEN 验证断言 SHALL 使用
{ exact: true }精确匹配模型名称文本
Scenario: 删除模型并验证
- WHEN 用户点击模型删除按钮并确认
- THEN 该模型 SHALL 从模型表格中消失
- THEN 验证断言 SHALL 使用
{ exact: true }精确匹配模型名称文本
Requirement: 统计页面 E2E 测试
E2E 测试 SHALL 验证统计页面的数据展示和筛选功能。所有测试用例 SHALL NOT 被跳过。
Scenario: 统计数据准备
- WHEN 统计测试开始前
- THEN SHALL 通过 API seed 供应商和模型
- THEN SHALL 通过 sql.js seed 多日历史统计数据(覆盖不同供应商、不同模型、不同日期)
Scenario: 统计概览验证
- WHEN 加载统计页面
- THEN 统计摘要卡片 SHALL 显示正确的总请求量
- THEN 统计摘要卡片 SHALL 显示正确的活跃模型数和活跃供应商数
- THEN 统计表格 SHALL 显示 seed 的数据行
- THEN 页面 SHALL 渲染趋势图表区域(标题包含"请求趋势")
Scenario: 统计筛选验证
- WHEN 页面加载完成
- THEN 页面 SHALL 显示筛选栏(供应商下拉选择和模型名称输入框)
- WHEN 用户选择供应商筛选条件
- THEN 统计表格 SHALL 只显示该供应商的数据
- WHEN 用户输入模型名称筛选条件
- THEN 统计表格 SHALL 只显示匹配模型的数据
Requirement: 导航 E2E 测试
E2E 测试 SHALL 验证页面导航和侧边栏功能。
Scenario: 侧边栏渲染
- WHEN 加载任意页面
- THEN 侧边栏 SHALL 显示应用名称和导航菜单项
Scenario: 页面切换
- WHEN 用户点击侧边栏导航菜单项
- THEN 页面 SHALL 切换到对应路由并显示正确内容
- THEN 当前菜单项 SHALL 高亮
Scenario: URL 持久化
- WHEN 用户在统计页面刷新浏览器
- THEN 页面 SHALL 保持在统计页面
Requirement: 表单验证 E2E 测试
E2E 测试 SHALL 验证表单的校验行为。
Scenario: 供应商表单必填校验
- WHEN 用户打开添加供应商对话框并直接点击保存
- THEN SHALL 显示所有必填字段的验证错误提示
Scenario: URL 格式校验
- WHEN 用户在 base_url 字段输入无效 URL 并提交
- THEN SHALL 显示 URL 格式错误提示
Scenario: 对话框行为
- WHEN 用户打开对话框后点击取消
- THEN 对话框 SHALL 关闭且表单重置
- WHEN 用户再次打开对话框
- THEN 表单字段 SHALL 为空
Requirement: E2E 测试文件组织
E2E 测试 SHALL 按 7 个 spec 文件组织。
Scenario: 文件结构
- WHEN 查看
e2e/目录 - THEN SHALL 包含以下测试文件:
providers.spec.ts、models.spec.ts、stats.spec.ts、navigation.spec.ts、validation.spec.ts - THEN SHALL 包含以下辅助文件:
fixtures.ts、global-setup.ts、global-teardown.ts - THEN SHALL NOT 包含已删除的文件:
stats-cards.spec.ts、sidebar.spec.ts、crud.spec.ts
Requirement: 新增依赖
E2E 测试 SHALL 引入 sql.js 作为 devDependency。
Scenario: sql.js 依赖
- WHEN 安装前端依赖
- THEN
package.json的 devDependencies SHALL 包含sql.js - THEN
package.json的 devDependencies SHALL 包含@types/sql.js - THEN sql.js SHALL 仅在 E2E 测试的 seed 逻辑中使用,不影响生产代码