diff --git a/tests-ui/tests/composables/useServerLogs.test.ts b/tests-ui/tests/composables/useServerLogs.test.ts index 3af4f0faa..3a761fd91 100644 --- a/tests-ui/tests/composables/useServerLogs.test.ts +++ b/tests-ui/tests/composables/useServerLogs.test.ts @@ -24,22 +24,22 @@ describe('useServerLogs', () => { }) it('should initialize with empty logs array', () => { - const { logs } = useServerLogs() + const { logs } = useServerLogs({ ui_id: 'test-ui-id' }) expect(logs.value).toEqual([]) }) it('should not subscribe to logs by default', () => { - useServerLogs() + useServerLogs({ ui_id: 'test-ui-id' }) expect(api.subscribeLogs).not.toHaveBeenCalled() }) it('should subscribe to logs when immediate is true', () => { - useServerLogs({ immediate: true }) + useServerLogs({ ui_id: 'test-ui-id', immediate: true }) expect(api.subscribeLogs).toHaveBeenCalledWith(true) }) it('should start listening when startListening is called', async () => { - const { startListening } = useServerLogs() + const { startListening } = useServerLogs({ ui_id: 'test-ui-id' }) await startListening() @@ -47,7 +47,9 @@ describe('useServerLogs', () => { }) it('should stop listening when stopListening is called', async () => { - const { startListening, stopListening } = useServerLogs() + const { startListening, stopListening } = useServerLogs({ + ui_id: 'test-ui-id' + }) await startListening() await stopListening() @@ -56,7 +58,7 @@ describe('useServerLogs', () => { }) it('should register event listener when starting', async () => { - const { startListening } = useServerLogs() + const { startListening } = useServerLogs({ ui_id: 'test-ui-id' }) await startListening() @@ -68,7 +70,7 @@ describe('useServerLogs', () => { }) it('should handle log messages correctly', async () => { - const { logs, startListening } = useServerLogs() + const { logs, startListening } = useServerLogs({ ui_id: 'test-ui-id' }) await startListening() @@ -93,6 +95,7 @@ describe('useServerLogs', () => { it('should use the message filter if provided', async () => { const { logs, startListening } = useServerLogs({ + ui_id: 'test-ui-id', messageFilter: (msg) => msg !== 'remove me' }) diff --git a/tests-ui/tests/composables/widgets/useManagerQueue.test.ts b/tests-ui/tests/composables/widgets/useManagerQueue.test.ts index 7fce2b5e1..81d8a35f3 100644 --- a/tests-ui/tests/composables/widgets/useManagerQueue.test.ts +++ b/tests-ui/tests/composables/widgets/useManagerQueue.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { nextTick } from 'vue' +import { nextTick, ref } from 'vue' import { useManagerQueue } from '@/composables/useManagerQueue' import { api } from '@/scripts/api' @@ -12,32 +12,39 @@ vi.mock('@/scripts/api', () => ({ } })) +vi.mock('@/services/comfyManagerService', () => ({ + useComfyManagerService: vi.fn(() => ({ + getTaskQueue: vi.fn().mockResolvedValue({ + queue_running: [], + queue_pending: [] + }), + getTaskHistory: vi.fn().mockResolvedValue({}), + clearTaskHistory: vi.fn().mockResolvedValue(null), + deleteTaskHistoryItems: vi.fn().mockResolvedValue(null) + })) +})) + +vi.mock('@/services/dialogService', () => ({ + useDialogService: vi.fn(() => ({ + showManagerProgressDialog: vi.fn() + })) +})) + describe('useManagerQueue', () => { - const createMockTask = (result: any = 'result') => ({ - task: vi.fn().mockResolvedValue(result), - onComplete: vi.fn() - }) - - const createQueueWithMockTask = () => { - const queue = useManagerQueue() - const mockTask = createMockTask() - queue.enqueueTask(mockTask) - return { queue, mockTask } - } - - const getEventListenerCallback = () => - vi.mocked(api.addEventListener).mock.calls[0][1] - - const simulateServerStatus = async (status: 'all-done' | 'in_progress') => { - const event = new CustomEvent('cm-queue-status', { - detail: { status } - }) - getEventListenerCallback()!(event as any) - await nextTick() - } + let taskHistory: any + let taskQueue: any + let installedPacks: any beforeEach(() => { vi.clearAllMocks() + taskHistory = ref({}) + taskQueue = ref({ + history: {}, + running_queue: [], + pending_queue: [], + installed_packs: {} + }) + installedPacks = ref({}) }) afterEach(() => { @@ -46,284 +53,182 @@ describe('useManagerQueue', () => { describe('initialization', () => { it('should initialize with empty queue and DONE status', () => { - const queue = useManagerQueue() + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) expect(queue.queueLength.value).toBe(0) - expect(queue.statusMessage.value).toBe('all-done') expect(queue.allTasksDone.value).toBe(true) }) + + it('should set up event listeners on creation', () => { + useManagerQueue(taskHistory, taskQueue, installedPacks) + + expect(api.addEventListener).toHaveBeenCalled() + }) }) - describe('queue management', () => { - it('should add tasks to the queue', () => { - const queue = useManagerQueue() - const mockTask = createMockTask() + describe('processing state handling', () => { + it('should update processing state based on queue length', async () => { + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) - queue.enqueueTask(mockTask) + // Initially empty queue + expect(queue.isProcessing.value).toBe(false) + expect(queue.allTasksDone.value).toBe(true) - expect(queue.queueLength.value).toBe(1) + // Add tasks to queue + taskQueue.value.running_queue = [{ id: 'task1' } as any] + taskQueue.value.pending_queue = [{ id: 'task2' } as any] + + // Force reactivity update + await nextTick() + + expect(queue.queueLength.value).toBe(2) + }) + }) + + describe('task state management', () => { + it('should reflect task queue state changes', async () => { + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) + + // Add running tasks + taskQueue.value.running_queue = [{ id: 'task1' } as any] + taskQueue.value.pending_queue = [{ id: 'task2' } as any] + + await nextTick() + + expect(queue.queueLength.value).toBe(2) expect(queue.allTasksDone.value).toBe(false) }) - it('should clear the queue when clearQueue is called', () => { - const queue = useManagerQueue() + it('should handle empty queue state', async () => { + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) - // Add some tasks - queue.enqueueTask(createMockTask()) - queue.enqueueTask(createMockTask()) + taskQueue.value.running_queue = [] + taskQueue.value.pending_queue = [] - expect(queue.queueLength.value).toBe(2) - - // Clear the queue - queue.clearQueue() + await nextTick() expect(queue.queueLength.value).toBe(0) expect(queue.allTasksDone.value).toBe(true) }) }) - describe('server status handling', () => { - it('should update server status when receiving websocket events', async () => { - const queue = useManagerQueue() + describe('queue data management', () => { + it('should provide access to task queue state', async () => { + taskQueue.value.running_queue = [{ id: 'task1' } as any] + taskQueue.value.pending_queue = [ + { id: 'task2' }, + { id: 'task3' } + ] as any[] - await simulateServerStatus('in_progress') - - expect(queue.statusMessage.value).toBe('in_progress') - expect(queue.allTasksDone.value).toBe(false) - }) - - it('should handle invalid status values gracefully', async () => { - const queue = useManagerQueue() - - // Simulate an invalid status - const event = new CustomEvent('cm-queue-status', { - detail: null as any - }) - - getEventListenerCallback()!(event) + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) await nextTick() - // Should maintain the default status - expect(queue.statusMessage.value).toBe('all-done') - }) - - it('should handle missing status property gracefully', async () => { - const queue = useManagerQueue() - - // Simulate a detail object without status property - const event = new CustomEvent('cm-queue-status', { - detail: { someOtherProperty: 'value' } as any - }) - - getEventListenerCallback()!(event) - await nextTick() - - // Should maintain the default status - expect(queue.statusMessage.value).toBe('all-done') - }) - }) - - describe('task execution', () => { - it('should start the next task when server is idle and queue has items', async () => { - const { queue, mockTask } = createQueueWithMockTask() - - await simulateServerStatus('all-done') - - // Task should have been started - expect(mockTask.task).toHaveBeenCalled() - expect(queue.queueLength.value).toBe(0) - }) - - it('should execute onComplete callback when task completes and server becomes idle', async () => { - const { mockTask } = createQueueWithMockTask() - - // Start the task - await simulateServerStatus('all-done') - expect(mockTask.task).toHaveBeenCalled() - - // Simulate task completion - await mockTask.task.mock.results[0].value - - // Simulate server cycle (in_progress -> done) - await simulateServerStatus('in_progress') - expect(mockTask.onComplete).not.toHaveBeenCalled() - - await simulateServerStatus('all-done') - expect(mockTask.onComplete).toHaveBeenCalled() - }) - - it('should handle tasks without onComplete callback', async () => { - const queue = useManagerQueue() - const mockTask = { task: vi.fn().mockResolvedValue('result') } - - queue.enqueueTask(mockTask) - - // Start the task - await simulateServerStatus('all-done') - expect(mockTask.task).toHaveBeenCalled() - - // Simulate task completion - await mockTask.task.mock.results[0].value - - // Simulate server cycle - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - - // Should not throw errors even without onComplete - expect(queue.allTasksDone.value).toBe(true) - }) - - it('should process multiple tasks in sequence', async () => { - const queue = useManagerQueue() - const mockTask1 = createMockTask('result1') - const mockTask2 = createMockTask('result2') - - // Add tasks to the queue - queue.enqueueTask(mockTask1) - queue.enqueueTask(mockTask2) - expect(queue.queueLength.value).toBe(2) - - // Process first task - await simulateServerStatus('all-done') - expect(mockTask1.task).toHaveBeenCalled() - expect(queue.queueLength.value).toBe(1) - - // Complete first task - await mockTask1.task.mock.results[0].value - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - expect(mockTask1.onComplete).toHaveBeenCalled() - - // Process second task - expect(mockTask2.task).toHaveBeenCalled() - expect(queue.queueLength.value).toBe(0) - - // Complete second task - await mockTask2.task.mock.results[0].value - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - expect(mockTask2.onComplete).toHaveBeenCalled() - - // Queue should be empty and all tasks done - expect(queue.queueLength.value).toBe(0) - expect(queue.allTasksDone.value).toBe(true) - }) - - it('should handle task that returns rejected promise', async () => { - const queue = useManagerQueue() - const mockTask = { - task: vi.fn().mockRejectedValue(new Error('Task failed')), - onComplete: vi.fn() - } - - queue.enqueueTask(mockTask) - - // Start the task - await simulateServerStatus('all-done') - expect(mockTask.task).toHaveBeenCalled() - - // Let the promise rejection happen - try { - await mockTask.task() - } catch (e) { - // Ignore the error - } - - // Simulate server cycle - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - - // onComplete should still be called for failed tasks - expect(mockTask.onComplete).toHaveBeenCalled() - }) - - it('should handle multiple multiple tasks enqueued at once while server busy', async () => { - const queue = useManagerQueue() - const mockTask1 = createMockTask() - const mockTask2 = createMockTask() - const mockTask3 = createMockTask() - - // Three tasks enqueued at once - await simulateServerStatus('in_progress') - await Promise.all([ - queue.enqueueTask(mockTask1), - queue.enqueueTask(mockTask2), - queue.enqueueTask(mockTask3) + expect(queue.taskQueue.value.running_queue).toEqual([{ id: 'task1' }]) + expect(queue.taskQueue.value.pending_queue).toEqual([ + { id: 'task2' }, + { id: 'task3' } ]) + expect(queue.queueLength.value).toBe(3) + }) - // Task 1 - await simulateServerStatus('all-done') - expect(mockTask1.task).toHaveBeenCalled() + it('should provide access to task history', async () => { + const mockHistory = { + task1: { result: 'success', timestamp: '2023-01-01' }, + task2: { result: 'error', timestamp: '2023-01-02' } + } + taskHistory.value = mockHistory as any - // Verify state of onComplete callbacks - expect(mockTask1.onComplete).toHaveBeenCalled() - expect(mockTask2.onComplete).not.toHaveBeenCalled() - expect(mockTask3.onComplete).not.toHaveBeenCalled() + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) + await nextTick() - // Verify state of queue - expect(queue.queueLength.value).toBe(2) - expect(queue.allTasksDone.value).toBe(false) + expect(queue.taskHistory.value).toEqual(mockHistory) + expect(queue.historyCount.value).toBe(2) + }) - // Task 2 - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - expect(mockTask2.task).toHaveBeenCalled() + it('should handle empty state gracefully', async () => { + taskQueue.value.running_queue = [] + taskQueue.value.pending_queue = [] + taskHistory.value = {} - // Verify state of onComplete callbacks - expect(mockTask2.onComplete).toHaveBeenCalled() - expect(mockTask3.onComplete).not.toHaveBeenCalled() + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) + await nextTick() - // Verify state of queue - expect(queue.queueLength.value).toBe(1) - expect(queue.allTasksDone.value).toBe(false) - - // Task 3 - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - - // Verify state of onComplete callbacks - expect(mockTask3.task).toHaveBeenCalled() - expect(mockTask3.onComplete).toHaveBeenCalled() - - // Verify state of queue expect(queue.queueLength.value).toBe(0) + expect(queue.historyCount.value).toBe(0) + }) + }) + + describe('state management', () => { + it('should provide reactive task history', async () => { + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) + + taskHistory.value = { + task1: { result: 'success' } as any, + task2: { result: 'error' } as any + } + + await nextTick() + + expect(queue.taskHistory.value).toEqual({ + task1: { result: 'success' }, + task2: { result: 'error' } + }) + expect(queue.historyCount.value).toBe(2) + }) + + it('should provide reactive installed packs', async () => { + installedPacks.value = { + pack1: { version: '1.0' }, + pack2: { version: '2.0' } + } + + await nextTick() + + // The composable should have access to installedPacks through the parameter + expect(installedPacks.value).toEqual({ + pack1: { version: '1.0' }, + pack2: { version: '2.0' } + }) + }) + }) + + describe('computed properties', () => { + it('should correctly compute allTasksDone', async () => { + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) + + // Empty queue = all done + expect(queue.allTasksDone.value).toBe(true) + + // Add pending tasks + taskQueue.value.pending_queue = [{ id: 'task1' } as any] + + await nextTick() + + expect(queue.allTasksDone.value).toBe(false) + + // Clear queue + taskQueue.value.running_queue = [] + taskQueue.value.pending_queue = [] + + await nextTick() + expect(queue.allTasksDone.value).toBe(true) }) - it('should handle adding tasks while processing is in progress', async () => { - const queue = useManagerQueue() - const mockTask1 = createMockTask() - const mockTask2 = createMockTask() + it('should correctly compute queueLength', async () => { + const queue = useManagerQueue(taskHistory, taskQueue, installedPacks) - // Add first task and start processing - queue.enqueueTask(mockTask1) - await simulateServerStatus('all-done') - expect(mockTask1.task).toHaveBeenCalled() + expect(queue.queueLength.value).toBe(0) - // Add second task while first is processing - queue.enqueueTask(mockTask2) - expect(queue.queueLength.value).toBe(1) + taskQueue.value.running_queue = [{ id: 'task1' } as any] + taskQueue.value.pending_queue = [ + { id: 'task2' } as any, + { id: 'task3' } as any + ] - // Complete first task - await mockTask1.task.mock.results[0].value - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') + await nextTick() - // Second task should now be processed - expect(mockTask2.task).toHaveBeenCalled() - }) - - it('should handle server status changes without tasks in queue', async () => { - const queue = useManagerQueue() - - // Cycle server status without any tasks - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - await simulateServerStatus('in_progress') - await simulateServerStatus('all-done') - - // Should not cause any errors - expect(queue.allTasksDone.value).toBe(true) + expect(queue.queueLength.value).toBe(3) }) }) }) diff --git a/tests-ui/tests/store/comfyManagerStore.test.ts b/tests-ui/tests/store/comfyManagerStore.test.ts index 41ead3532..9556d6c05 100644 --- a/tests-ui/tests/store/comfyManagerStore.test.ts +++ b/tests-ui/tests/store/comfyManagerStore.test.ts @@ -4,10 +4,10 @@ import { nextTick, ref } from 'vue' import { useComfyManagerService } from '@/services/comfyManagerService' import { useComfyManagerStore } from '@/stores/comfyManagerStore' -import { - InstalledPacksResponse, - ManagerPackInstalled -} from '@/types/comfyManagerTypes' +import { components } from '@/types/generatedManagerTypes' + +type InstalledPacksResponse = components['schemas']['InstalledPacksResponse'] +type ManagerPackInstalled = components['schemas']['ManagerPackInstalled'] vi.mock('@/services/comfyManagerService', () => ({ useComfyManagerService: vi.fn()