001project_wildgrowth/backend/scripts/test-course-generation-flow.ts

383 lines
11 KiB
TypeScript
Raw Normal View History

2026-02-11 15:26:03 +08:00
/**
*
* 使ts-node backend/scripts/test-course-generation-flow.ts
*/
import axios from 'axios';
import * as dotenv from 'dotenv';
import path from 'path';
// 加载环境变量
dotenv.config({ path: path.join(__dirname, '../.env.test') });
const BASE_URL = process.env.API_BASE_URL || 'http://localhost:3000';
const TEST_USER_EMAIL = process.env.TEST_USER_EMAIL || 'test@example.com';
const TEST_USER_PASSWORD = process.env.TEST_USER_PASSWORD || 'test123456';
interface CreateCourseResponse {
success: boolean;
data: {
courseId: string;
taskId: string;
status: string;
generationStyle?: string;
message?: string;
};
}
interface CourseStatusResponse {
success: boolean;
data: {
courses: Array<{
id: string;
title: string;
generation_status: string | null;
generation_progress: number | null;
status: string;
progress: number;
error_message?: string | null;
}>;
};
}
interface TaskResponse {
success: boolean;
data: {
task: {
id: string;
status: string;
generationStyle: string | null;
outline: any;
suggestedTitle: string | null;
errorMessage: string | null;
};
};
}
interface PromptLogResponse {
success: boolean;
data: {
logs: Array<{
id: string;
promptType: string;
taskId: string | null;
status: string;
duration: number | null;
tokensUsed: number | null;
errorMessage: string | null;
createdAt: string;
}>;
total: number;
};
}
// 测试内容
const TEST_CONTENT = `
#
##
### 1.1
-
-
-
### 1.2
-
-
-
##
### 2.1
-
-
-
### 2.2
-
-
-
##
### 3.1
-
-
-
### 3.2
-
-
-
`;
async function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
interface LoginResponse {
success: boolean;
data: {
token: string;
user: any;
};
}
async function login(): Promise<string> {
console.log('🔐 登录获取 Token...');
// 先尝试注册(如果用户不存在)
try {
console.log('📝 尝试注册测试用户...');
await axios.post(`${BASE_URL}/api/auth/register`, {
email: TEST_USER_EMAIL,
password: TEST_USER_PASSWORD,
username: '测试用户',
});
console.log('✅ 注册成功');
} catch (regError: any) {
if (regError.response?.status === 400 && regError.response?.data?.message?.includes('已存在')) {
console.log(' 用户已存在,直接登录');
} else {
console.log(`⚠️ 注册失败(可能用户已存在): ${regError.response?.data?.message || regError.message}`);
}
}
// 登录
try {
const response = await axios.post<LoginResponse>(`${BASE_URL}/api/auth/login`, {
email: TEST_USER_EMAIL,
password: TEST_USER_PASSWORD,
});
if (response.data.success && response.data.data.token) {
console.log('✅ 登录成功');
return response.data.data.token;
} else {
throw new Error('登录失败:未返回 Token');
}
} catch (error: any) {
const errorMsg = error.response?.data?.message || error.message;
throw new Error(`登录失败: ${errorMsg}`);
}
}
async function createCourse(token: string, style: 'full' | 'essence' | 'one-page' = 'essence'): Promise<CreateCourseResponse['data']> {
console.log(`\n📝 创建课程(风格: ${style}...`);
const response = await axios.post<CreateCourseResponse>(
`${BASE_URL}/api/ai/content/upload`,
{
content: TEST_CONTENT,
style: style,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
if (!response.data.success) {
throw new Error('创建课程失败');
}
console.log(`✅ 课程创建成功:`);
console.log(` - Course ID: ${response.data.data.courseId}`);
console.log(` - Task ID: ${response.data.data.taskId}`);
console.log(` - 状态: ${response.data.data.status}`);
return response.data.data;
}
async function checkCourseStatus(token: string, courseId: string, maxWait: number = 300000): Promise<void> {
console.log(`\n⏳ 等待课程生成完成(最多 ${maxWait / 1000} 秒)...`);
const startTime = Date.now();
let lastProgress = -1;
while (Date.now() - startTime < maxWait) {
try {
const response = await axios.get<CourseStatusResponse>(
`${BASE_URL}/api/my-courses`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const course = response.data.data.courses.find(c => c.id === courseId);
if (!course) {
console.log('⚠️ 课程未找到,继续等待...');
await sleep(3000);
continue;
}
const progress = course.generation_progress ? Math.round(course.generation_progress * 100) : 0;
if (progress !== lastProgress) {
console.log(`📊 生成进度: ${progress}% (状态: ${course.generation_status || course.status})`);
lastProgress = progress;
}
if (course.generation_status === 'completed' || course.status === 'completed') {
console.log(`\n✅ 课程生成完成!`);
console.log(` - 标题: ${course.title}`);
console.log(` - 最终状态: ${course.status}`);
return;
}
if (course.generation_status === 'failed' || course.status === 'failed') {
console.log(`\n❌ 课程生成失败!`);
console.log(` - 错误信息: ${course.error_message || '未知错误'}`);
throw new Error(`生成失败: ${course.error_message || '未知错误'}`);
}
await sleep(3000);
} catch (error: any) {
if (error.response?.status === 401) {
throw new Error('Token 已过期,请重新登录');
}
console.log(`⚠️ 查询状态失败: ${error.message},继续重试...`);
await sleep(3000);
}
}
throw new Error('生成超时');
}
async function checkTaskStatus(token: string, taskId: string): Promise<void> {
console.log(`\n📋 查询任务详情 (Task ID: ${taskId})...`);
try {
const response = await axios.get<TaskResponse>(
`${BASE_URL}/api/ai/content/tasks/${taskId}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const task = response.data.data.task;
console.log(`✅ 任务状态:`);
console.log(` - 状态: ${task.status}`);
console.log(` - 风格: ${task.generationStyle || '未设置'}`);
console.log(` - 标题: ${task.suggestedTitle || '未生成'}`);
console.log(` - 大纲: ${task.outline ? '已生成' : '未生成'}`);
if (task.errorMessage) {
console.log(` - 错误: ${task.errorMessage}`);
}
} catch (error: any) {
console.log(`⚠️ 查询任务失败: ${error.message}`);
}
}
async function checkPromptLogs(token: string, taskId: string): Promise<void> {
console.log(`\n📝 查询 AI 调用日志 (Task ID: ${taskId})...`);
try {
const response = await axios.get<PromptLogResponse>(
`${BASE_URL}/api/ai/prompts/logs?taskId=${taskId}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const logs = response.data.data.logs;
console.log(`✅ 找到 ${logs.length} 条日志记录:`);
logs.forEach((log, index) => {
console.log(`\n ${index + 1}. ${log.promptType} (${log.status})`);
console.log(` - 耗时: ${log.duration ? `${log.duration}ms` : 'N/A'}`);
console.log(` - Tokens: ${log.tokensUsed || 'N/A'}`);
console.log(` - 时间: ${new Date(log.createdAt).toLocaleString()}`);
if (log.errorMessage) {
console.log(` - 错误: ${log.errorMessage}`);
}
});
} catch (error: any) {
console.log(`⚠️ 查询日志失败: ${error.message}`);
}
}
async function main() {
console.log('🧪 开始测试课程生成完整流程\n');
console.log(`📍 API 地址: ${BASE_URL}`);
console.log(`👤 测试用户: ${TEST_USER_EMAIL}\n`);
try {
// 1. 登录
const token = await login();
// 2. 创建课程(测试三种风格)
const styles: Array<'full' | 'essence' | 'one-page'> = ['essence', 'full', 'one-page'];
for (const style of styles) {
console.log(`\n${'='.repeat(60)}`);
console.log(`测试风格: ${style}`);
console.log('='.repeat(60));
try {
// 创建课程
const { courseId, taskId } = await createCourse(token, style);
// 查询任务状态
await checkTaskStatus(token, taskId);
// 等待生成完成
await checkCourseStatus(token, courseId);
// 查询日志
await checkPromptLogs(token, taskId);
console.log(`\n✅ 风格 ${style} 测试完成!`);
// 等待一下再进行下一个测试
if (style !== styles[styles.length - 1]) {
console.log('\n⏸ 等待 5 秒后进行下一个测试...');
await sleep(5000);
}
} catch (error: any) {
console.error(`\n❌ 风格 ${style} 测试失败: ${error.message}`);
// 继续测试下一个风格
}
}
console.log(`\n${'='.repeat(60)}`);
console.log('🎉 所有测试完成!');
console.log('='.repeat(60));
} catch (error: any) {
console.error(`\n❌ 测试失败: ${error.message}`);
if (error.stack) {
console.error(error.stack);
}
process.exit(1);
}
}
// 运行测试
main().catch(console.error);