video-flow-b/app/service/test/Role.test.ts
2025-07-30 16:09:49 +08:00

514 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { getRoleList, getRoleData, updateText, updateTag, regenerateRole, getUserRoleLibrary, replaceRole, getRoleShots, applyRoleToShots } from '@/api/video_flow';
import { RoleEditUseCase } from '../usecase/RoleEditUseCase';
import { TextEditUseCase } from '../usecase/TextEditUseCase';
import { TagEditUseCase } from '../usecase/TagEditUseCase';
import { RoleItem, TextItem, TagItem } from '../domain/Item';
import { RoleEntity, AITextEntity, TagEntity, ShotEntity } from '../domain/Entities';
// Mock API模块
jest.mock('@/api/video_flow', () => ({
getRoleList: jest.fn(),
getRoleData: jest.fn(),
updateText: jest.fn(),
updateTag: jest.fn(),
regenerateRole: jest.fn(),
getUserRoleLibrary: jest.fn(),
replaceRole: jest.fn(),
getRoleShots: jest.fn(),
applyRoleToShots: jest.fn(),
}));
// Mock UseCase模块
jest.mock('../usecase/RoleEditUseCase');
jest.mock('../usecase/TextEditUseCase');
jest.mock('../usecase/TagEditUseCase');
// Mock Domain模块
jest.mock('../domain/Item', () => ({
RoleItem: jest.fn(),
TextItem: jest.fn(),
TagItem: jest.fn(),
}));
describe('RoleService 业务逻辑测试', () => {
let mockRoleEditUseCase: jest.Mocked<RoleEditUseCase>;
let mockTextEditUseCase: jest.Mocked<TextEditUseCase>;
let mockTagEditUseCase: jest.Mocked<TagEditUseCase>;
// 测试数据
const mockRoleEntity: RoleEntity = {
id: 'role1',
name: '测试角色',
generateTextId: 'text1',
tagIds: ['tag1', 'tag2'],
imageUrl: 'http://example.com/role1.jpg',
updatedAt: Date.now(),
loadingProgress: 100,
disableEdit: false,
isStored: true,
};
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 mockShotEntity: ShotEntity = {
id: 'shot1',
name: '分镜1',
sketchUrl: 'http://example.com/sketch1.jpg',
videoUrl: 'http://example.com/video1.mp4',
roleMap: [],
content: [],
shot: [],
updatedAt: Date.now(),
loadingProgress: 100,
disableEdit: false,
};
beforeEach(() => {
jest.clearAllMocks();
// 设置Mock UseCase实例
mockRoleEditUseCase = {
AIgenerateRole: jest.fn(),
applyRole: jest.fn(),
} as any;
mockTextEditUseCase = {
getOptimizedContent: jest.fn(),
updateText: jest.fn(),
} as any;
mockTagEditUseCase = {
updateTag: jest.fn(),
} as any;
// 设置Mock构造函数
(RoleEditUseCase as jest.MockedClass<typeof RoleEditUseCase>).mockImplementation(() => mockRoleEditUseCase);
(TextEditUseCase as jest.MockedClass<typeof TextEditUseCase>).mockImplementation(() => mockTextEditUseCase);
(TagEditUseCase as jest.MockedClass<typeof TagEditUseCase>).mockImplementation(() => mockTagEditUseCase);
// 设置Mock Item构造函数
(RoleItem as jest.MockedClass<typeof RoleItem>).mockImplementation((entity) => ({
entity,
metadata: {},
disableEdit: entity.disableEdit,
type: 1,
} as any));
(TextItem as jest.MockedClass<typeof TextItem>).mockImplementation((entity) => ({
entity,
metadata: {},
disableEdit: entity.disableEdit,
type: 0,
} as any));
(TagItem as jest.MockedClass<typeof TagItem>).mockImplementation((entity) => ({
entity,
metadata: {},
disableEdit: entity.disableEdit,
type: 2,
} as any));
});
describe('数据初始化测试', () => {
it('应该成功获取角色列表', async () => {
const mockRoles = [mockRoleEntity];
(getRoleList as jest.Mock).mockResolvedValue({
successful: true,
data: mockRoles,
message: 'success',
});
const result = await getRoleList({ projectId: 'project1' });
expect(getRoleList).toHaveBeenCalledWith({ projectId: 'project1' });
expect(result.successful).toBe(true);
expect(result.data).toEqual(mockRoles);
});
it('获取角色列表失败时应该返回错误信息', async () => {
(getRoleList as jest.Mock).mockResolvedValue({
successful: false,
message: '获取失败',
});
const result = await getRoleList({ projectId: 'project1' });
expect(result.successful).toBe(false);
expect(result.message).toBe('获取失败');
});
});
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);
});
});
describe('重新生成角色形象测试', () => {
it('应该成功重新生成角色', async () => {
const newRoleEntity = { ...mockRoleEntity, id: 'role2', name: '新角色' };
(regenerateRole as jest.Mock).mockResolvedValue({
successful: true,
data: newRoleEntity,
});
mockRoleEditUseCase.AIgenerateRole.mockResolvedValue(newRoleEntity);
const result = await regenerateRole({
prompt: '重新生成角色',
tagTypes: ['tag1', 'tag2'],
roleId: 'role1'
});
expect(regenerateRole).toHaveBeenCalledWith({
prompt: '重新生成角色',
tagTypes: ['tag1', 'tag2'],
roleId: 'role1'
});
expect(result.successful).toBe(true);
expect(result.data.id).toBe('role2');
expect(result.data.name).toBe('新角色');
});
});
describe('重新获取角色数据测试', () => {
it('应该成功重新获取角色数据并更新实体', async () => {
const mockTextEntity = {
id: 'text1',
content: '更新后的AI文本',
updatedAt: Date.now(),
loadingProgress: 100,
disableEdit: false,
};
const mockTags = [
{
id: 'tag1',
name: '更新标签1',
content: '更新内容1',
updatedAt: Date.now(),
loadingProgress: 100,
disableEdit: false,
},
{
id: 'tag2',
name: '更新标签2',
content: '更新内容2',
updatedAt: Date.now(),
loadingProgress: 100,
disableEdit: false,
}
];
(getRoleData as jest.Mock).mockResolvedValue({
successful: true,
data: {
text: mockTextEntity,
tags: mockTags,
},
});
// 模拟RoleItem的setEntity方法
const mockSetEntity = jest.fn();
(RoleItem as jest.MockedClass<typeof RoleItem>).mockImplementation((entity) => ({
entity,
metadata: {},
disableEdit: entity.disableEdit,
type: 1,
setEntity: mockSetEntity,
} as any));
const roleItem = new RoleItem(mockRoleEntity);
const useCase = new RoleEditUseCase(roleItem);
const result = await useCase.refreshRoleData();
expect(getRoleData).toHaveBeenCalledWith({ roleId: 'role1' });
expect(result.text).toEqual(mockTextEntity);
expect(result.tags).toEqual(mockTags);
expect(mockSetEntity).toHaveBeenCalledWith(expect.objectContaining({
generateTextId: 'text1',
tagIds: ['tag1', 'tag2'],
updatedAt: expect.any(Number),
}));
});
it('角色ID不存在时应该抛出错误', async () => {
const emptyRoleEntity = { ...mockRoleEntity, id: '' };
const roleItem = new RoleItem(emptyRoleEntity);
const useCase = new RoleEditUseCase(roleItem);
await expect(useCase.refreshRoleData()).rejects.toThrow('角色ID不存在无法获取角色数据');
});
it('API调用失败时应该抛出错误', async () => {
(getRoleData as jest.Mock).mockResolvedValue({
successful: false,
message: '获取失败',
});
const roleItem = new RoleItem(mockRoleEntity);
const useCase = new RoleEditUseCase(roleItem);
await expect(useCase.refreshRoleData()).rejects.toThrow('获取角色数据失败: 获取失败');
});
});
describe('角色形象库选取使用测试', () => {
it('应该成功获取用户角色库', async () => {
const mockLibraryRoles = [mockRoleEntity];
(getUserRoleLibrary as jest.Mock).mockResolvedValue({
successful: true,
data: mockLibraryRoles,
});
const result = await getUserRoleLibrary();
expect(getUserRoleLibrary).toHaveBeenCalled();
expect(result.successful).toBe(true);
expect(result.data).toEqual(mockLibraryRoles);
});
it('应该成功替换角色', async () => {
(replaceRole as jest.Mock).mockResolvedValue({
successful: true,
data: { success: true },
});
const result = await replaceRole({
currentRoleId: 'role1',
replaceRoleId: 'newRoleId'
});
expect(replaceRole).toHaveBeenCalledWith({
currentRoleId: 'role1',
replaceRoleId: 'newRoleId'
});
expect(result.successful).toBe(true);
});
it('替换角色失败时应该返回错误信息', async () => {
(replaceRole as jest.Mock).mockResolvedValue({
successful: false,
message: '替换失败',
});
const result = await replaceRole({
currentRoleId: 'role1',
replaceRoleId: 'newRoleId'
});
expect(result.successful).toBe(false);
expect(result.message).toBe('替换失败');
});
});
describe('角色形象应用到多个分镜测试', () => {
it('应该成功获取角色分镜列表', async () => {
const mockShots = [mockShotEntity];
(getRoleShots as jest.Mock).mockResolvedValue({
successful: true,
data: {
shots: mockShots,
appliedShotIds: [],
},
});
const result = await getRoleShots({ roleId: 'role1' });
expect(getRoleShots).toHaveBeenCalledWith({ roleId: 'role1' });
expect(result.successful).toBe(true);
expect(result.data.shots).toEqual(mockShots);
expect(result.data.appliedShotIds).toEqual([]);
});
it('应该成功应用角色到选中的分镜', async () => {
(applyRoleToShots as jest.Mock).mockResolvedValue({
successful: true,
data: { success: true },
});
mockRoleEditUseCase.applyRole.mockResolvedValue({} as any);
const result = await applyRoleToShots({
roleId: 'role1',
shotIds: ['shot1', 'shot2']
});
expect(applyRoleToShots).toHaveBeenCalledWith({
roleId: 'role1',
shotIds: ['shot1', 'shot2']
});
expect(result.successful).toBe(true);
});
it('应用角色失败时应该返回错误信息', async () => {
(applyRoleToShots as jest.Mock).mockResolvedValue({
successful: false,
message: '应用失败',
});
const result = await applyRoleToShots({
roleId: 'role1',
shotIds: ['shot1']
});
expect(result.successful).toBe(false);
expect(result.message).toBe('应用失败');
});
});
describe('UseCase业务逻辑测试', () => {
it('RoleEditUseCase应该正确初始化', () => {
const roleItem = new RoleItem(mockRoleEntity);
const useCase = new RoleEditUseCase(roleItem);
expect(RoleEditUseCase).toHaveBeenCalledWith(roleItem);
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('RoleItem应该正确包装RoleEntity', () => {
const roleItem = new RoleItem(mockRoleEntity);
expect(RoleItem).toHaveBeenCalledWith(mockRoleEntity);
expect(roleItem.entity).toEqual(mockRoleEntity);
expect(roleItem.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 () => {
(getRoleList as jest.Mock).mockRejectedValue(new Error('网络错误'));
await expect(getRoleList({ projectId: 'project1' })).rejects.toThrow('网络错误');
});
it('API返回失败状态时应该正确处理', async () => {
(getRoleList as jest.Mock).mockResolvedValue({
successful: false,
message: '服务器错误',
});
const result = await getRoleList({ projectId: 'project1' });
expect(result.successful).toBe(false);
expect(result.message).toBe('服务器错误');
});
});
});