mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-20 14:54:12 +00:00
refactor: remove as any from 5 test files (batch 12)
Fixed 31 instances across: - typeGuardUtil.test.ts: Use Parameters utility type for partial mocks - graphTraversalUtil.test.ts: Use proper type assertions for property mutations and invalid input testing - subgraphNavigationStore.viewport.test.ts: Import Subgraph type, fix mock canvas typing - useCanvasManager.test.ts: Use as unknown as Type for mutable mock store properties - useCanvasTools.test.ts: Use as unknown as Type for mutable mock store properties The canvas mock store pattern now uses as unknown as HTMLCanvasElement/CanvasRenderingContext2D at both declaration and assignment points to allow partial mocks while maintaining type safety.
This commit is contained in:
@@ -3,13 +3,13 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { MaskBlendMode } from '@/extensions/core/maskeditor/types'
|
||||
import { useCanvasManager } from '@/composables/maskeditor/useCanvasManager'
|
||||
const mockStore = {
|
||||
imgCanvas: null as any,
|
||||
maskCanvas: null as any,
|
||||
rgbCanvas: null as any,
|
||||
imgCtx: null as any,
|
||||
maskCtx: null as any,
|
||||
rgbCtx: null as any,
|
||||
canvasBackground: null as any,
|
||||
imgCanvas: null as unknown as HTMLCanvasElement,
|
||||
maskCanvas: null as unknown as HTMLCanvasElement,
|
||||
rgbCanvas: null as unknown as HTMLCanvasElement,
|
||||
imgCtx: null as unknown as CanvasRenderingContext2D,
|
||||
maskCtx: null as unknown as CanvasRenderingContext2D,
|
||||
rgbCtx: null as unknown as CanvasRenderingContext2D,
|
||||
canvasBackground: null as unknown as HTMLElement,
|
||||
maskColor: { r: 0, g: 0, b: 0 },
|
||||
maskBlendMode: MaskBlendMode.Black,
|
||||
maskOpacity: 0.8
|
||||
@@ -40,7 +40,7 @@ describe('useCanvasManager', () => {
|
||||
|
||||
mockStore.imgCtx = {
|
||||
drawImage: vi.fn()
|
||||
}
|
||||
} as unknown as CanvasRenderingContext2D
|
||||
|
||||
mockStore.maskCtx = {
|
||||
drawImage: vi.fn(),
|
||||
@@ -48,16 +48,16 @@ describe('useCanvasManager', () => {
|
||||
putImageData: vi.fn(),
|
||||
globalCompositeOperation: 'source-over',
|
||||
fillStyle: ''
|
||||
}
|
||||
} as unknown as CanvasRenderingContext2D
|
||||
|
||||
mockStore.rgbCtx = {
|
||||
drawImage: vi.fn()
|
||||
}
|
||||
} as unknown as CanvasRenderingContext2D
|
||||
|
||||
mockStore.imgCanvas = {
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
} as unknown as HTMLCanvasElement
|
||||
|
||||
mockStore.maskCanvas = {
|
||||
width: 0,
|
||||
@@ -66,18 +66,18 @@ describe('useCanvasManager', () => {
|
||||
mixBlendMode: '',
|
||||
opacity: ''
|
||||
}
|
||||
}
|
||||
} as unknown as HTMLCanvasElement
|
||||
|
||||
mockStore.rgbCanvas = {
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
} as unknown as HTMLCanvasElement
|
||||
|
||||
mockStore.canvasBackground = {
|
||||
style: {
|
||||
backgroundColor: ''
|
||||
}
|
||||
}
|
||||
} as unknown as HTMLElement
|
||||
|
||||
mockStore.maskColor = { r: 0, g: 0, b: 0 }
|
||||
mockStore.maskBlendMode = MaskBlendMode.Black
|
||||
@@ -163,7 +163,7 @@ describe('useCanvasManager', () => {
|
||||
it('should throw error when canvas missing', async () => {
|
||||
const manager = useCanvasManager()
|
||||
|
||||
mockStore.imgCanvas = null
|
||||
mockStore.imgCanvas = null as unknown as HTMLCanvasElement
|
||||
|
||||
const origImage = createMockImage(512, 512)
|
||||
const maskImage = createMockImage(512, 512)
|
||||
@@ -176,7 +176,7 @@ describe('useCanvasManager', () => {
|
||||
it('should throw error when context missing', async () => {
|
||||
const manager = useCanvasManager()
|
||||
|
||||
mockStore.imgCtx = null
|
||||
mockStore.imgCtx = null as unknown as CanvasRenderingContext2D
|
||||
|
||||
const origImage = createMockImage(512, 512)
|
||||
const maskImage = createMockImage(512, 512)
|
||||
@@ -259,7 +259,7 @@ describe('useCanvasManager', () => {
|
||||
it('should return early when canvas missing', async () => {
|
||||
const manager = useCanvasManager()
|
||||
|
||||
mockStore.maskCanvas = null
|
||||
mockStore.maskCanvas = null as unknown as HTMLCanvasElement
|
||||
|
||||
await manager.updateMaskColor()
|
||||
|
||||
@@ -269,7 +269,7 @@ describe('useCanvasManager', () => {
|
||||
it('should return early when context missing', async () => {
|
||||
const manager = useCanvasManager()
|
||||
|
||||
mockStore.maskCtx = null
|
||||
mockStore.maskCtx = null as unknown as CanvasRenderingContext2D
|
||||
|
||||
await manager.updateMaskColor()
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ const mockCanvasHistory = {
|
||||
}
|
||||
|
||||
const mockStore = {
|
||||
maskCtx: null as any,
|
||||
imgCtx: null as any,
|
||||
maskCanvas: null as any,
|
||||
imgCanvas: null as any,
|
||||
rgbCtx: null as any,
|
||||
rgbCanvas: null as any,
|
||||
maskCtx: null as unknown as CanvasRenderingContext2D,
|
||||
imgCtx: null as unknown as CanvasRenderingContext2D,
|
||||
maskCanvas: null as unknown as HTMLCanvasElement,
|
||||
imgCanvas: null as unknown as HTMLCanvasElement,
|
||||
rgbCtx: null as unknown as CanvasRenderingContext2D,
|
||||
rgbCanvas: null as unknown as HTMLCanvasElement,
|
||||
maskColor: { r: 255, g: 255, b: 255 },
|
||||
paintBucketTolerance: 10,
|
||||
fillOpacity: 100,
|
||||
@@ -61,30 +61,30 @@ describe('useCanvasTools', () => {
|
||||
getImageData: vi.fn(() => mockMaskImageData),
|
||||
putImageData: vi.fn(),
|
||||
clearRect: vi.fn()
|
||||
}
|
||||
} as unknown as CanvasRenderingContext2D
|
||||
|
||||
mockStore.imgCtx = {
|
||||
getImageData: vi.fn(() => mockImgImageData)
|
||||
}
|
||||
} as unknown as CanvasRenderingContext2D
|
||||
|
||||
mockStore.rgbCtx = {
|
||||
clearRect: vi.fn()
|
||||
}
|
||||
} as unknown as CanvasRenderingContext2D
|
||||
|
||||
mockStore.maskCanvas = {
|
||||
width: 100,
|
||||
height: 100
|
||||
}
|
||||
} as unknown as HTMLCanvasElement
|
||||
|
||||
mockStore.imgCanvas = {
|
||||
width: 100,
|
||||
height: 100
|
||||
}
|
||||
} as unknown as HTMLCanvasElement
|
||||
|
||||
mockStore.rgbCanvas = {
|
||||
width: 100,
|
||||
height: 100
|
||||
}
|
||||
} as unknown as HTMLCanvasElement
|
||||
|
||||
mockStore.maskColor = { r: 255, g: 255, b: 255 }
|
||||
mockStore.paintBucketTolerance = 10
|
||||
@@ -158,7 +158,7 @@ describe('useCanvasTools', () => {
|
||||
})
|
||||
|
||||
it('should return early when canvas missing', () => {
|
||||
mockStore.maskCanvas = null
|
||||
mockStore.maskCanvas = null as unknown as HTMLCanvasElement
|
||||
|
||||
const tools = useCanvasTools()
|
||||
|
||||
@@ -243,7 +243,7 @@ describe('useCanvasTools', () => {
|
||||
})
|
||||
|
||||
it('should return early when canvas missing', async () => {
|
||||
mockStore.imgCanvas = null
|
||||
mockStore.imgCanvas = null as unknown as HTMLCanvasElement
|
||||
|
||||
const tools = useCanvasTools()
|
||||
|
||||
@@ -363,7 +363,7 @@ describe('useCanvasTools', () => {
|
||||
})
|
||||
|
||||
it('should return early when canvas missing', () => {
|
||||
mockStore.maskCanvas = null
|
||||
mockStore.maskCanvas = null as unknown as HTMLCanvasElement
|
||||
|
||||
const tools = useCanvasTools()
|
||||
|
||||
@@ -373,7 +373,7 @@ describe('useCanvasTools', () => {
|
||||
})
|
||||
|
||||
it('should return early when context missing', () => {
|
||||
mockStore.maskCtx = null
|
||||
mockStore.maskCtx = null as unknown as CanvasRenderingContext2D
|
||||
|
||||
const tools = useCanvasTools()
|
||||
|
||||
@@ -395,7 +395,7 @@ describe('useCanvasTools', () => {
|
||||
})
|
||||
|
||||
it('should handle missing mask canvas', () => {
|
||||
mockStore.maskCanvas = null
|
||||
mockStore.maskCanvas = null as unknown as HTMLCanvasElement
|
||||
|
||||
const tools = useCanvasTools()
|
||||
|
||||
@@ -406,7 +406,7 @@ describe('useCanvasTools', () => {
|
||||
})
|
||||
|
||||
it('should handle missing rgb canvas', () => {
|
||||
mockStore.rgbCanvas = null
|
||||
mockStore.rgbCanvas = null as unknown as HTMLCanvasElement
|
||||
|
||||
const tools = useCanvasTools()
|
||||
|
||||
|
||||
@@ -2,11 +2,14 @@ import { createPinia, setActivePinia } from 'pinia'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
import type { Subgraph } from '@/lib/litegraph/src/litegraph'
|
||||
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
|
||||
import type { ComfyWorkflow } from '@/platform/workflow/management/stores/workflowStore'
|
||||
import { app } from '@/scripts/app'
|
||||
import { useSubgraphNavigationStore } from '@/stores/subgraphNavigationStore'
|
||||
|
||||
const mockSetDirty = vi.fn()
|
||||
|
||||
vi.mock('@/scripts/app', () => {
|
||||
const mockCanvas = {
|
||||
subgraph: null,
|
||||
@@ -18,7 +21,7 @@ vi.mock('@/scripts/app', () => {
|
||||
offset: [0, 0]
|
||||
}
|
||||
},
|
||||
setDirty: vi.fn()
|
||||
setDirty: mockSetDirty
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -37,12 +40,12 @@ vi.mock('@/scripts/app', () => {
|
||||
// Mock canvasStore
|
||||
vi.mock('@/renderer/core/canvas/canvasStore', () => ({
|
||||
useCanvasStore: () => ({
|
||||
getCanvas: () => (app as any).canvas
|
||||
getCanvas: () => app.canvas
|
||||
})
|
||||
}))
|
||||
|
||||
// Get reference to mock canvas
|
||||
const mockCanvas = app.canvas as any
|
||||
const mockCanvas = app.canvas
|
||||
|
||||
describe('useSubgraphNavigationStore - Viewport Persistence', () => {
|
||||
beforeEach(() => {
|
||||
@@ -52,7 +55,7 @@ describe('useSubgraphNavigationStore - Viewport Persistence', () => {
|
||||
mockCanvas.ds.offset = [0, 0]
|
||||
mockCanvas.ds.state.scale = 1
|
||||
mockCanvas.ds.state.offset = [0, 0]
|
||||
mockCanvas.setDirty.mockClear()
|
||||
mockSetDirty.mockClear()
|
||||
})
|
||||
|
||||
describe('saveViewport', () => {
|
||||
@@ -98,7 +101,7 @@ describe('useSubgraphNavigationStore - Viewport Persistence', () => {
|
||||
|
||||
// Mock being in a subgraph
|
||||
const mockSubgraph = { id: 'sub-456' }
|
||||
workflowStore.activeSubgraph = mockSubgraph as any
|
||||
workflowStore.activeSubgraph = mockSubgraph as unknown as Subgraph
|
||||
|
||||
// Set viewport state
|
||||
mockCanvas.ds.state.scale = 3
|
||||
@@ -158,7 +161,7 @@ describe('useSubgraphNavigationStore - Viewport Persistence', () => {
|
||||
// Reset canvas
|
||||
mockCanvas.ds.scale = 1
|
||||
mockCanvas.ds.offset = [0, 0]
|
||||
mockCanvas.setDirty.mockClear()
|
||||
mockSetDirty.mockClear()
|
||||
|
||||
// Try to restore non-existent viewport
|
||||
navigationStore.restoreViewport('non-existent')
|
||||
@@ -166,7 +169,7 @@ describe('useSubgraphNavigationStore - Viewport Persistence', () => {
|
||||
// Canvas should not change
|
||||
expect(mockCanvas.ds.scale).toBe(1)
|
||||
expect(mockCanvas.ds.offset).toEqual([0, 0])
|
||||
expect(mockCanvas.setDirty).not.toHaveBeenCalled()
|
||||
expect(mockSetDirty).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -194,7 +197,7 @@ describe('useSubgraphNavigationStore - Viewport Persistence', () => {
|
||||
mockCanvas.ds.state.offset = [100, 100]
|
||||
|
||||
// Navigate to subgraph
|
||||
workflowStore.activeSubgraph = subgraph1 as any
|
||||
workflowStore.activeSubgraph = subgraph1 as unknown as Subgraph
|
||||
await nextTick()
|
||||
|
||||
// Root viewport should have been saved automatically
|
||||
@@ -239,10 +242,14 @@ describe('useSubgraphNavigationStore - Viewport Persistence', () => {
|
||||
const workflow1 = { path: 'workflow1.json' } as ComfyWorkflow
|
||||
const workflow2 = { path: 'workflow2.json' } as ComfyWorkflow
|
||||
|
||||
workflowStore.activeWorkflow = workflow1 as any
|
||||
workflowStore.activeWorkflow = workflow1 as unknown as ReturnType<
|
||||
typeof useWorkflowStore
|
||||
>['activeWorkflow']
|
||||
await nextTick()
|
||||
|
||||
workflowStore.activeWorkflow = workflow2 as any
|
||||
workflowStore.activeWorkflow = workflow2 as unknown as ReturnType<
|
||||
typeof useWorkflowStore
|
||||
>['activeWorkflow']
|
||||
await nextTick()
|
||||
|
||||
// Cache should be preserved (LRU will manage memory)
|
||||
|
||||
@@ -96,8 +96,8 @@ describe('graphTraversalUtil', () => {
|
||||
|
||||
it('should return null for invalid input', () => {
|
||||
expect(parseExecutionId('')).toBeNull()
|
||||
expect(parseExecutionId(null as any)).toBeNull()
|
||||
expect(parseExecutionId(undefined as any)).toBeNull()
|
||||
expect(parseExecutionId(null as unknown as string)).toBeNull()
|
||||
expect(parseExecutionId(undefined as unknown as string)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -415,7 +415,7 @@ describe('graphTraversalUtil', () => {
|
||||
|
||||
// Add a title property to each node
|
||||
forEachNode(graph, (node) => {
|
||||
;(node as any).title = `Node ${node.id}`
|
||||
;(node as unknown as { title: string }).title = `Node ${node.id}`
|
||||
})
|
||||
|
||||
expect(nodes[0]).toHaveProperty('title', 'Node 1')
|
||||
@@ -653,7 +653,7 @@ describe('graphTraversalUtil', () => {
|
||||
it('should return root graph from subgraph', () => {
|
||||
const rootGraph = createMockGraph([])
|
||||
const subgraph = createMockSubgraph('sub-uuid', [])
|
||||
;(subgraph as any).rootGraph = rootGraph
|
||||
;(subgraph as Subgraph & { rootGraph: LGraph }).rootGraph = rootGraph
|
||||
|
||||
expect(getRootGraph(subgraph)).toBe(rootGraph)
|
||||
})
|
||||
@@ -663,8 +663,10 @@ describe('graphTraversalUtil', () => {
|
||||
const midSubgraph = createMockSubgraph('mid-uuid', [])
|
||||
const deepSubgraph = createMockSubgraph('deep-uuid', [])
|
||||
|
||||
;(midSubgraph as any).rootGraph = rootGraph
|
||||
;(deepSubgraph as any).rootGraph = midSubgraph
|
||||
;(midSubgraph as Subgraph & { rootGraph: LGraph }).rootGraph = rootGraph
|
||||
;(
|
||||
deepSubgraph as Subgraph & { rootGraph: LGraph | Subgraph }
|
||||
).rootGraph = midSubgraph
|
||||
|
||||
expect(getRootGraph(deepSubgraph)).toBe(rootGraph)
|
||||
})
|
||||
@@ -726,7 +728,7 @@ describe('graphTraversalUtil', () => {
|
||||
const graph = createMockGraph(nodes)
|
||||
|
||||
forEachSubgraphNode(graph, subgraphId, (node) => {
|
||||
;(node as any).title = 'Updated Title'
|
||||
;(node as unknown as { title: string }).title = 'Updated Title'
|
||||
})
|
||||
|
||||
expect(nodes[0]).toHaveProperty('title', 'Updated Title')
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('typeGuardUtil', () => {
|
||||
it('should identify SubgraphInputNode as IO node', () => {
|
||||
const node = {
|
||||
constructor: { comfyClass: 'SubgraphInputNode' }
|
||||
} as any
|
||||
} as unknown as Parameters<typeof isSubgraphIoNode>[0]
|
||||
|
||||
expect(isSubgraphIoNode(node)).toBe(true)
|
||||
})
|
||||
@@ -15,7 +15,7 @@ describe('typeGuardUtil', () => {
|
||||
it('should identify SubgraphOutputNode as IO node', () => {
|
||||
const node = {
|
||||
constructor: { comfyClass: 'SubgraphOutputNode' }
|
||||
} as any
|
||||
} as unknown as Parameters<typeof isSubgraphIoNode>[0]
|
||||
|
||||
expect(isSubgraphIoNode(node)).toBe(true)
|
||||
})
|
||||
@@ -23,13 +23,13 @@ describe('typeGuardUtil', () => {
|
||||
it('should not identify regular nodes as IO nodes', () => {
|
||||
const node = {
|
||||
constructor: { comfyClass: 'CLIPTextEncode' }
|
||||
} as any
|
||||
} as unknown as Parameters<typeof isSubgraphIoNode>[0]
|
||||
|
||||
expect(isSubgraphIoNode(node)).toBe(false)
|
||||
})
|
||||
|
||||
it('should handle nodes without constructor', () => {
|
||||
const node = {} as any
|
||||
const node = {} as unknown as Parameters<typeof isSubgraphIoNode>[0]
|
||||
|
||||
expect(isSubgraphIoNode(node)).toBe(false)
|
||||
})
|
||||
@@ -37,7 +37,7 @@ describe('typeGuardUtil', () => {
|
||||
it('should handle nodes without comfyClass', () => {
|
||||
const node = {
|
||||
constructor: {}
|
||||
} as any
|
||||
} as unknown as Parameters<typeof isSubgraphIoNode>[0]
|
||||
|
||||
expect(isSubgraphIoNode(node)).toBe(false)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user