import { getSceneList, getSceneData, updateText, updateTag, regenerateScene, getSceneShots, applySceneToShots } from '@/api/video_flow'; import { SceneEditUseCase } from '../usecase/SceneEditUseCase'; import { TextEditUseCase } from '../usecase/TextEditUseCase'; import { TagEditUseCase } from '../usecase/TagEditUseCase'; import { SceneItem, TextItem, TagItem } from '../domain/Item'; import { SceneEntity, AITextEntity, TagEntity, ShotEntity, ShotStatus } from '../domain/Entities'; // Mock API模块 jest.mock('@/api/video_flow', () => ({ getSceneList: jest.fn(), getSceneData: jest.fn(), updateText: jest.fn(), updateTag: jest.fn(), regenerateScene: jest.fn(), getSceneShots: jest.fn(), applySceneToShots: jest.fn(), })); // Mock UseCase模块 jest.mock('../usecase/SceneEditUseCase'); jest.mock('../usecase/TextEditUseCase'); jest.mock('../usecase/TagEditUseCase'); // Mock Domain模块 jest.mock('../domain/Item', () => ({ SceneItem: jest.fn(), TextItem: jest.fn(), TagItem: jest.fn(), })); describe('SceneService 业务逻辑测试', () => { let mockSceneEditUseCase: jest.Mocked; let mockTextEditUseCase: jest.Mocked; let mockTagEditUseCase: jest.Mocked; // 测试数据 const mockSceneEntity: SceneEntity = { id: 'scene1', name: '测试场景', imageUrl: 'http://example.com/scene1.jpg', tagIds: ['tag1', 'tag2'], generateTextId: 'text1', updatedAt: Date.now(), loadingProgress: 100, disableEdit: false, }; const mockTextEntity: AITextEntity = { id: 'text1', content: '这是AI生成的场景文本内容', updatedAt: Date.now(), loadingProgress: 100, disableEdit: false, }; const mockTagEntity1: TagEntity = { id: 'tag1', name: '场景标签1', content: '场景标签内容1', updatedAt: Date.now(), loadingProgress: 100, disableEdit: false, }; const mockTagEntity2: TagEntity = { id: 'tag2', name: '场景标签2', content: '场景标签内容2', updatedAt: Date.now(), loadingProgress: 100, disableEdit: false, }; const mockShotEntity: ShotEntity = { id: 'shot1', name: '分镜1', sketchUrl: 'http://example.com/sketch1.jpg', videoUrl: ['http://example.com/video1.mp4'], roleList: [], sceneList: [], content: [], status: ShotStatus.sketchLoading, shot: [], scriptId: 'script1', updatedAt: Date.now(), loadingProgress: 100, disableEdit: false, }; beforeEach(() => { jest.clearAllMocks(); // 设置Mock UseCase实例 mockSceneEditUseCase = { AIgenerateScene: jest.fn(), applyScene: jest.fn(), refreshSceneData: jest.fn(), } as any; mockTextEditUseCase = { getOptimizedContent: jest.fn(), updateText: jest.fn(), } as any; mockTagEditUseCase = { updateTag: jest.fn(), } as any; // 设置Mock构造函数 (SceneEditUseCase as jest.MockedClass).mockImplementation(() => mockSceneEditUseCase); (TextEditUseCase as jest.MockedClass).mockImplementation(() => mockTextEditUseCase); (TagEditUseCase as jest.MockedClass).mockImplementation(() => mockTagEditUseCase); // 设置Mock Item构造函数 (SceneItem as jest.MockedClass).mockImplementation((entity) => ({ entity, metadata: {}, disableEdit: entity.disableEdit, type: 3, } as any)); (TextItem as jest.MockedClass).mockImplementation((entity) => ({ entity, metadata: {}, disableEdit: entity.disableEdit, type: 0, } as any)); (TagItem as jest.MockedClass).mockImplementation((entity) => ({ entity, metadata: {}, disableEdit: entity.disableEdit, type: 2, } as any)); }); describe('数据初始化测试', () => { it('应该成功获取场景列表', async () => { const mockScenes = [mockSceneEntity]; (getSceneList as jest.Mock).mockResolvedValue({ successful: true, data: mockScenes, message: 'success', }); const result = await getSceneList({ projectId: 'project1' }); expect(getSceneList).toHaveBeenCalledWith({ projectId: 'project1' }); expect(result.successful).toBe(true); expect(result.data).toEqual(mockScenes); }); it('获取场景列表失败时应该返回错误信息', async () => { (getSceneList as jest.Mock).mockResolvedValue({ successful: false, message: '获取失败', }); const result = await getSceneList({ projectId: 'project1' }); expect(result.successful).toBe(false); expect(result.message).toBe('获取失败'); }); it('应该成功获取场景数据', async () => { (getSceneData as jest.Mock).mockResolvedValue({ successful: true, data: { text: mockTextEntity, tags: [mockTagEntity1, mockTagEntity2], }, }); const result = await getSceneData({ sceneId: 'scene1' }); expect(getSceneData).toHaveBeenCalledWith({ sceneId: 'scene1' }); expect(result.successful).toBe(true); expect(result.data.text).toEqual(mockTextEntity); expect(result.data.tags).toEqual([mockTagEntity1, mockTagEntity2]); }); }); describe('修改文本和标签测试', () => { it('应该成功修改AI文本', async () => { const updatedTextEntity = { ...mockTextEntity, content: '更新后的场景文本' }; (updateText as jest.Mock).mockResolvedValue({ successful: true, data: updatedTextEntity, }); const result = await updateText({ textId: 'text1', content: '新的场景文本内容' }); expect(updateText).toHaveBeenCalledWith({ textId: 'text1', content: '新的场景文本内容' }); expect(result.successful).toBe(true); expect(result.data.content).toBe('更新后的场景文本'); }); it('应该成功修改标签内容', async () => { const updatedTagEntity = { ...mockTagEntity1, content: '更新后的场景标签' }; (updateTag as jest.Mock).mockResolvedValue({ successful: true, data: updatedTagEntity, }); const result = await updateTag({ tagId: 'tag1', content: '新的场景标签内容' }); expect(updateTag).toHaveBeenCalledWith({ tagId: 'tag1', content: '新的场景标签内容' }); expect(result.successful).toBe(true); expect(result.data.content).toBe('更新后的场景标签'); }); }); describe('文本AI优化测试', () => { it('应该成功优化AI文本', async () => { const optimizedContent = '优化后的场景文本内容'; const updatedTextEntity = { ...mockTextEntity, content: optimizedContent }; mockTextEditUseCase.getOptimizedContent.mockResolvedValue(optimizedContent); mockTextEditUseCase.updateText.mockResolvedValue({ entity: updatedTextEntity, metadata: {}, disableEdit: false, type: 0, } as any); (updateText as jest.Mock).mockResolvedValue({ successful: true, data: updatedTextEntity, }); // 模拟优化流程 const optimizedContentResult = await mockTextEditUseCase.getOptimizedContent(); const updateResult = await mockTextEditUseCase.updateText(optimizedContentResult); expect(mockTextEditUseCase.getOptimizedContent).toHaveBeenCalled(); expect(mockTextEditUseCase.updateText).toHaveBeenCalledWith(optimizedContent); expect(updateResult.entity.content).toBe(optimizedContent); }); it('没有文本内容时优化应该抛出错误', async () => { const emptyTextEntity = { ...mockTextEntity, content: '' }; mockTextEditUseCase.getOptimizedContent.mockRejectedValue(new Error('没有可优化的文本内容')); await expect(mockTextEditUseCase.getOptimizedContent()).rejects.toThrow('没有可优化的文本内容'); }); }); describe('重新生成场景测试', () => { it('应该成功重新生成场景', async () => { const newSceneEntity = { ...mockSceneEntity, id: 'scene2', name: '新场景' }; (regenerateScene as jest.Mock).mockResolvedValue({ successful: true, data: newSceneEntity, }); mockSceneEditUseCase.AIgenerateScene.mockResolvedValue(newSceneEntity); const result = await regenerateScene({ prompt: '重新生成场景', tagTypes: ['tag1', 'tag2'], sceneId: 'scene1' }); expect(regenerateScene).toHaveBeenCalledWith({ prompt: '重新生成场景', tagTypes: ['tag1', 'tag2'], sceneId: 'scene1' }); expect(result.successful).toBe(true); expect(result.data.id).toBe('scene2'); expect(result.data.name).toBe('新场景'); }); it('重新生成场景失败时应该返回错误信息', async () => { (regenerateScene as jest.Mock).mockResolvedValue({ successful: false, message: '重新生成失败', }); const result = await regenerateScene({ prompt: '重新生成场景', tagTypes: ['tag1', 'tag2'], sceneId: 'scene1' }); expect(result.successful).toBe(false); expect(result.message).toBe('重新生成失败'); }); }); describe('场景业务流程测试', () => { it('应该完成完整的场景编辑流程:获取列表→选择场景→修改提示词→智能优化→修改标签→重新生成→应用场景', async () => { // 模拟用户操作:获取场景列表 const mockScenes = [mockSceneEntity]; (getSceneList as jest.Mock).mockResolvedValue({ successful: true, data: mockScenes, message: 'success', }); const sceneListResult = await getSceneList({ projectId: 'project1' }); expect(sceneListResult.successful).toBe(true); expect(sceneListResult.data).toEqual(mockScenes); // 模拟用户操作:选择场景并获取场景数据 (getSceneData as jest.Mock).mockResolvedValue({ successful: true, data: { text: mockTextEntity, tags: [mockTagEntity1, mockTagEntity2], }, }); const sceneDataResult = await getSceneData({ sceneId: 'scene1' }); expect(sceneDataResult.successful).toBe(true); expect(sceneDataResult.data.text).toEqual(mockTextEntity); expect(sceneDataResult.data.tags).toEqual([mockTagEntity1, mockTagEntity2]); // 模拟用户操作:修改场景提示词 const updatedTextEntity = { ...mockTextEntity, content: '修改后的场景提示词' }; (updateText as jest.Mock).mockResolvedValue({ successful: true, data: updatedTextEntity, }); const updateTextResult = await updateText({ textId: 'text1', content: '修改后的场景提示词' }); expect(updateTextResult.successful).toBe(true); expect(updateTextResult.data.content).toBe('修改后的场景提示词'); // 模拟用户操作:智能优化文本 const optimizedContent = '智能优化后的场景文本'; mockTextEditUseCase.getOptimizedContent.mockResolvedValue(optimizedContent); mockTextEditUseCase.updateText.mockResolvedValue({ entity: { ...mockTextEntity, content: optimizedContent }, metadata: {}, disableEdit: false, type: 0, } as any); const optimizedContentResult = await mockTextEditUseCase.getOptimizedContent(); expect(optimizedContentResult).toBe(optimizedContent); // 模拟用户操作:修改标签 const updatedTagEntity = { ...mockTagEntity1, content: '修改后的标签内容' }; (updateTag as jest.Mock).mockResolvedValue({ successful: true, data: updatedTagEntity, }); const updateTagResult = await updateTag({ tagId: 'tag1', content: '修改后的标签内容' }); expect(updateTagResult.successful).toBe(true); expect(updateTagResult.data.content).toBe('修改后的标签内容'); // 模拟用户操作:使用新的提示词和标签重新生成场景 const newSceneEntity = { ...mockSceneEntity, id: 'scene2', name: '重新生成的场景' }; (regenerateScene as jest.Mock).mockResolvedValue({ successful: true, data: newSceneEntity, }); mockSceneEditUseCase.AIgenerateScene.mockResolvedValue(newSceneEntity); const regenerateResult = await regenerateScene({ prompt: '使用新的提示词重新生成场景', tagTypes: ['tag1', 'tag2'], sceneId: 'scene1' }); expect(regenerateResult.successful).toBe(true); expect(regenerateResult.data.name).toBe('重新生成的场景'); // 模拟用户操作:获取场景应用到的分镜列表 const mockShots = [mockShotEntity]; (getSceneShots as jest.Mock).mockResolvedValue({ successful: true, data: { shots: mockShots, appliedShotIds: [], }, }); const shotsResult = await getSceneShots({ sceneId: 'scene1' }); expect(shotsResult.successful).toBe(true); expect(shotsResult.data.shots).toEqual(mockShots); // 模拟用户操作:选择分镜并应用新的场景 (applySceneToShots as jest.Mock).mockResolvedValue({ successful: true, data: { success: true }, }); mockSceneEditUseCase.applyScene.mockResolvedValue({} as any); const applyResult = await applySceneToShots({ sceneId: 'scene1', shotIds: ['shot1', 'shot2'] }); expect(applyResult.successful).toBe(true); }); it('应该模拟用户选择场景并修改提示词的完整流程', async () => { // 用户操作:获取项目中的场景列表 const mockScenes = [ { ...mockSceneEntity, id: 'scene1', name: '场景1' }, { ...mockSceneEntity, id: 'scene2', name: '场景2' } ]; (getSceneList as jest.Mock).mockResolvedValue({ successful: true, data: mockScenes, }); const sceneList = await getSceneList({ projectId: 'project1' }); expect(sceneList.data).toHaveLength(2); // 用户操作:选择第一个场景 const selectedSceneId = 'scene1'; (getSceneData as jest.Mock).mockResolvedValue({ successful: true, data: { text: mockTextEntity, tags: [mockTagEntity1], }, }); const selectedSceneData = await getSceneData({ sceneId: selectedSceneId }); expect(selectedSceneData.data.text.id).toBe('text1'); // 用户操作:修改场景提示词 const newPrompt = '我想要一个更加戏剧性的场景'; (updateText as jest.Mock).mockResolvedValue({ successful: true, data: { ...mockTextEntity, content: newPrompt }, }); const updatedText = await updateText({ textId: 'text1', content: newPrompt }); expect(updatedText.data.content).toBe(newPrompt); // 用户操作:使用新提示词重新生成场景 const regeneratedScene = { ...mockSceneEntity, name: '戏剧性场景' }; (regenerateScene as jest.Mock).mockResolvedValue({ successful: true, data: regeneratedScene, }); const regenerationResult = await regenerateScene({ prompt: newPrompt, tagTypes: ['tag1'], sceneId: selectedSceneId }); expect(regenerationResult.data.name).toBe('戏剧性场景'); }); it('应该处理场景编辑流程中的错误情况', async () => { // 模拟获取场景列表失败 (getSceneList as jest.Mock).mockResolvedValue({ successful: false, message: '获取场景列表失败', }); const sceneListResult = await getSceneList({ projectId: 'project1' }); expect(sceneListResult.successful).toBe(false); expect(sceneListResult.message).toBe('获取场景列表失败'); // 模拟修改文本失败 (updateText as jest.Mock).mockResolvedValue({ successful: false, message: '修改文本失败', }); const updateTextResult = await updateText({ textId: 'text1', content: '新的文本内容' }); expect(updateTextResult.successful).toBe(false); expect(updateTextResult.message).toBe('修改文本失败'); // 模拟重新生成场景失败 (regenerateScene as jest.Mock).mockResolvedValue({ successful: false, message: '重新生成场景失败', }); const regenerateResult = await regenerateScene({ prompt: '重新生成场景', tagTypes: ['tag1'], sceneId: 'scene1' }); expect(regenerateResult.successful).toBe(false); expect(regenerateResult.message).toBe('重新生成场景失败'); // 模拟应用场景失败 (applySceneToShots as jest.Mock).mockResolvedValue({ successful: false, message: '应用场景失败', }); const applyResult = await applySceneToShots({ sceneId: 'scene1', shotIds: ['shot1'] }); expect(applyResult.successful).toBe(false); expect(applyResult.message).toBe('应用场景失败'); }); }); describe('场景应用到多个分镜测试', () => { it('应该成功获取场景分镜列表', async () => { const mockShots = [mockShotEntity]; (getSceneShots as jest.Mock).mockResolvedValue({ successful: true, data: { shots: mockShots, appliedShotIds: [], }, }); const result = await getSceneShots({ sceneId: 'scene1' }); expect(getSceneShots).toHaveBeenCalledWith({ sceneId: 'scene1' }); expect(result.successful).toBe(true); expect(result.data.shots).toEqual(mockShots); expect(result.data.appliedShotIds).toEqual([]); }); it('应该成功应用场景到选中的分镜', async () => { (applySceneToShots as jest.Mock).mockResolvedValue({ successful: true, data: { success: true }, }); mockSceneEditUseCase.applyScene.mockResolvedValue({} as any); const result = await applySceneToShots({ sceneId: 'scene1', shotIds: ['shot1', 'shot2'] }); expect(applySceneToShots).toHaveBeenCalledWith({ sceneId: 'scene1', shotIds: ['shot1', 'shot2'] }); expect(result.successful).toBe(true); }); it('应用场景失败时应该返回错误信息', async () => { (applySceneToShots as jest.Mock).mockResolvedValue({ successful: false, message: '应用失败', }); const result = await applySceneToShots({ sceneId: 'scene1', shotIds: ['shot1'] }); expect(result.successful).toBe(false); expect(result.message).toBe('应用失败'); }); it('应该正确处理已应用的分镜状态', async () => { const mockShots = [mockShotEntity]; (getSceneShots as jest.Mock).mockResolvedValue({ successful: true, data: { shots: mockShots, appliedShotIds: ['shot1'], // 分镜1已应用 }, }); const result = await getSceneShots({ sceneId: 'scene1' }); expect(result.data.appliedShotIds).toEqual(['shot1']); expect(result.data.shots).toEqual(mockShots); }); }); describe('UseCase业务逻辑测试', () => { it('SceneEditUseCase应该正确初始化', () => { const sceneItem = new SceneItem(mockSceneEntity); const useCase = new SceneEditUseCase(sceneItem); expect(SceneEditUseCase).toHaveBeenCalledWith(sceneItem); expect(useCase).toBeDefined(); }); it('TextEditUseCase应该正确初始化', () => { const textItem = new TextItem(mockTextEntity); const useCase = new TextEditUseCase(textItem); expect(TextEditUseCase).toHaveBeenCalledWith(textItem); expect(useCase).toBeDefined(); }); it('TagEditUseCase应该正确初始化', () => { const tagItem = new TagItem(mockTagEntity1); const useCase = new TagEditUseCase(tagItem); expect(TagEditUseCase).toHaveBeenCalledWith(tagItem); expect(useCase).toBeDefined(); }); }); describe('Domain实体测试', () => { it('SceneItem应该正确包装SceneEntity', () => { const sceneItem = new SceneItem(mockSceneEntity); expect(SceneItem).toHaveBeenCalledWith(mockSceneEntity); expect(sceneItem.entity).toEqual(mockSceneEntity); expect(sceneItem.disableEdit).toBe(false); }); it('TextItem应该正确包装AITextEntity', () => { const textItem = new TextItem(mockTextEntity); expect(TextItem).toHaveBeenCalledWith(mockTextEntity); expect(textItem.entity).toEqual(mockTextEntity); expect(textItem.disableEdit).toBe(false); }); it('TagItem应该正确包装TagEntity', () => { const tagItem = new TagItem(mockTagEntity1); expect(TagItem).toHaveBeenCalledWith(mockTagEntity1); expect(tagItem.entity).toEqual(mockTagEntity1); expect(tagItem.disableEdit).toBe(false); }); }); describe('错误处理测试', () => { it('API调用失败时应该正确处理错误', async () => { (getSceneList as jest.Mock).mockRejectedValue(new Error('网络错误')); await expect(getSceneList({ projectId: 'project1' })).rejects.toThrow('网络错误'); }); it('API返回失败状态时应该正确处理', async () => { (getSceneList as jest.Mock).mockResolvedValue({ successful: false, message: '服务器错误', }); const result = await getSceneList({ projectId: 'project1' }); expect(result.successful).toBe(false); expect(result.message).toBe('服务器错误'); }); it('UseCase未初始化时应该抛出相应错误', async () => { const sceneItem = new SceneItem(mockSceneEntity); const useCase = new SceneEditUseCase(sceneItem); // 模拟UseCase未初始化的情况 mockSceneEditUseCase.AIgenerateScene.mockRejectedValue(new Error('场景编辑UseCase未初始化')); await expect(useCase.AIgenerateScene({} as any, [])).rejects.toThrow('场景编辑UseCase未初始化'); }); }); describe('场景数据完整性测试', () => { it('应该验证场景实体的完整性', () => { const sceneItem = new SceneItem(mockSceneEntity); expect(sceneItem.entity.id).toBe('scene1'); expect(sceneItem.entity.name).toBe('测试场景'); expect(sceneItem.entity.imageUrl).toBe('http://example.com/scene1.jpg'); expect(sceneItem.entity.tagIds).toEqual(['tag1', 'tag2']); expect(sceneItem.entity.generateTextId).toBe('text1'); }); it('应该验证文本实体的完整性', () => { const textItem = new TextItem(mockTextEntity); expect(textItem.entity.id).toBe('text1'); expect(textItem.entity.content).toBe('这是AI生成的场景文本内容'); }); it('应该验证标签实体的完整性', () => { const tagItem = new TagItem(mockTagEntity1); expect(tagItem.entity.id).toBe('tag1'); expect(tagItem.entity.name).toBe('场景标签1'); expect(tagItem.entity.content).toBe('场景标签内容1'); }); }); });