fix(api): finalize frontend contract integration

This commit is contained in:
2026-07-22 15:25:22 +08:00
parent 217f82c57c
commit 17dd9de401
5 changed files with 59 additions and 8 deletions

View File

@@ -17,10 +17,63 @@ await server.listen()
const browser = await chromium.launch({ headless: true })
const page = await browser.newPage({ viewport: { width: 1440, height: 1024 }, deviceScaleFactor: 1 })
const errors = []
const projectId = '019b0000-0000-7000-8000-000000000001'
page.on('console', (message) => {
if (message.type() === 'error') errors.push(message.text())
})
const visualCheckWorkspace = {
project: {
id: projectId,
name: '森林项目',
identifier: 'forest',
icon: '森',
background: '#165DFF',
description: '前后端 API 对齐视觉检查项目',
initials: '森林',
unreadCount: 2,
},
channels: [
{ id: 'overview', projectId, type: 'overview', title: '概况', icon: 'home', count: 0, url: '', sortOrder: 0 },
{ id: 'tasks', projectId, type: 'tasks', title: '工作计划', icon: 'list', count: 0, url: '', sortOrder: 1 },
{ id: 'ai', projectId, type: 'ai_sessions', title: 'AI 助手', icon: 'robot', count: 0, url: '', sortOrder: 2 },
{ id: 'notes', projectId, type: 'notes_sources', title: '笔记资料', icon: 'file', count: 0, url: '', sortOrder: 3 },
{ id: 'cron', projectId, type: 'cron', title: '计划任务', icon: 'clock', count: 0, url: '', sortOrder: 4 },
],
tags: [{ id: '019b0000-0000-7000-8000-000000000002', name: '产品' }],
recentSessions: [],
inbox: [],
tasks: [],
aiSessions: [],
notesSources: [],
cronPlans: [],
}
await page.route('http://localhost:9150/api/v1/**', async (route) => {
const url = new URL(route.request().url())
if (url.pathname === '/api/v1/status') {
await route.fulfill({ json: { timestamp: new Date().toISOString() } })
return
}
if (url.pathname === '/api/v1/auth/login') {
await route.fulfill({ json: { token: 'visual-check-token' } })
return
}
if (url.pathname === '/api/v1/projects') {
await route.fulfill({ json: [visualCheckWorkspace.project] })
return
}
if (url.pathname === `/api/v1/projects/${projectId}/workspace`) {
await route.fulfill({ json: visualCheckWorkspace })
return
}
if (url.pathname === `/api/v1/projects/${projectId}/ai-sessions`) {
await route.fulfill({ json: [] })
return
}
await route.fulfill({ status: 404, json: { error: { code: 'not_found', message: '视觉检查未配置该接口' } } })
})
const collectMetrics = async () => page.evaluate(() => {
const statusbar = document.querySelector('.statusbar')
const statusName = document.querySelector('.status-name')
@@ -131,7 +184,7 @@ const channelListHoverMetrics = await collectMetrics()
const channelPageChecks = []
for (const channel of [
{ label: '工作计划', pageClass: 'project-tasks-page', expectedHeading: '工作计划' },
{ label: 'AI智能体', pageClass: 'project-ai-page', expectedHeading: 'AI智能体' },
{ label: 'AI 助手', pageClass: 'project-ai-page', expectedHeading: 'AI 助手' },
{ label: '笔记资料', pageClass: 'project-notes-page', expectedHeading: '笔记资料' },
{ label: '计划任务', pageClass: 'project-cron-page', expectedHeading: '计划任务' },
{ label: '新建频道', pageClass: 'project-new-channel-page', expectedHeading: '新建频道' },
@@ -172,10 +225,7 @@ const failures = []
const metrics = workspaceMetrics
if (errors.length) failures.push(`console errors: ${errors.join('; ')}`)
if (metrics.statusbarHeight !== 32) failures.push(`expected statusbar height 32, got ${metrics.statusbarHeight}`)
if (!metrics.statusOnlineDot) failures.push('expected online status to render as an icon dot')
if (metrics.statusName && metrics.statusOnlineDot && Math.abs(metrics.statusName.top - metrics.statusOnlineDot.top) > 6) {
failures.push(`expected online dot to sit beside username, got name=${JSON.stringify(metrics.statusName)}, dot=${JSON.stringify(metrics.statusOnlineDot)}`)
}
if (!metrics.statusName) failures.push('expected authenticated status label')
if (metrics.searchHeight !== 42) failures.push(`expected search height 42, got ${metrics.searchHeight}`)
if (metrics.overflowX) failures.push('expected no horizontal overflow')
if (!metrics.workbenchMain) failures.push('missing workbench main')