mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 22:09:37 +00:00
test: add unit tests for subgraph IO slot link events
- SubgraphInput.connect() fires node:slot-links:changed for widget inputs - SubgraphInputNode._disconnectNodeInput() fires on disconnect - LinkConnector.dropOnNothing() dispatches before-drop-on-canvas before dropped-on-canvas, and skips downstream when intercepted - Remove duplicate raf.flush() in finishInteraction
This commit is contained in:
committed by
Christian Byrne
parent
0d657402e7
commit
180fed69d8
87
src/lib/litegraph/src/canvas/LinkConnectorDropEvents.test.ts
Normal file
87
src/lib/litegraph/src/canvas/LinkConnectorDropEvents.test.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest'
|
||||
|
||||
import { LinkConnector } from '@/lib/litegraph/src/litegraph'
|
||||
import {
|
||||
createMockCanvasPointerEvent,
|
||||
createMockLGraphNode,
|
||||
createMockLinkNetwork,
|
||||
createMockNodeOutputSlot
|
||||
} from '@/utils/__tests__/litegraphTestUtils'
|
||||
|
||||
const mockSetConnectingLinks = vi.fn()
|
||||
|
||||
type RenderLinkItem = LinkConnector['renderLinks'][number]
|
||||
|
||||
function createMockRenderLink(): RenderLinkItem {
|
||||
const partial: Partial<RenderLinkItem> = {
|
||||
toType: 'input',
|
||||
fromPos: [0, 0],
|
||||
fromSlotIndex: 0,
|
||||
fromDirection: 0,
|
||||
network: createMockLinkNetwork(),
|
||||
node: createMockLGraphNode(),
|
||||
fromSlot: createMockNodeOutputSlot(),
|
||||
dragDirection: 0,
|
||||
canConnectToInput: vi.fn().mockReturnValue(false),
|
||||
canConnectToOutput: vi.fn().mockReturnValue(false),
|
||||
canConnectToReroute: vi.fn().mockReturnValue(false),
|
||||
connectToInput: vi.fn(),
|
||||
connectToOutput: vi.fn(),
|
||||
connectToSubgraphInput: vi.fn(),
|
||||
connectToRerouteOutput: vi.fn(),
|
||||
connectToSubgraphOutput: vi.fn(),
|
||||
connectToRerouteInput: vi.fn()
|
||||
}
|
||||
return partial as RenderLinkItem
|
||||
}
|
||||
|
||||
describe('LinkConnector.dropOnNothing event dispatch', () => {
|
||||
let connector: LinkConnector
|
||||
|
||||
beforeEach(() => {
|
||||
connector = new LinkConnector(mockSetConnectingLinks)
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
test('dispatches before-drop-on-canvas before dropped-on-canvas', () => {
|
||||
connector.renderLinks.push(createMockRenderLink())
|
||||
|
||||
const callOrder: string[] = []
|
||||
connector.events.addEventListener('before-drop-on-canvas', () => {
|
||||
callOrder.push('before-drop-on-canvas')
|
||||
})
|
||||
connector.events.addEventListener('dropped-on-canvas', () => {
|
||||
callOrder.push('dropped-on-canvas')
|
||||
})
|
||||
|
||||
connector.dropOnNothing(createMockCanvasPointerEvent(100, 100))
|
||||
|
||||
expect(callOrder).toEqual(['before-drop-on-canvas', 'dropped-on-canvas'])
|
||||
})
|
||||
|
||||
test('skips dropped-on-canvas when before-drop-on-canvas is intercepted', () => {
|
||||
connector.renderLinks.push(createMockRenderLink())
|
||||
|
||||
const droppedListener = vi.fn()
|
||||
connector.events.addEventListener('before-drop-on-canvas', (e) => {
|
||||
e.preventDefault()
|
||||
})
|
||||
connector.events.addEventListener('dropped-on-canvas', droppedListener)
|
||||
|
||||
connector.dropOnNothing(createMockCanvasPointerEvent(100, 100))
|
||||
|
||||
expect(droppedListener).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('does not dispatch events when renderLinks is empty', () => {
|
||||
const beforeListener = vi.fn()
|
||||
const droppedListener = vi.fn()
|
||||
connector.events.addEventListener('before-drop-on-canvas', beforeListener)
|
||||
connector.events.addEventListener('dropped-on-canvas', droppedListener)
|
||||
|
||||
connector.dropOnNothing(createMockCanvasPointerEvent(100, 100))
|
||||
|
||||
expect(beforeListener).not.toHaveBeenCalled()
|
||||
expect(droppedListener).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
102
src/lib/litegraph/src/subgraph/SubgraphIOSlotLinks.test.ts
Normal file
102
src/lib/litegraph/src/subgraph/SubgraphIOSlotLinks.test.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { describe, expect, vi } from 'vitest'
|
||||
|
||||
import { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import { NodeSlotType } from '@/lib/litegraph/src/types/globalEnums'
|
||||
|
||||
import { subgraphTest } from './__fixtures__/subgraphFixtures'
|
||||
|
||||
describe('SubgraphInput.connect triggers node:slot-links:changed', () => {
|
||||
subgraphTest(
|
||||
'fires connected event when connecting to a widget input',
|
||||
({ simpleSubgraph }) => {
|
||||
const subgraph = simpleSubgraph
|
||||
const triggerSpy = vi.spyOn(subgraph, 'trigger')
|
||||
|
||||
const node = new LGraphNode('Target')
|
||||
node.addInput('prompt', 'STRING')
|
||||
node.inputs[0].widget = { name: 'prompt' }
|
||||
subgraph.add(node)
|
||||
|
||||
subgraph.inputNode.slots[0].connect(node.inputs[0], node)
|
||||
|
||||
expect(triggerSpy).toHaveBeenCalledWith('node:slot-links:changed', {
|
||||
nodeId: node.id,
|
||||
slotType: NodeSlotType.INPUT,
|
||||
slotIndex: 0,
|
||||
connected: true,
|
||||
linkId: expect.any(Number)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
subgraphTest(
|
||||
'does not fire event when connecting to a non-widget input',
|
||||
({ simpleSubgraph }) => {
|
||||
const subgraph = simpleSubgraph
|
||||
const triggerSpy = vi.spyOn(subgraph, 'trigger')
|
||||
|
||||
const node = new LGraphNode('Target')
|
||||
node.addInput('in', 'number')
|
||||
subgraph.add(node)
|
||||
|
||||
subgraph.inputNode.slots[0].connect(node.inputs[0], node)
|
||||
|
||||
expect(triggerSpy).not.toHaveBeenCalledWith(
|
||||
'node:slot-links:changed',
|
||||
expect.anything()
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
describe('SubgraphInputNode._disconnectNodeInput triggers node:slot-links:changed', () => {
|
||||
subgraphTest(
|
||||
'fires disconnected event when disconnecting a widget input',
|
||||
({ simpleSubgraph }) => {
|
||||
const subgraph = simpleSubgraph
|
||||
|
||||
const node = new LGraphNode('Target')
|
||||
node.addInput('prompt', 'STRING')
|
||||
node.inputs[0].widget = { name: 'prompt' }
|
||||
subgraph.add(node)
|
||||
|
||||
const link = subgraph.inputNode.slots[0].connect(node.inputs[0], node)
|
||||
expect(link).toBeDefined()
|
||||
|
||||
const triggerSpy = vi.spyOn(subgraph, 'trigger')
|
||||
|
||||
subgraph.inputNode._disconnectNodeInput(node, node.inputs[0], link!)
|
||||
|
||||
expect(triggerSpy).toHaveBeenCalledWith('node:slot-links:changed', {
|
||||
nodeId: node.id,
|
||||
slotType: NodeSlotType.INPUT,
|
||||
slotIndex: 0,
|
||||
connected: false,
|
||||
linkId: link!.id
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
subgraphTest(
|
||||
'does not fire event when disconnecting a non-widget input',
|
||||
({ simpleSubgraph }) => {
|
||||
const subgraph = simpleSubgraph
|
||||
|
||||
const node = new LGraphNode('Target')
|
||||
node.addInput('in', 'number')
|
||||
subgraph.add(node)
|
||||
|
||||
const link = subgraph.inputNode.slots[0].connect(node.inputs[0], node)
|
||||
expect(link).toBeDefined()
|
||||
|
||||
const triggerSpy = vi.spyOn(subgraph, 'trigger')
|
||||
|
||||
subgraph.inputNode._disconnectNodeInput(node, node.inputs[0], link!)
|
||||
|
||||
expect(triggerSpy).not.toHaveBeenCalledWith(
|
||||
'node:slot-links:changed',
|
||||
expect.anything()
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
@@ -544,8 +544,6 @@ export function useSlotLinkInteraction({
|
||||
|
||||
raf.flush()
|
||||
|
||||
raf.flush()
|
||||
|
||||
if (!state.source) {
|
||||
cleanupInteraction()
|
||||
app.canvas?.setDirty(true, true)
|
||||
|
||||
Reference in New Issue
Block a user