Files
mxivideo/src/pages/PythonCoreTestPage.tsx
2025-07-11 15:00:12 +08:00

340 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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