chore: add remaining test docs, scripts and temp files

- Add Git commit preparation checklist
- Add Phase testing guides and issue tracking
- Add utility scripts (env setup, test data initialization)
- Add temp migration SQL files (for reference)
- Update startup scripts and README
- Remove obsolete scripts
This commit is contained in:
2025-11-16 15:44:55 +08:00
parent 1992232fda
commit 855d142fec
32 changed files with 9125 additions and 113 deletions

409
backend/test-review-api.js Normal file
View File

@@ -0,0 +1,409 @@
/**
* 稿件审查API测试脚本
* 测试5个API端点的功能
*/
import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const API_BASE_URL = 'http://localhost:3001/api/v1';
const TEST_FILE_PATH = path.join(__dirname, '../docs/稿约规范性评估标准.txt'); // 使用现有文本文件作为测试
// 颜色输出
const colors = {
reset: '\x1b[0m',
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m',
};
function log(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
function separator() {
console.log('\n' + '='.repeat(80) + '\n');
}
// 延迟函数
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// ==================== 测试函数 ====================
/**
* 测试1: 上传稿件
*/
async function testUploadManuscript() {
log('📤 测试1: 上传稿件 (POST /review/upload)', 'cyan');
try {
// 检查测试文件是否存在
if (!fs.existsSync(TEST_FILE_PATH)) {
log(`❌ 测试文件不存在: ${TEST_FILE_PATH}`, 'red');
log('💡 提示请准备一个Word文档.doc或.docx作为测试文件', 'yellow');
return null;
}
const formData = new FormData();
formData.append('file', fs.createReadStream(TEST_FILE_PATH));
formData.append('modelType', 'deepseek-v3');
log(`📄 测试文件: ${path.basename(TEST_FILE_PATH)}`, 'blue');
log(`🤖 使用模型: deepseek-v3`, 'blue');
const response = await axios.post(
`${API_BASE_URL}/review/upload`,
formData,
{
headers: formData.getHeaders(),
timeout: 30000,
}
);
if (response.data.success) {
log('✅ 上传成功!', 'green');
console.log('返回数据:', JSON.stringify(response.data, null, 2));
return response.data.data.taskId;
} else {
log('❌ 上传失败', 'red');
console.log('错误信息:', response.data.message);
return null;
}
} catch (error) {
log('❌ 请求失败', 'red');
if (error.response) {
console.log('状态码:', error.response.status);
console.log('错误信息:', error.response.data);
} else {
console.log('错误:', error.message);
}
return null;
}
}
/**
* 测试2: 查询任务状态
*/
async function testGetTaskStatus(taskId) {
log('🔍 测试2: 查询任务状态 (GET /review/tasks/:taskId)', 'cyan');
try {
log(`📋 任务ID: ${taskId}`, 'blue');
const response = await axios.get(`${API_BASE_URL}/review/tasks/${taskId}`, {
timeout: 10000,
});
if (response.data.success) {
log('✅ 查询成功!', 'green');
console.log('任务状态:', JSON.stringify(response.data.data, null, 2));
return response.data.data;
} else {
log('❌ 查询失败', 'red');
console.log('错误信息:', response.data.message);
return null;
}
} catch (error) {
log('❌ 请求失败', 'red');
if (error.response) {
console.log('状态码:', error.response.status);
console.log('错误信息:', error.response.data);
} else {
console.log('错误:', error.message);
}
return null;
}
}
/**
* 测试3: 轮询任务直到完成
*/
async function pollTaskUntilComplete(taskId, maxAttempts = 60) {
log('⏳ 测试3: 轮询任务状态直到完成', 'cyan');
for (let i = 0; i < maxAttempts; i++) {
const task = await testGetTaskStatus(taskId);
if (!task) {
log('❌ 查询任务失败,停止轮询', 'red');
return null;
}
log(`📊 当前状态: ${task.status}`, 'yellow');
if (task.status === 'completed') {
log('✅ 任务已完成!', 'green');
return task;
}
if (task.status === 'failed') {
log('❌ 任务失败', 'red');
console.log('错误信息:', task.errorMessage);
return null;
}
log(`⏱️ 等待5秒后重试... (${i + 1}/${maxAttempts})`, 'blue');
await delay(5000);
}
log('⚠️ 超过最大等待时间,任务仍未完成', 'yellow');
return null;
}
/**
* 测试4: 获取审查报告
*/
async function testGetReport(taskId) {
log('📊 测试4: 获取审查报告 (GET /review/tasks/:taskId/report)', 'cyan');
try {
log(`📋 任务ID: ${taskId}`, 'blue');
const response = await axios.get(`${API_BASE_URL}/review/tasks/${taskId}/report`, {
timeout: 10000,
});
if (response.data.success) {
log('✅ 获取报告成功!', 'green');
console.log('\n📄 完整报告:');
console.log(JSON.stringify(response.data.data, null, 2));
// 显示关键指标
const report = response.data.data;
separator();
log('📈 评估结果摘要:', 'cyan');
log(`总分: ${report.overallScore?.toFixed(1) || 'N/A'}`, 'green');
log(`稿约规范性评分: ${report.editorialReview?.overall_score || 'N/A'}`, 'blue');
log(`方法学评分: ${report.methodologyReview?.overall_score || 'N/A'}`, 'blue');
log(`字数: ${report.wordCount || 'N/A'}`, 'blue');
log(`耗时: ${report.durationSeconds || 'N/A'}`, 'blue');
separator();
return response.data.data;
} else {
log('❌ 获取报告失败', 'red');
console.log('错误信息:', response.data.message);
return null;
}
} catch (error) {
log('❌ 请求失败', 'red');
if (error.response) {
console.log('状态码:', error.response.status);
console.log('错误信息:', error.response.data);
} else {
console.log('错误:', error.message);
}
return null;
}
}
/**
* 测试5: 获取任务列表
*/
async function testGetTaskList() {
log('📋 测试5: 获取任务列表 (GET /review/tasks)', 'cyan');
try {
const response = await axios.get(`${API_BASE_URL}/review/tasks`, {
params: { page: 1, limit: 10 },
timeout: 10000,
});
if (response.data.success) {
log('✅ 获取列表成功!', 'green');
console.log(`找到 ${response.data.data.length} 个任务`);
console.log('任务列表:', JSON.stringify(response.data.data, null, 2));
console.log('分页信息:', JSON.stringify(response.data.pagination, null, 2));
return response.data.data;
} else {
log('❌ 获取列表失败', 'red');
console.log('错误信息:', response.data.message);
return null;
}
} catch (error) {
log('❌ 请求失败', 'red');
if (error.response) {
console.log('状态码:', error.response.status);
console.log('错误信息:', error.response.data);
} else {
console.log('错误:', error.message);
}
return null;
}
}
/**
* 测试6: 删除任务(可选)
*/
async function testDeleteTask(taskId) {
log('🗑️ 测试6: 删除任务 (DELETE /review/tasks/:taskId)', 'cyan');
try {
log(`📋 任务ID: ${taskId}`, 'blue');
const response = await axios.delete(`${API_BASE_URL}/review/tasks/${taskId}`, {
timeout: 10000,
});
if (response.data.success) {
log('✅ 删除成功!', 'green');
console.log('返回数据:', JSON.stringify(response.data, null, 2));
return true;
} else {
log('❌ 删除失败', 'red');
console.log('错误信息:', response.data.message);
return false;
}
} catch (error) {
log('❌ 请求失败', 'red');
if (error.response) {
console.log('状态码:', error.response.status);
console.log('错误信息:', error.response.data);
} else {
console.log('错误:', error.message);
}
return false;
}
}
// ==================== 主测试流程 ====================
async function runAllTests() {
log('🚀 开始稿件审查API测试', 'green');
separator();
// 测试1: 上传稿件
const taskId = await testUploadManuscript();
if (!taskId) {
log('❌ 上传失败,终止测试', 'red');
return;
}
separator();
// 等待2秒
await delay(2000);
// 测试2: 查询任务状态
await testGetTaskStatus(taskId);
separator();
// 测试3: 轮询直到完成
const completedTask = await pollTaskUntilComplete(taskId);
if (!completedTask) {
log('❌ 任务未能完成,跳过报告测试', 'red');
separator();
// 但仍然测试任务列表
await testGetTaskList();
separator();
return;
}
separator();
// 测试4: 获取报告
await testGetReport(taskId);
separator();
// 测试5: 获取任务列表
await testGetTaskList();
separator();
// 测试6: 删除任务(可选,取消注释以启用)
// log('⚠️ 是否删除测试任务取消注释testDeleteTask以启用', 'yellow');
// await testDeleteTask(taskId);
// separator();
log('✅ 所有测试完成!', 'green');
}
// ==================== 健康检查 ====================
async function checkHealth() {
log('🔍 检查后端服务健康状态...', 'cyan');
try {
const response = await axios.get('http://localhost:3001/health', {
timeout: 5000,
});
log('✅ 后端服务正常', 'green');
console.log('健康状态:', response.data);
return true;
} catch (error) {
log('❌ 后端服务不可用', 'red');
console.log('错误:', error.message);
log('💡 请先启动后端服务: npm run dev 或 启动后端.bat', 'yellow');
return false;
}
}
// ==================== 入口 ====================
async function main() {
console.log('\n');
log('═══════════════════════════════════════════════════════════════════════════════', 'cyan');
log(' 稿件审查API自动化测试脚本 ', 'cyan');
log('═══════════════════════════════════════════════════════════════════════════════', 'cyan');
console.log('\n');
// 健康检查
const healthy = await checkHealth();
if (!healthy) {
process.exit(1);
}
separator();
// 运行所有测试
await runAllTests();
console.log('\n');
log('═══════════════════════════════════════════════════════════════════════════════', 'cyan');
log(' 测试完成 ', 'cyan');
log('═══════════════════════════════════════════════════════════════════════════════', 'cyan');
console.log('\n');
}
main().catch(error => {
console.error('测试脚本执行失败:', error);
process.exit(1);
});