diff --git a/apps/desktop/src/components/__tests__/EnhancedChatMessageV2.test.tsx b/apps/desktop/src/components/__tests__/EnhancedChatMessageV2.test.tsx deleted file mode 100644 index 0f9bb2e..0000000 --- a/apps/desktop/src/components/__tests__/EnhancedChatMessageV2.test.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import { render, screen, fireEvent } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import { describe, test, expect, vi } from 'vitest'; -import { EnhancedChatMessageV2 } from '../EnhancedChatMessageV2'; - -// Mock 数据 -const mockUserMessage = { - id: '1', - type: 'user' as const, - content: '请推荐一些夏日穿搭', - timestamp: new Date('2024-01-01T10:00:00Z'), - status: 'sent' as const -}; - -const mockAssistantMessage = { - id: '2', - type: 'assistant' as const, - content: '夏日穿搭建议:选择轻薄透气的面料,如棉麻材质。推荐搭配清爽的色彩,如白色、浅蓝色等。', - timestamp: new Date('2024-01-01T10:01:00Z'), - status: 'sent' as const, - metadata: { - responseTime: 1500, - modelUsed: 'gemini-pro', - sources: [ - { - title: '夏日穿搭指南', - uri: 'https://example.com/summer-style.jpg', - content: { - type: 'image', - image_url: 'https://example.com/summer-style.jpg', - description: '清爽夏日穿搭示例' - } - } - ], - grounding_metadata: { - grounding_supports: [ - { - start_index: 0, - end_index: 20, - grounding_chunk_indices: [0] - } - ], - sources: [ - { - chunk_index: 0, - title: '夏日穿搭指南', - uri: 'https://example.com/summer-style.jpg', - content: { - type: 'image', - image_url: 'https://example.com/summer-style.jpg', - description: '清爽夏日穿搭示例' - } - } - ] - } - } -}; - -describe('EnhancedChatMessageV2', () => { - test('渲染用户消息', () => { - render(); - - expect(screen.getByText('请推荐一些夏日穿搭')).toBeInTheDocument(); - expect(screen.getByText('10:00')).toBeInTheDocument(); - }); - - test('渲染助手消息', () => { - render(); - - expect(screen.getByText(/夏日穿搭建议/)).toBeInTheDocument(); - expect(screen.getByText('10:01')).toBeInTheDocument(); - expect(screen.getByText('• 响应时间: 1500ms')).toBeInTheDocument(); - expect(screen.getByText('• gemini-pro')).toBeInTheDocument(); - }); - - test('显示素材来源', () => { - render( - - ); - - expect(screen.getByText('相关素材 (1)')).toBeInTheDocument(); - }); - - test('复制消息功能', async () => { - // Mock clipboard API - const mockWriteText = vi.fn().mockImplementation(() => Promise.resolve()); - Object.assign(navigator, { - clipboard: { - writeText: mockWriteText, - }, - }); - - render(); - - const copyButton = screen.getByTitle('复制消息'); - fireEvent.click(copyButton); - - expect(mockWriteText).toHaveBeenCalledWith('请推荐一些夏日穿搭'); - }); - - test('展开/收起素材来源', () => { - render( - - ); - - // 检查是否显示了素材来源标题 - expect(screen.getByText('相关素材 (1)')).toBeInTheDocument(); - }); - - test('角标引用功能', () => { - render( - - ); - - // 检查是否渲染了消息内容 - expect(screen.getByText(/夏日穿搭建议/)).toBeInTheDocument(); - }); - - test('发送中状态显示', () => { - const sendingMessage = { - ...mockUserMessage, - status: 'sending' as const - }; - - render(); - - expect(screen.getByText('发送中...')).toBeInTheDocument(); - }); -}); diff --git a/apps/desktop/src/components/__tests__/ProjectCard.test.tsx b/apps/desktop/src/components/__tests__/ProjectCard.test.tsx deleted file mode 100644 index 2466808..0000000 --- a/apps/desktop/src/components/__tests__/ProjectCard.test.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/react'; -import { ProjectCard } from '../ProjectCard'; -import { Project } from '../../types/project'; - -// Mock date-fns -vi.mock('date-fns', () => ({ - formatDistanceToNow: vi.fn(() => '2 天前'), -})); - -vi.mock('date-fns/locale', () => ({ - zhCN: {}, -})); - -const mockProject: Project = { - id: '1', - name: 'Test Project', - path: '/path/to/project', - description: 'Test description', - created_at: '2023-01-01T00:00:00Z', - updated_at: '2023-01-02T00:00:00Z', - is_active: true, -}; - -const mockProps = { - project: mockProject, - onOpen: vi.fn(), - onEdit: vi.fn(), - onDelete: vi.fn(), -}; - -describe('ProjectCard', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it('renders project information correctly', () => { - render(); - - expect(screen.getByText('Test Project')).toBeInTheDocument(); - expect(screen.getByText('Test description')).toBeInTheDocument(); - expect(screen.getByText('project')).toBeInTheDocument(); - expect(screen.getByText('2 天前')).toBeInTheDocument(); - }); - - it('calls onOpen when open button is clicked', () => { - render(); - - const openButton = screen.getByText('打开'); - fireEvent.click(openButton); - - expect(mockProps.onOpen).toHaveBeenCalledWith(mockProject); - }); - - it('calls onEdit when edit button is clicked', () => { - render(); - - const editButton = screen.getByText('编辑'); - fireEvent.click(editButton); - - expect(mockProps.onEdit).toHaveBeenCalledWith(mockProject); - }); - - it('renders without description', () => { - const projectWithoutDescription = { ...mockProject, description: undefined }; - render(); - - expect(screen.getByText('Test Project')).toBeInTheDocument(); - expect(screen.queryByText('Test description')).not.toBeInTheDocument(); - }); - - it('shows menu when more button is clicked', () => { - render(); - - // 找到更多按钮并点击 - 使用更通用的选择器 - const moreButtons = screen.getAllByRole('button'); - const moreButton = moreButtons.find(button => - button.querySelector('svg') && !button.textContent?.includes('编辑') && !button.textContent?.includes('打开') - ); - - if (moreButton) { - fireEvent.click(moreButton); - - // 检查菜单项是否显示 - expect(screen.getByText('打开项目')).toBeInTheDocument(); - expect(screen.getAllByText('编辑')).toHaveLength(2); // 一个在菜单中,一个在按钮中 - expect(screen.getByText('删除')).toBeInTheDocument(); - } - }); - - it('calls onDelete when delete menu item is clicked', () => { - render(); - - // 打开菜单 - const moreButtons = screen.getAllByRole('button'); - const moreButton = moreButtons.find(button => - button.querySelector('svg') && !button.textContent?.includes('编辑') && !button.textContent?.includes('打开') - ); - - if (moreButton) { - fireEvent.click(moreButton); - - // 点击删除 - const deleteButton = screen.getByText('删除'); - fireEvent.click(deleteButton); - - expect(mockProps.onDelete).toHaveBeenCalledWith(mockProject.id); - } - }); - - it('extracts directory name correctly', () => { - const projectWithWindowsPath = { - ...mockProject, - path: 'C:\\Users\\test\\MyProject', - }; - - render(); - expect(screen.getByText('MyProject')).toBeInTheDocument(); - }); -}); diff --git a/apps/desktop/src/components/__tests__/TaskCard.test.tsx b/apps/desktop/src/components/__tests__/TaskCard.test.tsx deleted file mode 100644 index 4a8b056..0000000 --- a/apps/desktop/src/components/__tests__/TaskCard.test.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import TaskCard from '../TaskCard'; -import { TaskDetail } from '../../types/uniComfyui'; - -// Mock the service -jest.mock('../../services/uniComfyuiService', () => ({ - UniComfyUIService: { - formatTaskStatus: jest.fn((status: string) => ({ - text: status === 'completed' ? '已完成' : '执行中', - color: status === 'completed' ? 'text-green-600' : 'text-blue-600' - })), - getTaskStatusIcon: jest.fn(() => '✅'), - formatTaskExecutionTime: jest.fn(() => '2分钟'), - formatFileSize: jest.fn(() => '1.2 MB'), - isImageFile: jest.fn(() => true), - isVideoFile: jest.fn(() => false), - generatePreviewUrl: jest.fn(() => '/test-image.jpg') - } -})); - -const mockTask: TaskDetail = { - id: 1, - workflow_run_id: 'test-task-123', - workflow_name: 'Test Workflow', - task_type: 'single', - status: 'completed', - input_params: {}, - created_at: '2024-01-01T10:00:00Z', - started_at: '2024-01-01T10:01:00Z', - completed_at: '2024-01-01T10:03:00Z', - result_files: [ - { - id: 'file-1', - task_id: 'test-task-123', - file_name: 'result.jpg', - file_path: '/path/to/result.jpg', - file_url: 'http://example.com/result.jpg', - file_type: 'image', - file_size: 1024000, - mime_type: 'image/jpeg', - created_at: '2024-01-01T10:03:00Z', - thumbnail_url: 'http://example.com/thumb.jpg' - } - ] -}; - -describe('TaskCard', () => { - it('renders task information correctly', () => { - render(); - - expect(screen.getByText('Test Workflow')).toBeInTheDocument(); - expect(screen.getByText('ID: test-task-123')).toBeInTheDocument(); - expect(screen.getByText('单个任务')).toBeInTheDocument(); - }); - - it('calls onViewDetail when view button is clicked', () => { - const mockOnViewDetail = jest.fn(); - render(); - - const viewButton = screen.getByTitle('查看详情'); - fireEvent.click(viewButton); - - expect(mockOnViewDetail).toHaveBeenCalledWith(mockTask); - }); - - it('calls onDownload when download button is clicked', () => { - const mockOnDownload = jest.fn(); - render(); - - const downloadButton = screen.getByTitle('下载结果'); - fireEvent.click(downloadButton); - - expect(mockOnDownload).toHaveBeenCalledWith(mockTask); - }); - - it('shows retry button for failed tasks', () => { - const failedTask = { ...mockTask, status: 'failed' as const }; - const mockOnRetry = jest.fn(); - - render(); - - const retryButton = screen.getByTitle('重试任务'); - expect(retryButton).toBeInTheDocument(); - - fireEvent.click(retryButton); - expect(mockOnRetry).toHaveBeenCalledWith(failedTask); - }); - - it('displays error message for failed tasks', () => { - const failedTask = { - ...mockTask, - status: 'failed' as const, - error_message: 'Task execution failed' - }; - - render(); - - expect(screen.getByText('Task execution failed')).toBeInTheDocument(); - }); - - it('renders in compact mode', () => { - render(); - - // In compact mode, the task name should have smaller text - const taskName = screen.getByText('Test Workflow'); - expect(taskName).toHaveClass('text-sm'); - }); - - it('hides actions when showActions is false', () => { - render(); - - expect(screen.queryByTitle('查看详情')).not.toBeInTheDocument(); - expect(screen.queryByTitle('下载结果')).not.toBeInTheDocument(); - }); -});