443 lines
12 KiB
TypeScript
443 lines
12 KiB
TypeScript
/**
|
||
* Text Video Agent API 测试文件
|
||
*/
|
||
|
||
import { textVideoAgentAPI, TextVideoAgentAPI } from '../src/services/textVideoAgentAPI'
|
||
import { TaskType, AspectRatio, VideoDuration } from '../src/services/textVideoAgentTypes'
|
||
|
||
// Mock fetch for testing
|
||
global.fetch = jest.fn()
|
||
|
||
describe('TextVideoAgentAPI', () => {
|
||
beforeEach(() => {
|
||
jest.clearAllMocks()
|
||
})
|
||
|
||
describe('基础功能测试', () => {
|
||
test('健康检查', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Service is healthy'
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.healthCheck()
|
||
|
||
expect(fetch).toHaveBeenCalledWith(
|
||
expect.stringContaining('/health'),
|
||
expect.any(Object)
|
||
)
|
||
expect(result).toEqual(mockResponse)
|
||
})
|
||
|
||
test('获取示例提示词', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Success',
|
||
data: {
|
||
prompts: ['示例提示词1', '示例提示词2']
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.getSamplePrompt(TaskType.VLOG)
|
||
|
||
expect(fetch).toHaveBeenCalledWith(
|
||
expect.stringContaining('/api/prompt/default?task_type=vlog'),
|
||
expect.any(Object)
|
||
)
|
||
expect(result).toEqual(mockResponse)
|
||
})
|
||
})
|
||
|
||
describe('图片生成测试', () => {
|
||
test('同步生成图片', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Image generated successfully',
|
||
data: {
|
||
image_url: 'https://example.com/generated-image.jpg'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.generateImageSync({
|
||
prompt: '测试图片生成',
|
||
max_wait_time: 60
|
||
})
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.image_url).toBe('https://example.com/generated-image.jpg')
|
||
})
|
||
|
||
test('异步生成图片', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Task submitted',
|
||
data: {
|
||
task_id: 'test-task-123'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.generateImageAsync('测试异步图片生成')
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.task_id).toBe('test-task-123')
|
||
})
|
||
|
||
test('带重试的图片生成', async () => {
|
||
// 第一次失败
|
||
;(fetch as jest.Mock).mockRejectedValueOnce(new Error('Network error'))
|
||
|
||
// 第二次成功
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Image generated successfully',
|
||
data: {
|
||
image_url: 'https://example.com/generated-image.jpg'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.generateImageWithRetry({
|
||
prompt: '测试重试机制',
|
||
max_wait_time: 60
|
||
}, 2)
|
||
|
||
expect(fetch).toHaveBeenCalledTimes(2)
|
||
expect(result).toEqual(mockResponse)
|
||
})
|
||
})
|
||
|
||
describe('视频生成测试', () => {
|
||
test('同步生成视频', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Video generated successfully',
|
||
data: {
|
||
video_url: 'https://example.com/generated-video.mp4'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.generateVideoSync({
|
||
prompt: '测试视频生成',
|
||
img_url: 'https://example.com/base-image.jpg',
|
||
duration: '5'
|
||
})
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.video_url).toBe('https://example.com/generated-video.mp4')
|
||
})
|
||
|
||
test('异步生成视频', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Video task submitted',
|
||
data: {
|
||
task_id: 'video-task-456'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.generateVideoAsync({
|
||
prompt: '测试异步视频生成',
|
||
duration: '5'
|
||
})
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.task_id).toBe('video-task-456')
|
||
})
|
||
})
|
||
|
||
describe('任务管理测试', () => {
|
||
test('创建任务', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Task created successfully',
|
||
data: {
|
||
task_id: 'new-task-789'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.createTask({
|
||
task_type: TaskType.VLOG,
|
||
prompt: '测试任务创建',
|
||
ar: AspectRatio.PORTRAIT
|
||
})
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.task_id).toBe('new-task-789')
|
||
})
|
||
|
||
test('查询任务状态', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Task status retrieved',
|
||
data: {
|
||
task_id: 'test-task-123',
|
||
status: 'completed',
|
||
progress: 100,
|
||
result: {
|
||
image_url: 'https://example.com/result.jpg'
|
||
}
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.getTaskStatusAsync('test-task-123')
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.status).toBe('completed')
|
||
})
|
||
})
|
||
|
||
describe('文件操作测试', () => {
|
||
test('文件上传', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'File uploaded successfully',
|
||
data: 'https://example.com/uploaded-file.jpg'
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const mockFile = new File(['test content'], 'test.jpg', { type: 'image/jpeg' })
|
||
const result = await textVideoAgentAPI.uploadFile(mockFile)
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data).toBe('https://example.com/uploaded-file.jpg')
|
||
})
|
||
})
|
||
|
||
describe('图片描述测试', () => {
|
||
test('通过URL描述图片', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Image described successfully',
|
||
data: {
|
||
description: '这是一张美丽的风景照片'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.describeImageByUrl({
|
||
image_url: 'https://example.com/image.jpg'
|
||
})
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.description).toBe('这是一张美丽的风景照片')
|
||
})
|
||
|
||
test('通过文件描述图片', async () => {
|
||
const mockResponse = {
|
||
status: true,
|
||
msg: 'Image described successfully',
|
||
data: {
|
||
description: '这是一张人物照片'
|
||
}
|
||
}
|
||
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => mockResponse
|
||
})
|
||
|
||
const mockFile = new File(['image content'], 'portrait.jpg', { type: 'image/jpeg' })
|
||
const result = await textVideoAgentAPI.describeImageByFile({
|
||
img_file: mockFile
|
||
})
|
||
|
||
expect(result).toEqual(mockResponse)
|
||
expect(result.data?.description).toBe('这是一张人物照片')
|
||
})
|
||
})
|
||
|
||
describe('高级功能测试', () => {
|
||
test('端到端内容生成', async () => {
|
||
// Mock 创建任务
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => ({
|
||
status: true,
|
||
data: { task_id: 'end-to-end-task' }
|
||
})
|
||
})
|
||
|
||
// Mock 图片生成
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => ({
|
||
status: true,
|
||
data: { image_url: 'https://example.com/generated.jpg' }
|
||
})
|
||
})
|
||
|
||
// Mock 视频生成
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => ({
|
||
status: true,
|
||
data: { video_url: 'https://example.com/generated.mp4' }
|
||
})
|
||
})
|
||
|
||
const result = await textVideoAgentAPI.generateContentEndToEnd(
|
||
'测试端到端生成',
|
||
{
|
||
taskType: TaskType.VLOG,
|
||
aspectRatio: AspectRatio.PORTRAIT,
|
||
videoDuration: VideoDuration.MEDIUM,
|
||
generateVideo: true
|
||
}
|
||
)
|
||
|
||
expect(result).toEqual({
|
||
imageUrl: 'https://example.com/generated.jpg',
|
||
videoUrl: 'https://example.com/generated.mp4',
|
||
taskId: 'end-to-end-task'
|
||
})
|
||
})
|
||
|
||
test('轮询任务直到完成', async () => {
|
||
// 第一次查询 - 进行中
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => ({
|
||
status: true,
|
||
data: { status: 'running', progress: 50 }
|
||
})
|
||
})
|
||
|
||
// 第二次查询 - 完成
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: true,
|
||
json: async () => ({
|
||
status: true,
|
||
data: {
|
||
status: 'completed',
|
||
progress: 100,
|
||
result: { image_url: 'https://example.com/final.jpg' }
|
||
}
|
||
})
|
||
})
|
||
|
||
const progressCallback = jest.fn()
|
||
|
||
const result = await textVideoAgentAPI.pollTaskUntilComplete(
|
||
'test-task-id',
|
||
100, // 快速轮询用于测试
|
||
5000, // 5秒超时
|
||
progressCallback
|
||
)
|
||
|
||
expect(fetch).toHaveBeenCalledTimes(2)
|
||
expect(progressCallback).toHaveBeenCalledTimes(2)
|
||
expect(result.data?.status).toBe('completed')
|
||
})
|
||
})
|
||
|
||
describe('错误处理测试', () => {
|
||
test('网络错误处理', async () => {
|
||
;(fetch as jest.Mock).mockRejectedValueOnce(new Error('Network error'))
|
||
|
||
await expect(textVideoAgentAPI.healthCheck()).rejects.toThrow('Network error')
|
||
})
|
||
|
||
test('HTTP错误处理', async () => {
|
||
;(fetch as jest.Mock).mockResolvedValueOnce({
|
||
ok: false,
|
||
status: 500,
|
||
json: async () => ({ error: 'Internal server error' })
|
||
})
|
||
|
||
await expect(textVideoAgentAPI.healthCheck()).rejects.toThrow('HTTP error! status: 500')
|
||
})
|
||
|
||
test('参数验证', async () => {
|
||
await expect(
|
||
textVideoAgentAPI.describeImageByUrl({} as any)
|
||
).rejects.toThrow('image_url is required')
|
||
|
||
await expect(
|
||
textVideoAgentAPI.describeImageByFile({} as any)
|
||
).rejects.toThrow('img_file is required')
|
||
})
|
||
})
|
||
|
||
describe('自定义配置测试', () => {
|
||
test('自定义API端点', () => {
|
||
const customAPI = new TextVideoAgentAPI('https://custom-endpoint.com')
|
||
expect(customAPI).toBeInstanceOf(TextVideoAgentAPI)
|
||
})
|
||
})
|
||
})
|
||
|
||
// 集成测试(需要真实API)
|
||
describe('集成测试 (需要真实API)', () => {
|
||
// 这些测试需要真实的API端点,通常在CI/CD环境中跳过
|
||
const shouldRunIntegrationTests = process.env.RUN_INTEGRATION_TESTS === 'true'
|
||
|
||
test.skipIf(!shouldRunIntegrationTests)('真实健康检查', async () => {
|
||
const result = await textVideoAgentAPI.healthCheck()
|
||
expect(result.status).toBe(true)
|
||
})
|
||
|
||
test.skipIf(!shouldRunIntegrationTests)('真实图片生成', async () => {
|
||
const result = await textVideoAgentAPI.generateImageSync({
|
||
prompt: '一朵美丽的花',
|
||
max_wait_time: 60
|
||
})
|
||
|
||
expect(result.status).toBe(true)
|
||
expect(result.data?.image_url).toBeDefined()
|
||
}, 120000) // 2分钟超时
|
||
})
|
||
|
||
export {}
|