mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-04 23:20:07 +00:00
[manager] Update tests for new manager API
Updated tests for manager queue composable, server logs composable, and manager store to work with the new API signatures and functionality.
This commit is contained in:
@@ -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'
|
||||
})
|
||||
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user