001project_wildgrowth/backend/scripts/test-created-by-visibility.ts

421 lines
13 KiB
TypeScript
Raw Normal View History

2026-02-11 15:26:03 +08:00
/**
* createdBy visibility
*
* 1. AI生成- createdBy visibility='private'
* 2. -
* 3. -
* 4. - 403
* 5. -
* 6. - 403
*/
import axios from 'axios';
import * as dotenv from 'dotenv';
import { join } from 'path';
// 加载环境变量
dotenv.config({ path: join(__dirname, '../.env.test') });
const BASE_URL = process.env.API_BASE_URL || 'http://localhost:3000';
const TEST_EMAIL = process.env.TEST_USER_EMAIL || `test_${Date.now()}@example.com`;
const TEST_PASSWORD = process.env.TEST_USER_PASSWORD || 'Test123456!';
let authToken: string = '';
let userId: string = '';
let createdCourseId: string = '';
let otherUserToken: string = '';
let otherUserId: string = '';
interface LoginResponse {
success: boolean;
data: {
token: string;
user: {
id: string;
email: string;
};
};
}
interface ApiResponse<T = any> {
success: boolean;
data: T;
message?: string;
}
interface CreateCourseResponse {
success: boolean;
data: {
courseId: string;
taskId: string;
status: string;
};
}
interface CourseResponse {
success: boolean;
data: {
course: {
id: string;
title: string;
created_by?: string;
visibility?: string;
status?: string;
};
};
}
interface CourseListResponse {
success: boolean;
data: {
courses: Array<{
id: string;
title: string;
visibility?: string;
}>;
};
}
async function registerUser(email: string, password: string): Promise<void> {
try {
// 尝试注册,如果接口不存在或用户已存在,则跳过
await axios.post(`${BASE_URL}/api/auth/register`, {
email,
password,
username: `测试用户_${Date.now()}`,
});
console.log(`✅ 用户注册成功: ${email}`);
} catch (error: any) {
if (error.response?.status === 404) {
// 注册接口不存在,跳过注册,直接尝试登录
console.log(` 注册接口不存在,跳过注册: ${email}`);
} else if (error.response?.status === 400 && (error.response?.data?.message?.includes('已存在') || error.response?.data?.message?.includes('exists'))) {
console.log(` 用户已存在: ${email}`);
} else {
// 其他错误也忽略,直接尝试登录
console.log(` 注册失败,将尝试登录: ${error.response?.status || error.message}`);
}
}
}
async function login(email: string, password: string): Promise<{ token: string; userId: string }> {
// 尝试使用测试 token
try {
const testTokenResponse = await axios.get<{ success: boolean; data: { token: string; user: { id: string } } }>(`${BASE_URL}/api/auth/test-token`);
if (testTokenResponse.data.success && testTokenResponse.data.data.token) {
console.log(`✅ 使用测试 token 登录成功`);
return {
token: testTokenResponse.data.data.token,
userId: testTokenResponse.data.data.user.id,
};
}
} catch (error) {
console.log(` 测试 token 不可用,尝试其他方式`);
}
// 如果测试 token 不可用,尝试普通登录(需要手机号和验证码)
const response = await axios.post<LoginResponse>(`${BASE_URL}/api/auth/login`, {
email,
password,
});
if (!response.data.success || !response.data.data.token) {
throw new Error('登录失败');
}
return {
token: response.data.data.token,
userId: response.data.data.user.id,
};
}
async function testCreateCourse() {
console.log('\n📝 测试 1: 用户创建课程AI生成');
const content = `# 测试课程
createdBy visibility
##
##
`;
const response = await axios.post<CreateCourseResponse>(
`${BASE_URL}/api/ai/content/upload`,
{
content,
style: 'essence',
},
{
headers: {
Authorization: `Bearer ${authToken}`,
},
}
);
if (response.data.success && response.data.data.courseId) {
createdCourseId = response.data.data.courseId;
console.log(`✅ 课程创建成功courseId: ${createdCourseId}`);
console.log(` taskId: ${response.data.data.taskId}`);
console.log(` status: ${response.data.data.status}`);
// 等待一下,让课程创建完成
await new Promise(resolve => setTimeout(resolve, 2000));
// 查询课程详情,验证 createdBy 和 visibility
const courseResponse = await axios.get<CourseResponse>(
`${BASE_URL}/api/courses/${createdCourseId}`,
{
headers: {
Authorization: `Bearer ${authToken}`,
},
}
);
const course = courseResponse.data.data.course;
console.log(`\n📋 课程信息验证:`);
console.log(` createdBy: ${course.created_by || 'null'} (应该是: ${userId})`);
console.log(` visibility: ${course.visibility || 'N/A'} (应该是: private)`);
console.log(` status: ${course.status || 'N/A'}`);
if (course.created_by === userId && course.visibility === 'private') {
console.log(`✅ createdBy 和 visibility 设置正确`);
} else {
console.log(`❌ createdBy 或 visibility 设置错误`);
}
} else {
throw new Error('创建课程失败');
}
}
async function testQueryCourses() {
console.log('\n📋 测试 2: 查询课程列表');
// 测试公开接口(未登录)
const publicResponse = await axios.get<CourseListResponse>(`${BASE_URL}/api/courses`);
const publicCourses = publicResponse.data.data.courses || [];
console.log(`✅ 公开接口返回 ${publicCourses.length} 个课程`);
console.log(` 所有课程 visibility 应该是 'public': ${publicCourses.every((c: any) => c.visibility === 'public' || !c.visibility)}`);
// 测试登录用户接口
const userResponse = await axios.get<CourseListResponse>(`${BASE_URL}/api/courses`, {
headers: {
Authorization: `Bearer ${authToken}`,
},
});
const userCourses = userResponse.data.data.courses || [];
console.log(`✅ 登录用户接口返回 ${userCourses.length} 个课程`);
// 验证应该包含自己创建的课程
const hasMyCourse = userCourses.some((c: any) => c.id === createdCourseId);
console.log(` 包含自己创建的课程: ${hasMyCourse ? '✅' : '❌'}`);
// 测试 my-courses 接口
const myCoursesResponse = await axios.get<CourseListResponse>(`${BASE_URL}/api/my-courses`, {
headers: {
Authorization: `Bearer ${authToken}`,
},
});
const myCourses = myCoursesResponse.data.data.courses || [];
console.log(`✅ /api/my-courses 返回 ${myCourses.length} 个课程`);
const hasMyCourseInList = myCourses.some((c: any) => c.id === createdCourseId);
console.log(` 包含自己创建的课程: ${hasMyCourseInList ? '✅' : '❌'}`);
}
async function testUpdateOwnCourse() {
console.log('\n✏ 测试 3: 修改自己创建的课程');
try {
const response = await axios.put<CourseResponse>(
`${BASE_URL}/api/courses/${createdCourseId}`,
{
title: '修改后的测试课程标题',
description: '这是修改后的描述',
},
{
headers: {
Authorization: `Bearer ${authToken}`,
},
}
);
if (response.data.success) {
console.log(`✅ 修改自己创建的课程成功`);
console.log(` 新标题: ${response.data.data.course.title}`);
} else {
const errorMsg = (response.data as any).message || '未知错误';
console.log(`❌ 修改失败: ${errorMsg}`);
}
} catch (error: any) {
if (error.response?.status === 403) {
console.log(`❌ 修改失败: 权限不足403`);
} else {
console.log(`❌ 修改失败: ${error.message}`);
}
}
}
async function testUpdateOtherUserCourse() {
console.log('\n✏ 测试 4: 尝试修改他人创建的课程(应该失败)');
// 先创建一个其他用户的课程(如果还没有)
if (!otherUserToken) {
const otherEmail = `other_${Date.now()}@example.com`;
await registerUser(otherEmail, TEST_PASSWORD);
const loginResult = await login(otherEmail, TEST_PASSWORD);
otherUserToken = loginResult.token;
otherUserId = loginResult.userId;
}
// 尝试修改第一个用户创建的课程
try {
await axios.put(
`${BASE_URL}/api/courses/${createdCourseId}`,
{
title: '尝试修改他人课程',
},
{
headers: {
Authorization: `Bearer ${otherUserToken}`,
},
}
);
console.log(`❌ 不应该成功修改他人课程`);
} catch (error: any) {
if (error.response?.status === 403) {
console.log(`✅ 正确拒绝修改他人课程403 Forbidden`);
} else {
console.log(`⚠️ 返回了其他错误: ${error.response?.status} - ${error.message}`);
}
}
}
async function testDeleteOwnCourse() {
console.log('\n🗑 测试 5: 删除自己创建的课程');
// 先创建一个用于删除的课程
const content = `# 待删除的测试课程`;
const createResponse = await axios.post<CreateCourseResponse>(
`${BASE_URL}/api/ai/content/upload`,
{
content,
style: 'essence',
},
{
headers: {
Authorization: `Bearer ${authToken}`,
},
}
);
if (createResponse.data.success) {
const courseIdToDelete = createResponse.data.data.courseId;
console.log(` 创建了用于删除的课程: ${courseIdToDelete}`);
// 等待课程创建完成
await new Promise(resolve => setTimeout(resolve, 2000));
try {
const response = await axios.delete<ApiResponse>(
`${BASE_URL}/api/courses/${courseIdToDelete}`,
{
headers: {
Authorization: `Bearer ${authToken}`,
},
}
);
if (response.data.success) {
console.log(`✅ 删除自己创建的课程成功`);
} else {
console.log(`❌ 删除失败: ${response.data.message || '未知错误'}`);
}
} catch (error: any) {
if (error.response?.status === 403) {
console.log(`❌ 删除失败: 权限不足403`);
} else {
console.log(`❌ 删除失败: ${error.message}`);
}
}
}
}
async function testDeleteOtherUserCourse() {
console.log('\n🗑 测试 6: 尝试删除他人创建的课程(应该失败)');
if (!otherUserToken) {
const otherEmail = `other_${Date.now()}@example.com`;
await registerUser(otherEmail, TEST_PASSWORD);
const loginResult = await login(otherEmail, TEST_PASSWORD);
otherUserToken = loginResult.token;
otherUserId = loginResult.userId;
}
// 尝试删除第一个用户创建的课程
try {
await axios.delete(
`${BASE_URL}/api/courses/${createdCourseId}`,
{
headers: {
Authorization: `Bearer ${otherUserToken}`,
},
}
);
console.log(`❌ 不应该成功删除他人课程`);
} catch (error: any) {
if (error.response?.status === 403) {
console.log(`✅ 正确拒绝删除他人课程403 Forbidden`);
} else {
console.log(`⚠️ 返回了其他错误: ${error.response?.status} - ${error.message}`);
}
}
}
async function main() {
console.log('🚀 开始测试 createdBy 和 visibility 功能\n');
console.log(`测试环境: ${BASE_URL}`);
try {
// 1. 注册和登录测试用户
console.log('\n👤 注册和登录测试用户...');
await registerUser(TEST_EMAIL, TEST_PASSWORD);
const loginResult = await login(TEST_EMAIL, TEST_PASSWORD);
authToken = loginResult.token;
userId = loginResult.userId;
console.log(`✅ 登录成功userId: ${userId}`);
// 2. 测试创建课程
await testCreateCourse();
// 3. 测试查询课程列表
await testQueryCourses();
// 4. 测试修改自己创建的课程
await testUpdateOwnCourse();
// 5. 测试修改他人创建的课程(应该失败)
await testUpdateOtherUserCourse();
// 6. 测试删除自己创建的课程
await testDeleteOwnCourse();
// 7. 测试删除他人创建的课程(应该失败)
await testDeleteOtherUserCourse();
console.log('\n✅ 所有测试完成!');
} catch (error: any) {
console.error('\n❌ 测试失败:', error.message);
if (error.response) {
console.error('响应数据:', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
main();