[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:
bymyself
2025-06-13 14:00:10 -07:00
parent 9d028a4c53
commit 8df4a4acfc
3 changed files with 183 additions and 275 deletions

View File

@@ -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'
})

View File

@@ -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)
})
})
})

View File

@@ -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()