mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-26 09:44:06 +00:00
CodeRabbit Generated Unit Tests: Add injectionKeys and boundsCalculator unit tests
This commit is contained in:
committed by
GitHub
parent
8b58943229
commit
c4f4a452a0
@@ -349,3 +349,49 @@ describe('useTransformState', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('useTransformState - Non-Shared Behavior', () => {
|
||||
it('should create independent instances for multiple calls', () => {
|
||||
const state1 = useTransformState()
|
||||
const state2 = useTransformState()
|
||||
|
||||
// Modify state1
|
||||
const mockCanvas1 = {
|
||||
ds: { offset: [100, 200], scale: 1.5 }
|
||||
} as any
|
||||
state1.syncWithCanvas(mockCanvas1)
|
||||
|
||||
// Modify state2 differently
|
||||
const mockCanvas2 = {
|
||||
ds: { offset: [300, 400], scale: 0.5 }
|
||||
} as any
|
||||
state2.syncWithCanvas(mockCanvas2)
|
||||
|
||||
// Each instance should have its own camera state
|
||||
expect(state1.camera.x).toBe(100)
|
||||
expect(state1.camera.z).toBe(1.5)
|
||||
expect(state2.camera.x).toBe(300)
|
||||
expect(state2.camera.z).toBe(0.5)
|
||||
})
|
||||
|
||||
it('should handle ArrayLike<number> parameters correctly', () => {
|
||||
const { isNodeInViewport } = useTransformState()
|
||||
|
||||
const viewport = { width: 800, height: 600 }
|
||||
|
||||
// Test with regular arrays
|
||||
const arrayPos: number[] = [100, 200]
|
||||
const arraySize: number[] = [150, 100]
|
||||
expect(() => isNodeInViewport(arrayPos, arraySize, viewport)).not.toThrow()
|
||||
|
||||
// Test with TypedArrays
|
||||
const typedPos = new Float32Array([100, 200])
|
||||
const typedSize = new Float64Array([150, 100])
|
||||
expect(() => isNodeInViewport(typedPos, typedSize, viewport)).not.toThrow()
|
||||
|
||||
// Test with tuples
|
||||
const tuplePos: [number, number] = [100, 200]
|
||||
const tupleSize: [number, number] = [150, 100]
|
||||
expect(() => isNodeInViewport(tuplePos, tupleSize, viewport)).not.toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
59
tests-ui/tests/renderer/core/layout/injectionKeys.test.ts
Normal file
59
tests-ui/tests/renderer/core/layout/injectionKeys.test.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { inject, provide } from 'vue'
|
||||
|
||||
import {
|
||||
TransformStateKey,
|
||||
type TransformState
|
||||
} from '@/renderer/core/layout/injectionKeys'
|
||||
|
||||
describe('injectionKeys', () => {
|
||||
describe('TransformStateKey', () => {
|
||||
it('should be a valid Symbol injection key', () => {
|
||||
expect(TransformStateKey).toBeDefined()
|
||||
expect(typeof TransformStateKey).toBe('symbol')
|
||||
expect(TransformStateKey.toString()).toContain('transformState')
|
||||
})
|
||||
|
||||
it('should work with Vue provide/inject', () => {
|
||||
const mockTransformState: TransformState = {
|
||||
camera: { x: 0, y: 0, z: 1 },
|
||||
screenToCanvas: () => ({ x: 0, y: 0 }),
|
||||
canvasToScreen: () => ({ x: 0, y: 0 }),
|
||||
isNodeInViewport: () => true
|
||||
}
|
||||
|
||||
// Simulate provide
|
||||
provide(TransformStateKey, mockTransformState)
|
||||
|
||||
// Simulate inject
|
||||
const injected = inject(TransformStateKey)
|
||||
expect(injected).toBe(mockTransformState)
|
||||
})
|
||||
|
||||
it('should enforce correct TransformState interface structure', () => {
|
||||
const validState: TransformState = {
|
||||
camera: { x: 10, y: 20, z: 1.5 },
|
||||
screenToCanvas: (point: { x: number; y: number }) => ({
|
||||
x: point.x / 1.5 - 10,
|
||||
y: point.y / 1.5 - 20
|
||||
}),
|
||||
canvasToScreen: (point: { x: number; y: number }) => ({
|
||||
x: (point.x + 10) * 1.5,
|
||||
y: (point.y + 20) * 1.5
|
||||
}),
|
||||
isNodeInViewport: (
|
||||
nodePos: ArrayLike<number>,
|
||||
nodeSize: ArrayLike<number>,
|
||||
viewport: { width: number; height: number },
|
||||
margin?: number
|
||||
) => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Type check - should compile without errors
|
||||
const _check: TransformState = validState
|
||||
expect(_check).toBeDefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,95 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { calculateNodeBounds } from '@/renderer/core/spatial/boundsCalculator'
|
||||
|
||||
describe('boundsCalculator', () => {
|
||||
describe('calculateNodeBounds', () => {
|
||||
it('should calculate bounds for single node', () => {
|
||||
const nodes = [{ pos: [100, 200], size: [150, 100] }]
|
||||
|
||||
const bounds = calculateNodeBounds(nodes)
|
||||
|
||||
expect(bounds).toEqual({
|
||||
minX: 100,
|
||||
minY: 200,
|
||||
maxX: 250,
|
||||
maxY: 300,
|
||||
width: 150,
|
||||
height: 100
|
||||
})
|
||||
})
|
||||
|
||||
it('should calculate bounds for multiple nodes', () => {
|
||||
const nodes = [
|
||||
{ pos: [100, 200], size: [150, 100] },
|
||||
{ pos: [300, 400], size: [200, 150] },
|
||||
{ pos: [50, 100], size: [100, 80] }
|
||||
]
|
||||
|
||||
const bounds = calculateNodeBounds(nodes)
|
||||
|
||||
expect(bounds).toEqual({
|
||||
minX: 50,
|
||||
minY: 100,
|
||||
maxX: 500,
|
||||
maxY: 550,
|
||||
width: 450,
|
||||
height: 450
|
||||
})
|
||||
})
|
||||
|
||||
it('should return null for empty array', () => {
|
||||
const nodes: Array<{ pos: ArrayLike<number>; size: ArrayLike<number> }> =
|
||||
[]
|
||||
|
||||
const bounds = calculateNodeBounds(nodes)
|
||||
|
||||
expect(bounds).toBeNull()
|
||||
})
|
||||
|
||||
it('should handle nodes with negative coordinates', () => {
|
||||
const nodes = [
|
||||
{ pos: [-100, -200], size: [150, 100] },
|
||||
{ pos: [50, 100], size: [100, 80] }
|
||||
]
|
||||
|
||||
const bounds = calculateNodeBounds(nodes)
|
||||
|
||||
expect(bounds).toEqual({
|
||||
minX: -100,
|
||||
minY: -200,
|
||||
maxX: 150,
|
||||
maxY: 180,
|
||||
width: 250,
|
||||
height: 380
|
||||
})
|
||||
})
|
||||
|
||||
it('should accept TypedArray for position and size', () => {
|
||||
const nodes = [
|
||||
{ pos: new Float32Array([100, 200]), size: [150, 100] },
|
||||
{ pos: new Float64Array([300, 400]), size: new Float32Array([200, 150]) }
|
||||
]
|
||||
|
||||
const bounds = calculateNodeBounds(nodes)
|
||||
|
||||
expect(bounds).not.toBeNull()
|
||||
expect(bounds!.minX).toBe(100)
|
||||
expect(bounds!.minY).toBe(200)
|
||||
})
|
||||
|
||||
it('should handle large number of nodes efficiently', () => {
|
||||
const nodes = Array.from({ length: 10000 }, (_, i) => ({
|
||||
pos: [i * 10, i * 10],
|
||||
size: [100, 100]
|
||||
}))
|
||||
|
||||
const start = performance.now()
|
||||
const bounds = calculateNodeBounds(nodes)
|
||||
const end = performance.now()
|
||||
|
||||
expect(bounds).not.toBeNull()
|
||||
expect(end - start).toBeLessThan(100)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -399,3 +399,83 @@ describe('useNodeEventHandlers', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('useNodeEventHandlers - New Batch Operations', () => {
|
||||
describe('selectNodes', () => {
|
||||
it('should select multiple nodes at once', () => {
|
||||
const { selectNodes } = useNodeEventHandlers()
|
||||
|
||||
const mockNodes = [
|
||||
{ id: 'node1', selected: false },
|
||||
{ id: 'node2', selected: false },
|
||||
{ id: 'node3', selected: false }
|
||||
]
|
||||
|
||||
mockNodeManager.value!.getNode = vi.fn((id: string) =>
|
||||
mockNodes.find((n) => n.id === id)
|
||||
) as any
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
canvasStore.canvas!.select = vi.fn()
|
||||
canvasStore.canvas!.deselectAll = vi.fn()
|
||||
|
||||
selectNodes(['node1', 'node2', 'node3'], false)
|
||||
|
||||
expect(canvasStore.canvas!.deselectAll).toHaveBeenCalled()
|
||||
expect(canvasStore.canvas!.select).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
|
||||
it('should skip non-existent nodes', () => {
|
||||
const { selectNodes } = useNodeEventHandlers()
|
||||
|
||||
mockNodeManager.value!.getNode = vi.fn(() => null)
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
canvasStore.canvas!.select = vi.fn()
|
||||
|
||||
selectNodes(['missing-node'], false)
|
||||
|
||||
expect(canvasStore.canvas!.select).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('deselectNodes', () => {
|
||||
it('should deselect multiple nodes', () => {
|
||||
const { deselectNodes } = useNodeEventHandlers()
|
||||
|
||||
const mockNodes = [
|
||||
{ id: 'node1', selected: true },
|
||||
{ id: 'node2', selected: true }
|
||||
]
|
||||
|
||||
mockNodeManager.value!.getNode = vi.fn((id: string) =>
|
||||
mockNodes.find((n) => n.id === id)
|
||||
) as any
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
canvasStore.canvas!.deselect = vi.fn()
|
||||
|
||||
deselectNodes(['node1', 'node2'])
|
||||
|
||||
expect(canvasStore.canvas!.deselect).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('deselectNode', () => {
|
||||
it('should deselect a single node', () => {
|
||||
const { deselectNode } = useNodeEventHandlers()
|
||||
|
||||
const mockNodeToDeselect = { id: 'test-node', selected: true }
|
||||
mockNodeManager.value!.getNode = vi.fn(() => mockNodeToDeselect as any)
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
canvasStore.canvas!.deselect = vi.fn()
|
||||
|
||||
deselectNode('test-node')
|
||||
|
||||
expect(canvasStore.canvas!.deselect).toHaveBeenCalledWith(
|
||||
mockNodeToDeselect
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user