mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-07 08:30:06 +00:00
* move ref initialization to the component * remove redundant init * [refactor] Move minimap to domain-driven renderer structure - Create new src/renderer/extensions/minimap/ structure following domain-driven design - Add composables: useMinimapGraph, useMinimapViewport, useMinimapRenderer, useMinimapInteraction, useMinimapSettings - Add minimapCanvasRenderer with efficient batched rendering - Add comprehensive type definitions in types.ts - Remove old src/composables/useMinimap.ts composable - Implement proper separation of concerns with dedicated composables for each domain The new structure provides cleaner APIs, better performance through batched rendering, and improved maintainability through domain separation. * [test] Fix minimap tests for new renderer structure - Update all test imports to use new renderer paths - Fix mock implementations to match new composable APIs - Add proper RAF mocking for throttled functions - Fix type assertions to handle strict TypeScript checks - Update test expectations for new implementation behavior - Fix viewport transform calculations in tests - Handle async/throttled behavior correctly in tests All 28 minimap tests now passing with new architecture. * [fix] Remove unused init import in MiniMap component * [refactor] Move useWorkflowThumbnail to renderer/thumbnail structure - Moved useWorkflowThumbnail from src/composables to src/renderer/thumbnail/composables - Updated all imports in components, stores and services - Moved test file to match new structure - This ensures all rendering-related composables live in the renderer directory * [test] Fix minimap canvas renderer test for connections - Fixed mock setup for graph links to match LiteGraph's hybrid Map/Object structure - LiteGraph expects links to be accessible both as a Map and as an object - Test now properly verifies connection rendering functionality
268 lines
7.1 KiB
TypeScript
268 lines
7.1 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { ref } from 'vue'
|
|
|
|
import type { LGraph } from '@/lib/litegraph/src/litegraph'
|
|
import { useMinimapRenderer } from '@/renderer/extensions/minimap/composables/useMinimapRenderer'
|
|
import { renderMinimapToCanvas } from '@/renderer/extensions/minimap/minimapCanvasRenderer'
|
|
import type { UpdateFlags } from '@/renderer/extensions/minimap/types'
|
|
|
|
vi.mock('@/renderer/extensions/minimap/minimapCanvasRenderer', () => ({
|
|
renderMinimapToCanvas: vi.fn()
|
|
}))
|
|
|
|
describe('useMinimapRenderer', () => {
|
|
let mockCanvas: HTMLCanvasElement
|
|
let mockContext: CanvasRenderingContext2D
|
|
let mockGraph: LGraph
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
|
|
mockContext = {
|
|
clearRect: vi.fn()
|
|
} as any
|
|
|
|
mockCanvas = {
|
|
getContext: vi.fn().mockReturnValue(mockContext)
|
|
} as any
|
|
|
|
mockGraph = {
|
|
_nodes: [{ id: '1', pos: [0, 0], size: [100, 100] }]
|
|
} as any
|
|
})
|
|
|
|
it('should initialize with full redraw needed', () => {
|
|
const canvasRef = ref(mockCanvas)
|
|
const graphRef = ref(mockGraph as any)
|
|
const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 })
|
|
const scaleRef = ref(1)
|
|
const updateFlagsRef = ref<UpdateFlags>({
|
|
bounds: false,
|
|
nodes: false,
|
|
connections: false,
|
|
viewport: false
|
|
})
|
|
const settings = {
|
|
nodeColors: ref(true),
|
|
showLinks: ref(true),
|
|
showGroups: ref(true),
|
|
renderBypass: ref(false),
|
|
renderError: ref(false)
|
|
}
|
|
|
|
const renderer = useMinimapRenderer(
|
|
canvasRef,
|
|
graphRef,
|
|
boundsRef,
|
|
scaleRef,
|
|
updateFlagsRef,
|
|
settings,
|
|
250,
|
|
200
|
|
)
|
|
|
|
expect(renderer.needsFullRedraw.value).toBe(true)
|
|
expect(renderer.needsBoundsUpdate.value).toBe(true)
|
|
})
|
|
|
|
it('should handle empty graph with fast path', () => {
|
|
const emptyGraph = { _nodes: [] } as any
|
|
const canvasRef = ref(mockCanvas)
|
|
const graphRef = ref(emptyGraph)
|
|
const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 })
|
|
const scaleRef = ref(1)
|
|
const updateFlagsRef = ref<UpdateFlags>({
|
|
bounds: false,
|
|
nodes: false,
|
|
connections: false,
|
|
viewport: false
|
|
})
|
|
const settings = {
|
|
nodeColors: ref(true),
|
|
showLinks: ref(true),
|
|
showGroups: ref(true),
|
|
renderBypass: ref(false),
|
|
renderError: ref(false)
|
|
}
|
|
|
|
const renderer = useMinimapRenderer(
|
|
canvasRef,
|
|
graphRef,
|
|
boundsRef,
|
|
scaleRef,
|
|
updateFlagsRef,
|
|
settings,
|
|
250,
|
|
200
|
|
)
|
|
|
|
renderer.renderMinimap()
|
|
|
|
expect(mockContext.clearRect).toHaveBeenCalledWith(0, 0, 250, 200)
|
|
expect(vi.mocked(renderMinimapToCanvas)).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should only render when redraw is needed', async () => {
|
|
const { renderMinimapToCanvas } = await import(
|
|
'@/renderer/extensions/minimap/minimapCanvasRenderer'
|
|
)
|
|
const canvasRef = ref(mockCanvas)
|
|
const graphRef = ref(mockGraph as any)
|
|
const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 })
|
|
const scaleRef = ref(1)
|
|
const updateFlagsRef = ref<UpdateFlags>({
|
|
bounds: false,
|
|
nodes: false,
|
|
connections: false,
|
|
viewport: false
|
|
})
|
|
const settings = {
|
|
nodeColors: ref(true),
|
|
showLinks: ref(true),
|
|
showGroups: ref(true),
|
|
renderBypass: ref(false),
|
|
renderError: ref(false)
|
|
}
|
|
|
|
const renderer = useMinimapRenderer(
|
|
canvasRef,
|
|
graphRef,
|
|
boundsRef,
|
|
scaleRef,
|
|
updateFlagsRef,
|
|
settings,
|
|
250,
|
|
200
|
|
)
|
|
|
|
// First render (needsFullRedraw is true by default)
|
|
renderer.renderMinimap()
|
|
expect(vi.mocked(renderMinimapToCanvas)).toHaveBeenCalledTimes(1)
|
|
|
|
// Second render without changes (should not render)
|
|
renderer.renderMinimap()
|
|
expect(vi.mocked(renderMinimapToCanvas)).toHaveBeenCalledTimes(1)
|
|
|
|
// Set update flag and render again
|
|
updateFlagsRef.value.nodes = true
|
|
renderer.renderMinimap()
|
|
expect(vi.mocked(renderMinimapToCanvas)).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('should update minimap with bounds and viewport callbacks', () => {
|
|
const updateBounds = vi.fn()
|
|
const updateViewport = vi.fn()
|
|
|
|
const canvasRef = ref(mockCanvas)
|
|
const graphRef = ref(mockGraph as any)
|
|
const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 })
|
|
const scaleRef = ref(1)
|
|
const updateFlagsRef = ref<UpdateFlags>({
|
|
bounds: true,
|
|
nodes: false,
|
|
connections: false,
|
|
viewport: false
|
|
})
|
|
const settings = {
|
|
nodeColors: ref(true),
|
|
showLinks: ref(true),
|
|
showGroups: ref(true),
|
|
renderBypass: ref(false),
|
|
renderError: ref(false)
|
|
}
|
|
|
|
const renderer = useMinimapRenderer(
|
|
canvasRef,
|
|
graphRef,
|
|
boundsRef,
|
|
scaleRef,
|
|
updateFlagsRef,
|
|
settings,
|
|
250,
|
|
200
|
|
)
|
|
|
|
renderer.updateMinimap(updateBounds, updateViewport)
|
|
|
|
expect(updateBounds).toHaveBeenCalled()
|
|
expect(updateViewport).toHaveBeenCalled()
|
|
expect(updateFlagsRef.value.bounds).toBe(false)
|
|
expect(renderer.needsFullRedraw.value).toBe(false) // After rendering, needsFullRedraw is reset to false
|
|
expect(updateFlagsRef.value.viewport).toBe(false) // After updating viewport, this is reset to false
|
|
})
|
|
|
|
it('should force full redraw when requested', () => {
|
|
const canvasRef = ref(mockCanvas)
|
|
const graphRef = ref(mockGraph as any)
|
|
const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 })
|
|
const scaleRef = ref(1)
|
|
const updateFlagsRef = ref<UpdateFlags>({
|
|
bounds: false,
|
|
nodes: false,
|
|
connections: false,
|
|
viewport: false
|
|
})
|
|
const settings = {
|
|
nodeColors: ref(true),
|
|
showLinks: ref(true),
|
|
showGroups: ref(true),
|
|
renderBypass: ref(false),
|
|
renderError: ref(false)
|
|
}
|
|
|
|
const renderer = useMinimapRenderer(
|
|
canvasRef,
|
|
graphRef,
|
|
boundsRef,
|
|
scaleRef,
|
|
updateFlagsRef,
|
|
settings,
|
|
250,
|
|
200
|
|
)
|
|
|
|
renderer.forceFullRedraw()
|
|
|
|
expect(renderer.needsFullRedraw.value).toBe(true)
|
|
expect(updateFlagsRef.value.bounds).toBe(true)
|
|
expect(updateFlagsRef.value.nodes).toBe(true)
|
|
expect(updateFlagsRef.value.connections).toBe(true)
|
|
expect(updateFlagsRef.value.viewport).toBe(true)
|
|
})
|
|
|
|
it('should handle null canvas gracefully', () => {
|
|
const canvasRef = ref<HTMLCanvasElement | undefined>(undefined)
|
|
const graphRef = ref(mockGraph as any)
|
|
const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 })
|
|
const scaleRef = ref(1)
|
|
const updateFlagsRef = ref<UpdateFlags>({
|
|
bounds: false,
|
|
nodes: false,
|
|
connections: false,
|
|
viewport: false
|
|
})
|
|
const settings = {
|
|
nodeColors: ref(true),
|
|
showLinks: ref(true),
|
|
showGroups: ref(true),
|
|
renderBypass: ref(false),
|
|
renderError: ref(false)
|
|
}
|
|
|
|
const renderer = useMinimapRenderer(
|
|
canvasRef,
|
|
graphRef,
|
|
boundsRef,
|
|
scaleRef,
|
|
updateFlagsRef,
|
|
settings,
|
|
250,
|
|
200
|
|
)
|
|
|
|
// Should not throw
|
|
expect(() => renderer.renderMinimap()).not.toThrow()
|
|
expect(mockCanvas.getContext).not.toHaveBeenCalled()
|
|
})
|
|
})
|