340 lines
10 KiB
TypeScript
340 lines
10 KiB
TypeScript
/**
|
||
* Python Core 测试页面
|
||
* 用于测试增强版Python Core的各项功能
|
||
*/
|
||
|
||
import React, { useState } from 'react'
|
||
import { invoke } from '@tauri-apps/api/tauri'
|
||
import { Play, CheckCircle, XCircle, Loader, RefreshCw } from 'lucide-react'
|
||
|
||
interface PythonResponse {
|
||
status: boolean
|
||
msg: string
|
||
data?: any
|
||
}
|
||
|
||
interface TestResult {
|
||
name: string
|
||
status: 'pending' | 'running' | 'success' | 'error'
|
||
response?: PythonResponse
|
||
error?: string
|
||
duration?: number
|
||
}
|
||
|
||
const PythonCoreTestPage: React.FC = () => {
|
||
const [testResults, setTestResults] = useState<TestResult[]>([])
|
||
const [isRunning, setIsRunning] = useState(false)
|
||
|
||
const tests = [
|
||
{
|
||
name: '基础功能测试',
|
||
command: 'test_python_core_basic',
|
||
description: '测试Python Core的基本功能和响应格式'
|
||
},
|
||
{
|
||
name: '模板管理测试',
|
||
command: 'test_template_manager',
|
||
description: '测试模板管理服务的功能'
|
||
},
|
||
{
|
||
name: '项目管理测试',
|
||
command: 'test_project_manager',
|
||
description: '测试项目管理服务的功能'
|
||
},
|
||
{
|
||
name: '文件管理测试',
|
||
command: 'test_file_manager',
|
||
description: '测试文件管理服务的功能',
|
||
params: { path: '.' }
|
||
},
|
||
{
|
||
name: 'AI视频测试',
|
||
command: 'test_ai_video',
|
||
description: '测试AI视频生成环境和功能'
|
||
},
|
||
{
|
||
name: '资源分类测试',
|
||
command: 'test_get_categories',
|
||
description: '测试资源分类管理功能'
|
||
},
|
||
{
|
||
name: '批量导入测试',
|
||
command: 'test_batch_import_templates',
|
||
description: '测试模板批量导入功能',
|
||
params: { folder_path: './templates' }
|
||
},
|
||
{
|
||
name: '创建项目测试',
|
||
command: 'test_create_project',
|
||
description: '测试项目创建功能',
|
||
params: { name: 'Test Project', description: 'A test project' }
|
||
}
|
||
]
|
||
|
||
const runSingleTest = async (test: any, index: number) => {
|
||
const startTime = Date.now()
|
||
|
||
// 更新状态为运行中
|
||
setTestResults(prev => {
|
||
const newResults = [...prev]
|
||
newResults[index] = {
|
||
name: test.name,
|
||
status: 'running'
|
||
}
|
||
return newResults
|
||
})
|
||
|
||
try {
|
||
let response: PythonResponse
|
||
|
||
if (test.params) {
|
||
response = await invoke(test.command, test.params)
|
||
} else {
|
||
response = await invoke(test.command)
|
||
}
|
||
|
||
const duration = Date.now() - startTime
|
||
|
||
// 更新状态为成功
|
||
setTestResults(prev => {
|
||
const newResults = [...prev]
|
||
newResults[index] = {
|
||
name: test.name,
|
||
status: 'success',
|
||
response,
|
||
duration
|
||
}
|
||
return newResults
|
||
})
|
||
|
||
} catch (error) {
|
||
const duration = Date.now() - startTime
|
||
|
||
// 更新状态为错误
|
||
setTestResults(prev => {
|
||
const newResults = [...prev]
|
||
newResults[index] = {
|
||
name: test.name,
|
||
status: 'error',
|
||
error: error as string,
|
||
duration
|
||
}
|
||
return newResults
|
||
})
|
||
}
|
||
}
|
||
|
||
const runAllTests = async () => {
|
||
setIsRunning(true)
|
||
|
||
// 初始化所有测试状态
|
||
setTestResults(tests.map(test => ({
|
||
name: test.name,
|
||
status: 'pending' as const
|
||
})))
|
||
|
||
// 逐个运行测试
|
||
for (let i = 0; i < tests.length; i++) {
|
||
await runSingleTest(tests[i], i)
|
||
// 在测试之间添加短暂延迟
|
||
await new Promise(resolve => setTimeout(resolve, 500))
|
||
}
|
||
|
||
setIsRunning(false)
|
||
}
|
||
|
||
const runComprehensiveTest = async () => {
|
||
setIsRunning(true)
|
||
|
||
try {
|
||
const startTime = Date.now()
|
||
const results: PythonResponse[] = await invoke('test_all_python_core_functions')
|
||
const duration = Date.now() - startTime
|
||
|
||
// 将综合测试结果映射到各个测试
|
||
const mappedResults = tests.map((test, index) => ({
|
||
name: test.name,
|
||
status: results[index]?.status ? 'success' : 'error' as const,
|
||
response: results[index],
|
||
duration: duration / tests.length // 平均分配时间
|
||
}))
|
||
|
||
setTestResults(mappedResults)
|
||
} catch (error) {
|
||
console.error('Comprehensive test failed:', error)
|
||
setTestResults(tests.map(test => ({
|
||
name: test.name,
|
||
status: 'error' as const,
|
||
error: error as string
|
||
})))
|
||
}
|
||
|
||
setIsRunning(false)
|
||
}
|
||
|
||
const clearResults = () => {
|
||
setTestResults([])
|
||
}
|
||
|
||
const getStatusIcon = (status: TestResult['status']) => {
|
||
switch (status) {
|
||
case 'pending':
|
||
return <div className="w-5 h-5 rounded-full bg-gray-300" />
|
||
case 'running':
|
||
return <Loader className="w-5 h-5 text-blue-500 animate-spin" />
|
||
case 'success':
|
||
return <CheckCircle className="w-5 h-5 text-green-500" />
|
||
case 'error':
|
||
return <XCircle className="w-5 h-5 text-red-500" />
|
||
}
|
||
}
|
||
|
||
const getStatusColor = (status: TestResult['status']) => {
|
||
switch (status) {
|
||
case 'pending':
|
||
return 'border-gray-200 bg-gray-50'
|
||
case 'running':
|
||
return 'border-blue-200 bg-blue-50'
|
||
case 'success':
|
||
return 'border-green-200 bg-green-50'
|
||
case 'error':
|
||
return 'border-red-200 bg-red-50'
|
||
}
|
||
}
|
||
|
||
const successCount = testResults.filter(r => r.status === 'success').length
|
||
const errorCount = testResults.filter(r => r.status === 'error').length
|
||
const totalTests = testResults.length
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gray-50 p-6">
|
||
<div className="max-w-6xl mx-auto">
|
||
{/* 页面标题 */}
|
||
<div className="mb-8">
|
||
<h1 className="text-3xl font-bold text-gray-900 mb-2">
|
||
Python Core 功能测试
|
||
</h1>
|
||
<p className="text-gray-600">
|
||
测试增强版Python Core的各项功能,验证sidecar和模拟服务是否正常工作
|
||
</p>
|
||
</div>
|
||
|
||
{/* 控制按钮 */}
|
||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
|
||
<div className="flex items-center gap-4 mb-4">
|
||
<button
|
||
onClick={runAllTests}
|
||
disabled={isRunning}
|
||
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||
>
|
||
<Play size={16} />
|
||
逐个运行测试
|
||
</button>
|
||
|
||
<button
|
||
onClick={runComprehensiveTest}
|
||
disabled={isRunning}
|
||
className="flex items-center gap-2 px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||
>
|
||
<RefreshCw size={16} />
|
||
综合测试
|
||
</button>
|
||
|
||
<button
|
||
onClick={clearResults}
|
||
disabled={isRunning}
|
||
className="flex items-center gap-2 px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||
>
|
||
清除结果
|
||
</button>
|
||
</div>
|
||
|
||
{/* 测试统计 */}
|
||
{totalTests > 0 && (
|
||
<div className="flex items-center gap-6 text-sm">
|
||
<span className="text-gray-600">
|
||
总计: {totalTests}
|
||
</span>
|
||
<span className="text-green-600">
|
||
成功: {successCount}
|
||
</span>
|
||
<span className="text-red-600">
|
||
失败: {errorCount}
|
||
</span>
|
||
<span className="text-gray-600">
|
||
成功率: {totalTests > 0 ? Math.round((successCount / totalTests) * 100) : 0}%
|
||
</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* 测试结果 */}
|
||
<div className="space-y-4">
|
||
{tests.map((test, index) => {
|
||
const result = testResults[index]
|
||
|
||
return (
|
||
<div
|
||
key={test.name}
|
||
className={`bg-white rounded-lg shadow-sm border-2 p-6 ${
|
||
result ? getStatusColor(result.status) : 'border-gray-200'
|
||
}`}
|
||
>
|
||
<div className="flex items-start justify-between mb-4">
|
||
<div className="flex items-center gap-3">
|
||
{result ? getStatusIcon(result.status) : getStatusIcon('pending')}
|
||
<div>
|
||
<h3 className="font-semibold text-gray-900">{test.name}</h3>
|
||
<p className="text-sm text-gray-600">{test.description}</p>
|
||
</div>
|
||
</div>
|
||
|
||
{result?.duration && (
|
||
<span className="text-xs text-gray-500">
|
||
{result.duration}ms
|
||
</span>
|
||
)}
|
||
</div>
|
||
|
||
{/* 测试结果详情 */}
|
||
{result && (
|
||
<div className="mt-4">
|
||
{result.status === 'success' && result.response && (
|
||
<div className="bg-green-50 border border-green-200 rounded-lg p-4">
|
||
<div className="text-sm text-green-800 mb-2">
|
||
<strong>状态:</strong> {result.response.status ? '成功' : '失败'}
|
||
</div>
|
||
<div className="text-sm text-green-800 mb-2">
|
||
<strong>消息:</strong> {result.response.msg}
|
||
</div>
|
||
{result.response.data && (
|
||
<details className="text-sm text-green-800">
|
||
<summary className="cursor-pointer font-medium">查看数据</summary>
|
||
<pre className="mt-2 p-2 bg-green-100 rounded text-xs overflow-auto">
|
||
{JSON.stringify(result.response.data, null, 2)}
|
||
</pre>
|
||
</details>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
{result.status === 'error' && (
|
||
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
|
||
<div className="text-sm text-red-800">
|
||
<strong>错误:</strong> {result.error}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
)
|
||
})}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default PythonCoreTestPage
|