feat(historyV2): load workflows for images (#6384)

## Summary

Hooked up the "Load Workflow" action to our `history_v2` API.

Note: Our cloud envs were being stress tested right now so images are
loading at time of recording. Images were loading for me during
development before I had time to create the video.


## Screenshots 📷 



https://github.com/user-attachments/assets/02145504-ceae-497b-9049-553796d698da



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6384-Feat-history-v2-workflows-29b6d73d365081bcb706fe799b8ce66a)
by [Unito](https://www.unito.io)
This commit is contained in:
Arjan Singh
2025-10-29 18:35:42 -07:00
committed by GitHub
parent 6f068c87da
commit f2355a6ad1
9 changed files with 384 additions and 64 deletions

View File

@@ -0,0 +1,111 @@
import { describe, expect, it, vi } from 'vitest'
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
import { getWorkflowFromHistory } from '@/platform/workflow/cloud/getWorkflowFromHistory'
const mockWorkflow: ComfyWorkflowJSON = {
id: 'test-workflow-id',
revision: 0,
last_node_id: 5,
last_link_id: 3,
nodes: [],
links: [],
groups: [],
config: {},
extra: {},
version: 0.4
}
const mockHistoryResponse = {
'test-prompt-id': {
prompt: {
priority: 1,
prompt_id: 'test-prompt-id',
extra_data: {
client_id: 'test-client',
extra_pnginfo: {
workflow: mockWorkflow
}
}
},
outputs: {},
status: {
status_str: 'success',
completed: true,
messages: []
}
}
}
describe('getWorkflowFromHistory', () => {
it('should fetch workflow from /history_v2/{prompt_id} endpoint', async () => {
const mockFetchApi = vi.fn().mockResolvedValue({
json: async () => mockHistoryResponse
})
await getWorkflowFromHistory(mockFetchApi, 'test-prompt-id')
expect(mockFetchApi).toHaveBeenCalledWith('/history_v2/test-prompt-id')
})
it('should extract and return workflow from response', async () => {
const mockFetchApi = vi.fn().mockResolvedValue({
json: async () => mockHistoryResponse
})
const result = await getWorkflowFromHistory(mockFetchApi, 'test-prompt-id')
expect(result).toEqual(mockWorkflow)
})
it('should return undefined when prompt_id not found in response', async () => {
const mockFetchApi = vi.fn().mockResolvedValue({
json: async () => ({})
})
const result = await getWorkflowFromHistory(mockFetchApi, 'nonexistent-id')
expect(result).toBeUndefined()
})
it('should return undefined when workflow is missing from extra_pnginfo', async () => {
const mockFetchApi = vi.fn().mockResolvedValue({
json: async () => ({
'test-prompt-id': {
prompt: {
priority: 1,
prompt_id: 'test-prompt-id',
extra_data: {
client_id: 'test-client'
}
},
outputs: {}
}
})
})
const result = await getWorkflowFromHistory(mockFetchApi, 'test-prompt-id')
expect(result).toBeUndefined()
})
it('should handle fetch errors gracefully', async () => {
const mockFetchApi = vi.fn().mockRejectedValue(new Error('Network error'))
const result = await getWorkflowFromHistory(mockFetchApi, 'test-prompt-id')
expect(result).toBeUndefined()
})
it('should handle malformed JSON responses', async () => {
const mockFetchApi = vi.fn().mockResolvedValue({
json: async () => {
throw new Error('Invalid JSON')
}
})
const result = await getWorkflowFromHistory(mockFetchApi, 'test-prompt-id')
expect(result).toBeUndefined()
})
})