feat: E2E 测试集成真实后端
- Playwright 双 webServer 模式自动启动 Go 后端 + Vite 前端 - 后端使用临时 SQLite 数据库隔离,固定端口 19026 - vite.config.ts proxy target 动态读取环境变量 - 新增 sql.js 依赖用于 SQLite 统计数据 seed - 新增 e2e/fixtures.ts 共享工具模块(API seed + SQLite seed) - 拆分测试文件 5→7(providers/models/stats/navigation/validation) - 删除旧文件 crud.spec.ts/sidebar.spec.ts/stats-cards.spec.ts - E2E 测试尚有部分用例需调试修复
This commit is contained in:
87
frontend/e2e/fixtures.ts
Normal file
87
frontend/e2e/fixtures.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import initSqlite from 'sql.js'
|
||||
|
||||
export const API_BASE = `http://localhost:${process.env.NEX_BACKEND_PORT || '19026'}`
|
||||
|
||||
export interface SeedProviderInput {
|
||||
id: string
|
||||
name: string
|
||||
apiKey: string
|
||||
baseUrl: string
|
||||
protocol: 'openai' | 'anthropic'
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export interface SeedModelInput {
|
||||
providerId: string
|
||||
modelName: string
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export interface SeedStatsInput {
|
||||
providerId: string
|
||||
modelName: string
|
||||
requestCount: number
|
||||
date: string
|
||||
}
|
||||
|
||||
export async function seedProvider(
|
||||
request: import('@playwright/test').APIRequestContext,
|
||||
data: SeedProviderInput,
|
||||
) {
|
||||
const resp = await request.post(`${API_BASE}/api/providers`, {
|
||||
data: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
api_key: data.apiKey,
|
||||
base_url: data.baseUrl,
|
||||
protocol: data.protocol,
|
||||
enabled: data.enabled,
|
||||
},
|
||||
})
|
||||
if (!resp.ok()) {
|
||||
throw new Error(`seedProvider failed: ${resp.status()} ${await resp.text()}`)
|
||||
}
|
||||
return resp.json()
|
||||
}
|
||||
|
||||
export async function seedModel(
|
||||
request: import('@playwright/test').APIRequestContext,
|
||||
data: SeedModelInput,
|
||||
) {
|
||||
const resp = await request.post(`${API_BASE}/api/models`, {
|
||||
data: {
|
||||
provider_id: data.providerId,
|
||||
model_name: data.modelName,
|
||||
enabled: data.enabled,
|
||||
},
|
||||
})
|
||||
if (!resp.ok()) {
|
||||
throw new Error(`seedModel failed: ${resp.status()} ${await resp.text()}`)
|
||||
}
|
||||
return resp.json()
|
||||
}
|
||||
|
||||
export async function seedUsageStats(statsData: SeedStatsInput[]) {
|
||||
const tempDir = process.env.NEX_E2E_TEMP_DIR
|
||||
if (!tempDir) {
|
||||
throw new Error('NEX_E2E_TEMP_DIR not set')
|
||||
}
|
||||
|
||||
const dbPath = path.join(tempDir, 'test.db')
|
||||
const SQL = await initSqlite()
|
||||
const buf = fs.readFileSync(dbPath)
|
||||
const db = new SQL.Database(buf)
|
||||
|
||||
for (const row of statsData) {
|
||||
db.run(
|
||||
'INSERT OR REPLACE INTO usage_stats (provider_id, model_name, request_count, date) VALUES (?, ?, ?, ?)',
|
||||
[row.providerId, row.modelName, row.requestCount, row.date],
|
||||
)
|
||||
}
|
||||
|
||||
const data = db.export()
|
||||
fs.writeFileSync(dbPath, Buffer.from(data))
|
||||
db.close()
|
||||
}
|
||||
Reference in New Issue
Block a user